Использование Jison для преобразования списка команд в массив объектов

Я пытаюсь использовать Jison, который является JS-портом Bison, генератором парсера. Моя цель - преобразовать этот вход:

foo(10)
bar()
foo(28)
baz(28)

в это:

[
  { func: 'foo', arg: 10 },
  { func: 'bar' },
  { func: 'foo', arg: 28 },
  { func: 'baz', arg: 28 }
]

Вот мой файл зубров:

%lex

%%
[0-9]+\b                  return 'INTEGER'
\(                        return 'OPEN_PAREN'
\)                        return 'CLOSE_PAREN'
[\w]+\s*(?=\()            return 'FUNC_NAME'
\n+                       return 'LINE_END'

/lex

%%
expressions
  : expressions expression
  | expression
  ;

expression
  : LINE_END
  | e LINE_END
    {return $1}
  ;

e
  : FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
    {$$ = { func: $1, arg: $3 };}

  | FUNC_NAME OPEN_PAREN CLOSE_PAREN
    {$$ = { func: $1 };}
  ;

Вывод полученного сгенерированного парсера { func: 'foo', arg: 10 }, Другими словами, он возвращает только проанализированный объект из первого оператора и игнорирует остальные.

Я знаю, что моя проблема связана с семантической ценностью и "правой стороной" expression, но я довольно потерян в противном случае.

Любая помощь будет чрезвычайно ценится!

1 ответ

Решение

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

  1. LINE_END имеет регулярное выражение \n+|$ также соответствовать концу вывода.

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

  3. Переписал expression производство для производства массивов. Я также удалил {return $1} от e LINE_END правило, так как это привело к преждевременному возвращению синтаксического анализатора.

  4. Модифицированный expressions производство для объединения массивов.

Для expression а также expressions там я использовал сокращенный синтаксис для правил. Например expression -> [$1] эквивалентно expression { $$ = [$1] },

Вот грамматика:

%lex

%%
[0-9]+\b                  return 'INTEGER'
\(                        return 'OPEN_PAREN'
\)                        return 'CLOSE_PAREN'
[\w]+\s*(?=\()            return 'FUNC_NAME'
\n+|$                     return 'LINE_END'

/lex

%%
start:
  expressions
  { return $1 }
  ;

expressions
  : expressions expression -> $1.concat($2)
  | expression
  ;

expression
  : LINE_END -> []
  | e LINE_END -> [$1]
  ;

e 
  : FUNC_NAME OPEN_PAREN INTEGER CLOSE_PAREN
    {$$ = { func: $1, arg: $3 };}

  | FUNC_NAME OPEN_PAREN CLOSE_PAREN
    {$$ = { func: $1 };}
  ;

В сторону: Jison не порт Бизона. Это генератор парсеров, чье функционирование сильно вдохновлено Bison, но у него есть функции, которых у Bison нет, и есть некоторые функции Bison, которые Jison не поддерживает.

Другие вопросы по тегам