Peg.JS: простая реализация if..then..else

Я пытаюсь реализовать грамматику для простого оператора if..then..else вместе с простыми операторами.

Он должен иметь возможность анализировать оператор вроде:

if things are going fine
then
    things are supposed to be this way
    just go with it
else
    nothing new
How are you?

Документ начинается с решения (если... то... иначе) и сопровождается простым утверждением.

Моя грамматика пока выглядит так:

document = decision / simple_statement / !.

decision = i:if t:then e:(else)? document { return { if: { cond: i }, then: t, else: e } }

if = 'if' s:statement nl { return s }
then = 'then' nl actions:indented_statements+ { return actions }
else = 'else' nl actions:indented_statements+ { return actions }
indented_statements = ss:(tab statement nl)+ { return ss.reduce(function(st, el) { return st.concat(el) }, []) }
statement = text:$(char+) { return text.trim() }

simple_statement = s:statement nl document { return { action: s } }

char = [^\n\r]
ws = [ \t]*
tab = [\t]+ { return '' }
nl = [\r\n]+

Это возвращает вывод:

{
   "if": {
      "cond": "things are going fine"
   },
   "then": [
      [
         "",
         "things are supposed to be this way",
         [
            "
"
         ],
         "",
         "just go with it",
         [
            "
"
         ]
      ]
   ],
   "else": [
      [
         "",
         "nothing new",
         [
            "
"
         ]
      ]
   ]
}

<удар>1. Почему в массиве then и else есть лишние пустые строки и массивы? Что я должен сделать, чтобы удалить их?

  1. Почему моя грамматика не читает простые утверждения после решения? Что мне сделать, чтобы он прочитал и проанализировал весь документ?

EDIT: я думаю, что понял, почему я получаю массивы. Я изменил грамматику, чтобы убрать повторы внутри indented_statements.

document = decision / simple_statement / !.

decision = i:if t:then e:(else)? document { return { if: i, then: t, else: e } }

if = 'if' s:statement nl { return s }
then = 'then' nl actions:indented_statements+ { return actions }
else = 'else' nl actions:indented_statements+ { return actions }
indented_statements = tab s:statement nl { return s }
statement = text:$(char+) { return text.trim() }

simple_statement = s:statement nl document { return { action: s } }

char = [^\n\r]
ws = [ \t]*
tab = [\t]+ { return '' }
nl = [\r\n]+


person funkycoder    schedule 29.12.2020    source источник


Ответы (1)


Я понял ответ. Мне нужно было предоставить первое утверждение как повторяющееся:

document = (decision / simple_statement)*

person funkycoder    schedule 29.12.2020