2015-10-19 13 views
1

Грамматика, в крайнем случае, выглядит следующим образом:JavaCC»LOOKAHEAD (AllSymbols()) AllSymbols() не выбран, единственный, который будет обработан правильно

Phi ::= Phi_sub (("&&" | "||") Phi_sub)* 
Phi_sub ::= "(" Phi ")" | ... 

Psi ::= Psi_sub (("&&" | "||") Psi_sub)* 
Psi_sub ::= "(" Psi ")" | ... 

Xi ::= LOOKAHEAD(Phi) Phi | LOOKAHEAD(Psi) Psi 

Как вы можете видеть, бесконечные опережения бы в вообще может потребоваться в производстве Си, потому что синтаксический анализатор должен различать случаи, как:

((Phi_sub && Phi_sub) || Phi_sub) против ((Psi_sub && Psi_sub) || Psi_sub)

т.е. произвольного количества префиксов (.

Я подумал, что создание взгляда, подобного выше, будет работать, но это не так. Например, Phi выбирается, даже если Xi не расширяется до Phi, а относится к Psi. Это можно легко проверить на определенном потоке S, вызвав Phi с отладчиком сразу после того, как разобранный решил в Xi выбрать Phi и собирается позвонить Phi. Отладчик в таком случае показывает правильное расширение Psi, позволяя парсеру просто вызвать Phi, поскольку он хочет, приведет к исключению синтаксического анализа.

Другой способ тестирования является перекачка Phi и Psi:

Xi ::= LOOKAHEAD(Psi) Psi | LOOKAHEAD(Phi) Phi 

Это заставит анализатор разобрать конкретный S правильно, и поэтому кажется, что просто первая ветвь в Xi выбрана, будь то действительный или нет.

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

ответ

1

Ваши предположения не являются ошибочными. То, что вы пытаетесь сделать, должно работать. И он должен работать по причинам, по которым вы думаете, что он должен работать.


Вот полный пример, написанный на JavaCC.

void Start() : {} { Xi() <EOF> } 

void Xi() : {} { 
    LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; } 
| LOOKAHEAD(Psi()) Psi() { System.out.println("Psi") ; } 
} 

void Phi() : {} { Phi_sub() (("&&" | "||") Phi_sub())*} 

void Phi_sub() : {} { "(" Phi() ")" | "Phi_sub" } 

void Psi() : {} { Psi_sub() (("&&" | "||") Psi_sub())* } 

void Psi_sub() : {} { "(" Psi() ")" | "Psi_sub" } 

А вот некоторый пример вывод:

Input is : <<Phi_sub>> 
Phi 
Input is : <<Psi_sub>> 
Psi 
Input is : <<((Phi_sub && Phi_sub) || Phi_sub)>> 
Phi 
Input is : <<((Psi_sub && Psi_sub) || Psi_sub)>> 
Psi 

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


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

void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() } 

примерно эквивалентно

void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() | fail with a stupid error message } 

К примеру, вот еще один прогон выше грамматики

Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>> 
NOK. 
Encountered "" at line 1, column 1. 
Was expecting one of: 

В конце концов опережения провалилась, анализатор остается с пустым множеством ожиданий!

Если изменить Xi к

void Xi() : {} { 
    LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; } 
| Psi() { System.out.println("Psi") ; } 
} 

вы получите немного лучшее сообщение об ошибке

Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>> 
NOK. 
Encountered " "Phi_sub" "Phi_sub "" at line 1, column 26. 
Was expecting one of: 
    "(" ... 
    "Psi_sub" ... 

Вы также можете сделать персонализированное сообщение об ошибке

void Xi() : {} { 
    LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; } 
| LOOKAHEAD(Psi()) Psi() { System.out.println("Psi") ; } 
| { throw new ParseException("Expected either a Phi or a Psi at line " 
           + getToken(1).beginLine 
           + ", column " + getToken(1).beginColumn + ".") ; 
    } 
} 
+0

Спасибо, так что теперь я знаю , что проблема, скорее всего, игнорируется внутренним взглядом. Я либо (i) попытаюсь присоединиться к Phi и Psi в одно производство, а затем семантически проверить, является ли Phi Phi и Psi Psi, или (ii) переписать грамматику в другом генераторе парсера. – arataj

+0

Синтаксические спецификации просмотра игнорируются во время синтаксического просмотра. См. Обсуждение в FAQ. Это то, чего я никогда не понимал. Если вы опубликуете полный минимальный пример неудачи в качестве нового вопроса, кто-то может понять его. –