Однозначная грамматика для арифметических выражений без лишних скобок - PullRequest
0 голосов
/ 08 января 2011

Я ищу однозначную грамматику для арифметических выражений без лишних скобок. Например, скобки избыточны в id+(id*id), но не в (id+id)*id.

Ответы [ 2 ]

4 голосов
/ 20 февраля 2013

Вы можете легко это сделать. Единственный момент, когда скобки становятся необходимыми, это когда выражение суммы в качестве одного из фрагментов выражения умножения или некоторое выражение в качестве второго фрагмента одного из выражений деления. В любом из этих случаев вы можете убедиться, что круглые скобки не являются избыточными, принудительно заставляя материал внутри скобок иметь хотя бы один пустой оператор (не окруженный дополнительными скобками).

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

Вы хотите разобрать выражение как таковое:

expr      ::= expr addsub term
expr      ::= prodterm
expr      ::= value

sum       ::= expr addsub term

addsub    ::= '+' | '-'

term      ::= prodterm
term      ::= unit

prodterm  ::= term '*' unit
prodterm  ::= term '/' produnit

unit      ::= '(' sum ')'
unit      ::= value

produnit  ::= unit
produnit  ::= '(' prodterm ')'

value     ::= '0-9'*

У одиночного значения никогда не должно быть круглых скобок. Единицы - это подвыражения выражений умножения; produnits учитывают заключенные в скобки хвосты к вашим выражениям деления. (5) будет (значение), что невозможно, потому что скобки есть только у единиц измерения и единиц, и они требуют, чтобы в скобках присутствовал некоторый арифметический оператор, если они присутствуют. (значение) не может быть получено из какого-либо выражения, и ((что-либо)) невозможно, потому что только produnit и unit выводят скобки. Если присмотреться, produnit требует наличия * или /, если он выводится из круглых скобок, или для его анализа в виде единицы, или значения без скобок. единица требует + или - для появления или без скобок.

((5 + 6)) терпит неудачу, потому что (5 + 6) может анализировать только как единое целое, что может сделать его продуктом, но нет способа поместить скобки вокруг одинокого продукта - нет цепочки, которая превращает единица или продукт в скобках вокруг одинокого продукта.

Я остановлю свой выбор за вами: 5 * (6 * 7) не анализирует - вы бы подумали, что это термин, умноженный на единицу, но тогда (6 * 7) не единица, потому что единицы имеют быть значениями или круглыми скобками вокруг выражений хотя бы с одной суммой. Когда происходит хотя бы одна сумма, скобки не являются тривиальными. С другой стороны, 5 / (6 * 7) совсем не то же самое, что 5/6 * 7 - первое похоже на 5/6/7, а второе - на 5 * 7/6. Однако 5 / (6) - это то же самое, что и 5/6 - одиночные значения не могут встречаться в скобках. Аналогично, 5 / (6/7) - это не то же самое, что 5/6/7, потому что первое совпадает с 5 * 7/6, а второе - с 5 / (6 * 7). Другими словами, круглые скобки вокруг знаменателя никогда не бывают посторонними, если внутри есть простой оператор.

(5 + 6) +7 также невозможно, потому что левая часть (и правая часть) суммы являются либо строгими значениями, суммами без скобок вокруг суммы или продуктами без скобок вокруг продукта. Там нет способа повернуть

Вы можете убедить себя, что это верно, и убедиться, что это однозначно. Вы можете продемонстрировать себе, что это верно, расширив его, включив в него оператор возведения в степень, или даже лучше обобщить его на операторы с более высоким приоритетом или операторы с более низким приоритетом, такие как == или <. </p>

Надеюсь, это поможет!

2 голосов
/ 08 января 2011

Это зависит от того, что именно вы подразумеваете под «для арифметических выражений без лишних скобок». Это примет выражения без лишних скобок, но также примет произвольно вложенные скобки:

expr   ::= factor
expr   ::= factor mul_div factor

mul_div ::= '*' | '/'

factor ::= term
factor ::= term add_sub term

add_sub ::= '+' | '-'

term   ::= NUMBER
term   ::= '(' expr ')'

Я предполагаю, что NUMBER удастся распознать подписанные числа, поэтому здесь нет унарного плюса или минуса. Вы можете решить, как обращаться с ними, если они вам нужны. Вы также можете добавить переменные и т. Д., Если они вам нужны.

Если вы имеете в виду грамматику, которая отклоняет выражения с ненужными скобками, то я думаю, что вы ищете что-то, что не является контекстно-свободной грамматикой.

...