6

Я пытаюсь изучить основы , но я быстро застрял.Решение конфликтов разбора в крошечной грамматике Lemon

Вот маленькая грамматика:

%right PLUS_PLUS. 
%left DOT. 

program ::= expr. 

member_expr ::= expr DOT IDENTIFIER. 

lhs_expr ::= member_expr. 

expr ::= lhs_expr. 
expr ::= PLUS_PLUS lhs_expr. 

Это вызывает 1 разбор конфликта:

State 3: 
     (3) expr ::= lhs_expr * 
     (4) expr ::= PLUS_PLUS lhs_expr * 

          DOT reduce  3  expr ::= lhs_expr 
          DOT reduce  4  ** Parsing conflict ** 
        {default} reduce  4  expr ::= PLUS_PLUS lhs_expr 

В то время как, если я перепишем последнее правило следующим образом:

expr ::= PLUS_PLUS expr DOT IDENTIFIER. 

Затем он вызывает конфликтов нет. Но я не думаю, что это правильный путь.

Буду признателен, если кто-нибудь сможет объяснить, что именно, и почему.

+0

Предлагаю вам подумать об этом без дополнительных имен для вещей. Всюду, где у вас есть 'lhs_expr', вы можете просто написать' expr DOT IDENTIFIER', чтобы четко видеть, что действительно задают. Если все в терминах «expr», вы можете видеть конфликт более четко. –

+0

Вещь, 'lhs_expr' может быть чем-то иным, чем' expr DOT IDENTIFIER'. Эта конкретная грамматика не содержит других правил для нее, потому что я хотел, чтобы она была очень минимальной, но она также может быть, например, 'IDENTIFIER' или' expr LBRACKET expr RBRACKET' и т. Д. И я хочу написать правило 'PLUS_PLUS lhs_expr' только один раз и покрыть все возможные левые выражения, предварительно предваряемые. –

ответ

5

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

++ x . y 

с двумя интерпретациями:

[++ x ] . y 

и

++ [x . y] 

где [] являются только мой путь для отображения групп.

Лимон является парсером L (AL) R, и такие синтаксические анализаторы просто не обрабатывают двусмысленности (множественные интерпретации). Сообщается о конфликте с уменьшением-уменьшением, что происходит, когда парсер достигает этой средней точки; он группирует «++ x» как «[++ x]». или как "++ [x.]"? Оба варианта действительны, и они не могут безопасно выбирать.

Если вы придерживаетесь лимона (или другого генератора парсеров LALR), вы должны избавиться от проблемы, изменив грамматику. Вы можете использовать генератор парсера GLR; он согласился бы и дал бы вам оба анализа. Но все, что вы сделали тогда, - это толкать проблему разрешения двусмысленности на фразу после парсинга. Поскольку вы не хотите двусмысленности, вы можете избежать этого во время разбора, если сможете. В этом случае я думаю, что вы можете.]

Я думаю, вы пытаетесь построить C-подобный язык. Итак, вы хотите что-то вроде этого:

primitive_target ::= IDENTIFIER ; 
primitive_target ::= IDENTIFIER '[' expr ']' ; 
access_path ::= primitive_target ; 
access_path ::= access_path '.' primitive_target ; 

lhs ::= access_path ; 
lhs ::= PLUS_PLUS access_path ; 
lhs ::= access_path PLUS_PLUS ; 

program ::= expr ; 

expr ::= term ; 
expr ::= expr '+' term ; 
term :::= '(' expr ')' ; 
term ::= lhs ; 
term ::= lhs '=' expr ; 
term ::= constant ; 
+0

Спасибо за ответ. Но не должно быть двусмысленности '++ x. y' решаются приоритетами «PLUS_PLUS» и «DOT»? Учитывая мою грамматику, 'DOT' имеет более высокий приоритет (потому что он появляется после' PLUS_PLUS'). –

+0

Я не знаю ANTLR% right и% left declarations. То, что вы в основном хотите, это то, что заставляет сдвиг, когда вы сталкиваетесь с точкой с левым контекстом, содержащим ++. Мне непонятно, что% right и% оставили силу смещения; my * guess * - это принудительная ассоциативность для двоичных операторов, но PLUS_PLUS не является двоичным оператором, поэтому может быть бессмысленным.Мое лечение состояло в том, чтобы избежать этих специальных деклараций и заставить грамматику делать то, что я (ну, вы) хотел напрямую. –

+0

Это не АНТЛР, а Лимон. В любом случае, большое вам спасибо! –

 Смежные вопросы

  • Нет связанных вопросов^_^