Ply пример калькулятора нескольких выражений

Я пробовал пример калькулятора Ply из Github.

Когда я запускаю калькулятор, он работает внутри REPL. Как бы я использовал Ply, чтобы можно было оценивать несколько выражений одно за другим.

Например, если я ввожу 3+4, REPL делает следующее:

calc > 3+4
7
calc >

Если я ввожу 4+3 6+2, REPL делает следующее:

calc > 4+3 6+2
Syntax error at '6'
2
calc >  

Как бы я изменил пример калькулятора, чтобы REPL мог это сделать:

calc > 4+3 6+2
7
8
calc > 

Нужно ли мне модифицировать грамматику, синтаксический анализатор или и то, и другое? Я попытался изменить грамматику, чтобы сделать ее рекурсивной, но, похоже, это не сработало.


person Francis    schedule 23.08.2016    source источник
comment
Так как образец грамматики уже является леворекурсивным, ваше утверждение о том, что вы пытались изменить его, чтобы сделать его леворекурсивным, требует некоторого разъяснения. (И почему вы думаете, что это будет иметь значение?)   -  person rici    schedule 23.08.2016
comment
Слишком широко: вы по сути нашли стороннюю библиотеку и спрашиваете, как модифицировать ее для своих целей, что не лучше, чем написать этот код для меня.   -  person Two-Bit Alchemist    schedule 24.08.2016
comment
@Two-BitAlchemist Честно говоря, нет. Я пытаюсь написать простой интерпретатор с использованием Ply, и мой интерпретатор в настоящее время может оценивать только одно выражение/оператор за раз. Я не хотел публиковать свой интерпретатор, так как он значительно длиннее примера калькулятора. Я выбрал образец калькулятора, потому что он имеет то же ограничение, которое я пытаюсь выяснить, и он намного меньше.   -  person Francis    schedule 24.08.2016


Ответы (1)


Грамматика примера калькулятора допускает такие выражения, как - 42 (или -(4*8)+7). Если бы такое выражение было вторым выражением в строке, это создало бы двусмысленность. Является:

calc > 4 * 3 -(4*8)+7

одно выражение или два?

Один из способов сделать грамматику однозначной — разрешить несколько выражений в строке, разделенных запятой. Вы можете сделать это, просто добавив '.' в список литеральных токенов и поместив функцию

def p_line(p):
    '''line : statement
            | line ',' statement'''
    pass

в качестве первой функции парсера (т. е. непосредственно перед p_statement_assign.

С этим изменением:

$ python calc.py
Generating LALR tables
calc > 2+3
5
calc > 2+3,4+6
5
10
calc > 2,3
2
3
calc > a=2,a+7
9
person rici    schedule 23.08.2016
comment
Спасибо! Это именно то, что я искал! Я никогда даже не знал, что в грамматике может быть строка без действия синтаксического анализатора. - person Francis; 24.08.2016
comment
pass — это действие. Просто очень ленивая. - person rici; 24.08.2016