Files
freeCodeCamp/curriculum/challenges/chinese/10-coding-interview-prep/rosetta-code/s-expressions.md
2022-10-18 12:59:49 +05:30

2.8 KiB

id, title, challengeType, forumTopicId, dashedName
id title challengeType forumTopicId dashedName
59667989bf71cf555dd5d2ff S-表达式 1 302303 s-expressions

--description--

S-Expressions are one convenient way to parse and store data.

--instructions--

Write a simple reader/parser for S-Expressions that handles quoted and unquoted strings, integers and floats.

The function should read a single but nested S-Expression from a string and return it as a (nested) array.

Newlines and other whitespace may be ignored unless contained within a quoted string.

"()" inside quoted strings are not interpreted, but treated as part of the string.

Handling escaped quotes inside a string is optional; thus "(foo"bar)" may be treated as a string "foo"bar", or as an error.

For this, the reader need not recognize \ for escaping, but should, in addition, recognize numbers if the language has appropriate data types.

Note that with the exception of ()" (\ if escaping is supported) and whitespace, there are no special characters. 其他任何内容都是允许的,不带引号。

读者应该能够阅读以下输入

((data "quoted data" 123 4.5)
(data (!@# (4.5) "(more" "data)")))

and turn it into a native data structure.

--hints--

parseSexpr 是一个函数。

assert(typeof parseSexpr === 'function');

parseSexpr('(data1 data2 data3)') 应该返回 ['data1', 'data2', 'data3']

assert.deepEqual(parseSexpr(simpleSExpr), simpleSolution);

parseSexpr('((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))') should return [['data', '"quoted data"', 123, 4.5], ['data', ['!@#', [4.5], '"(more"', '"data)"']]].

assert.deepEqual(parseSexpr(basicSExpr), basicSolution);

--seed--

--after-user-code--

const simpleSExpr = '(data1 data2 data3)';
const simpleSolution = ['data1', 'data2', 'data3'];

const basicSExpr = '((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))';
const basicSolution = [["data","\"quoted data\"",123,4.5],["data",["!@#",[4.5],"\"(more\"","\"data)\""]]];

--seed-contents--

function parseSexpr(str) {

  return true;
}

--solutions--

function parseSexpr(str) {
  const t = str.match(/\s*("[^"]*"|\(|\)|"|[^\s()"]+)/g);
  for (var o, c = 0, i = t.length - 1; i >= 0; i--) {
    var n,
      ti = t[i].trim();
    if (ti == '"') return;
    else if (ti == '(') t[i] = '[', c += 1;
    else if (ti == ')') t[i] = ']', c -= 1;
    else if ((n = +ti) == ti) t[i] = n;
    else t[i] = `'${ti.replace('\'', '\\\'')}'`;
    if (i > 0 && ti != ']' && t[i - 1].trim() != '(') t.splice(i, 0, ',');
    if (!c) if (!o) o = true; else return;
  }
  return c ? undefined : eval(t.join(''));
}