2

В моей грамматике существуют правила производства выражений и фрагментов, которые первоначально содержали косвенную левую рекурсию. Это правила после того, как я удалил рекурсию из них.Javacc Недостижимое заявление

String expression() #Expression : {String number; Token t;} 
{ 
    number = fragment() 
    (
     (t = <Mult_Sign> number = fragment()) 
    ) 
    {return number;} 
} 

String fragment() #void : {String t;} 
{ 
    t = identifier() {return t;} 
    | t = number() {return t;} 
    | (<PLUS> | <MINUS>) fragment() 
    | <LBR> expression() <RBR> 
} 

Эти правила производства используются при попытке проанализировать условие в грамматике. Однако упорядочение правил производства либо имеет так, что принимается только выражение. Тем не менее он должен принимать что-то вроде while (x < = 10). Если у меня есть правила производства в противоположном порядке, как первоначально указано в грамматике. Когда я пытаюсь скомпилировать java-файл с помощью javac. Я получаю сообщение об ошибке, которое говорит мне, что идентификатор() является недостижимым. Это условие правила производства:

void condition() #void : {Token t;} 
{ 
    <NOT> expression() 
    | expression (<EQUALS>|<NOTEQUALS>|<LT>|<GT>|<LTE>|<GTE>|<AND>|<OR>) expression() 
    | identifier() 
} 

Если кто-то может помочь мне сказать, почему эта проблема возникает, было бы очень полезно.

ответ

5

Вы

void condition() #void : {Token t;} 
{ 
/*a*/  <NOT> expression() 
/*b*/  | expression (<EQUALS>|<NOTEQUALS>|<LT>|<GT>|<LTE>|<GTE>|<AND>|<OR>) expression() 
/*c*/  | identifier() 
} 

Если анализатор ищет состояние, он будет пытаться сделать выбор между тремя альтернативами на основе следующих маркеров ввода. Если этот токен является идентификатором, возникает проблема, так как любая альтернатива (b) или альтернатива (c) может работать. Столкнувшись с конфликтом выбора, JavaCC предпочитает первый, поэтому (б) будет выбран. И если следующий токен не является идентификатором, тогда альтернатива (c) не будет выбрана. Поэтому в любом случае альтернатива (с) не будет достигнута.


Это ваша проблема. Что нужно сделать по этому поводу? Это обычное решение.

Если вы хотите разрешить дальнейшие операторы в выражениях, сделайте больше нетерминалов, представляющих больше уровней приоритета. Например,

condition --> expression 
expression --> disjunct (OR expression)? 
disjunct --> conjunct (AND disjunct)? 
conjunct --> comparand ((EQ|NEQ|LT|GT|LE|GE) comparand)? 
comparand --> term ((PLUS|MINUS) term)* 
term --> fragment ((TIMES | DIVIDE) fragment)* 
fragment --> identifier | number | LBR expression RBR | (PLUS|MINUS|NOT) fragment 

Эта грамматика примет все, что захочет и, возможно, больше. Например, если у вас есть

statement --> WHILE condition DO statement 

Ваш парсер примет, например. "WHILE a + b DO a: = b". На многих языках это проверяется по типу; Java делает это так. На других языках это разрешается, разрешая всевозможные вещи как условия; LISP делает это.


Замечание о приоритете NOT

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

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

fragment --> identifier | number | LBR expression RBR | (PLUS|MINUS) fragment | NOT conjunct 

Теперь грамматика не LL (1) (это даже не однозначно). Таким образом, JavaCC предоставит некоторые предупреждения о конфликте выбора. Но он фактически будет разбирать, например.«НЕ LT б», как «NOT (ЛТ б)»


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

Начните с грамматики, как этот. (Это, по существу, ваша идея с большим вниманием к уровням приоритета.)

condition --> disjunct (OR condition)? 
disjunct --> conjunct (AND disjunct)? 
conjunct --> expression (EQ|NEQ|LT|GT|LE|GE) expression 
      | LBR condition RBR 
      | NOT conjunct 
      | identifier 

expression --> term ((PLUS|MINUS) term)* 
term --> fragment ((TIMES | DIVIDE) fragment)* 
fragment --> identifier | number | LBR expression RBR | (PLUS|MINUS) fragment 

Это однозначная грамматика для условий. Однако у него есть конфликт выбора при соединении, когда следующий токен является идентификатором или LBR. Для того, чтобы решить этот выбор конфликта вы смотрите вперед для оператора сравнения, используя синтаксический предпросмотр таким образом

void conjunct() : { } { 
    LOOKAHEAD(expression() (<EQ>|<NEQ>|<LT>|<GT>|<LE>|<GE>)) 
    expression() (<EQ>|<NEQ>|<LT>|<GT>|<LE>|<GE>) expression() 
| LBR condition() RBR 
| NOT conjunct() 
| identifier() { 

Так почему же (почти) не язык программирования сделать это таким образом? Большинство языков имеют переменные типа boolean и поэтому, как и вы, разрешают идентификаторы как условия. Поэтому вам все равно придется выполнять проверку типов, чтобы исключить «WHILE i DO ...», где «i» не имеет логического типа. Кроме того, что вы должны использовать для синтаксиса назначения? Вам нужно

statement --> identifier := (expression | condition) | ... 

Даже синтаксический просмотр не укажет, какой выбор подходит для «x: = y». Это двусмысленная грамматика.

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

void statement() : {} { 
    identifier <BECOMES> (LOOKAHEAD(condition()) condition()) | expression()) 
| ... 
} 

Это будет анализировать «y» в «x: = y» как условие, даже если оно числовое. Если вы знаете об этом и разрабатываете остальную часть компилятора, чтобы все работало, никакого вреда не было.

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

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

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