Почему у меня есть сдвиг уменьшить / конфликт на ')', а не '('? - PullRequest
2 голосов
/ 02 декабря 2009

У меня есть синтаксис вроде

%(var)

и

%var

и (Вар)

Мои правила похожи на

optExpr:
    | '%''('CommaLoop')'
    | '%' CommaLoop

CommaLoop:
    val | CommaLoop',' val

Expr:
    MoreRules
    | '(' val ')'

Проблема в том, что он, кажется, не в состоянии определить, принадлежит ли) %(CommaLoop) или % (val), но он жалуется на) вместо (. Какого черта? Разве он не должен жаловаться на (? Должен ли я исправить ошибку? Думаю, сделать %( токен - хорошее решение, но я хочу быть уверен, почему $( не является ошибкой, прежде чем делать это.

Ответы [ 2 ]

3 голосов
/ 08 декабря 2009

Это связано с тем, как работает разбор LR. Синтаксический анализ LR фактически выполняется снизу вверх, группируя токены в соответствии с RHS ваших правил грамматики и заменяя их LHS. Когда анализатор «сдвигается», он помещает токен в стек, но на самом деле еще не соответствует правилу. Вместо этого он отслеживает частично совпадающие правила через текущее состояние. Когда он попадает в состояние, которое соответствует концу правила, он может уменьшаться, выталкивая символы для RHS из стека и отталкивая один символ, обозначающий LHS. Поэтому, если есть конфликты, они не отображаются до тех пор, пока синтаксический анализатор не достигнет какого-либо правила, и не сможет решить, уменьшать (или уменьшать).

В вашем примере, после просмотра % ( val , это то, что будет в стеке (вершина находится на правая сторона здесь). Когда предвидение ) , он не может решить, должен ли он вытолкнуть val и уменьшить с помощью правила CommaLoop: val , или он должен сдвинуть ) , поэтому он может вытолкнуть 3 вещи и уменьшить с помощью правила Expr: '(' val ')'

Здесь я предполагаю, что у вас есть некоторые дополнительные правила, такие как CommaLoop: Expr , иначе ваша грамматика на самом деле ничего не соответствует и bison / yacc будет жаловаться на неиспользуемые нетерминалы.

0 голосов
/ 02 декабря 2009

Прямо сейчас ваше объяснение и ваша грамматика не совпадают. В своем объяснении вы показываете все три фразы как имеющие «var», но ваша грамматика показывает, что те, которые начинаются с «%», разрешают разделенный запятыми список, в то время как одна без позволяет использовать только один «val».

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

optExpr: '%' aList

aList: CommaLoop
    | parenList

parenList: '(' CommaLoop ')'

CommaLoop: 
    | val 
    | CommaLoop ',' val

Expr: MoreRules
    | parenList

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

...