0

Я пишу парсер/лексер для COOL (классно-ориентированный язык). и можно увидеть грамматику в следующей ссылке: (последняя страница РУКОВОДСТВА)Parsing Cool Язык с antlr, не могу распечатать желаемый результат

http://theory.stanford.edu/~aiken/software/cool/cool-manual.pdf

Я использую ANTLR написать эту программу и со следующим входом, я хочу следующий вывод:

вход:

class Main inherits IO { 
    main(): Object {{ 
    x <- 2 + 3 *4; 
    }}; 
}; 

выход:

1 
2 
3 
11 
6 
16 
27 
18 
27 
27 

но выход я получаю:

1 
2 
3 
11 
6 
27 
16 
27 
18 
27 

и вот мой парсер/лексический код:

// parser 
grammar CA2; 

program : {System.out.println("1");} (classdef';')+ ; 
classdef : {System.out.println("2");} CLASS ID (INHERITS ID)? '{' (feature';')* '}' ; 
feature : {System.out.println("3");} ID OPENP (formal (','formal)*)? CLOSEP ':' ID '{' expr '}' 
     | {System.out.println("4");} ID ':' ID (POINTTOLEFT expr)? ; 
formal : {System.out.println("5");} ID ':' ID ; 
expr : {System.out.println("6");} ID POINTTOLEFT expr exprprime 
    | {System.out.println("8");} ID OPENP (expr (','expr)*)? CLOSEP exprprime 
    | {System.out.println("9");} IF expr THEN expr ELSE expr FI exprprime 
    | {System.out.println("10");} WHILE expr LOOP expr POOL exprprime 
    | {System.out.println("11");} '{' (expr';')+ '}' exprprime 
    | {System.out.println("12");} LET ID ':' ID (POINTTOLEFT expr)? (','ID ':' ID (POINTTOLEFT expr)?)* IN expr exprprime 
    | {System.out.println("13");} CASE expr OF (ID POINTTORIGHT expr ';')+ ESAC exprprime 
    | {System.out.println("14");} NEW ID exprprime 
    | {System.out.println("15");} ISVOID expr exprprime 
    /*| {System.out.println("16");} expr ADD expr 
    | {System.out.println("17");} expr SUB expr 
    | {System.out.println("18");} expr MULTIPLY expr 
    | {System.out.println("19");} expr DIV expr 
    | {System.out.println("20");} TILDA expr 
    | {System.out.println("21");} expr LARGERTHAN expr 
    | {System.out.println("22");} expr LARGEREQ expr 
    | {System.out.println("23");} expr EQUALS expr 
    | {System.out.println("24");} NOT expr 
    | {System.out.println("25");} OPENP expr CLOSEP 
    | {System.out.println("26");} ID 
    | {System.out.println("27");} INTEGER*/ 
    | {System.out.println("28");} STRING exprprime | mathex exprprime ; 
    /*| {System.out.println("29");} TRUE 
    | {System.out.println("30");} FALSE ;*/ 
exprprime : {System.out.println("7");} (('@'ID)?)'.'ID OPENP (expr (','expr)*)? CLOSEP exprprime | ; 
mathex : b ; 
b : {System.out.println("24");} NOT b | c ; 
cprime : {System.out.println("21");} LARGERTHAN d cprime 
     | {System.out.println("22");} LARGEREQ d cprime 
     | {System.out.println("23");} EQUALS d cprime | ; 
c : d cprime ; 
dprime : {System.out.println("16");} ADD e dprime 
     | {System.out.println("17");} SUB e dprime | ; 
d : e dprime ; 
eprime : {System.out.println("18");} MULTIPLY f eprime 
     | {System.out.println("19");} DIV f eprime | ; 
e : f eprime ; 
f : {System.out.println("20");} TILDA f | g ; 
g : {System.out.println("25");} OPENP mathex CLOSEP 
    | {System.out.println("26");} ID 
    | {System.out.println("27");} INTEGER 
    | {System.out.println("29");} TRUE 
    | {System.out.println("30");} FALSE ; 

//lexer 
TRUE : 'true' ; 
FALSE : 'false' ; 
INHERITS : 'inherits' ; 
CLASS : 'class' ; 
IF : 'if' ; 
THEN : 'then' ; 
ELSE : 'else' ; 
FI : 'fi' ; 
WHILE : 'while' ; 
LOOP : 'loop' ; 
POOL : 'pool' ; 
LET : 'let' ; 
IN : 'in' ; 
CASE : 'case' ; 
OF : 'of' ; 
ESAC : 'esac' ; 
NEW : 'new' ; 
ISVOID : 'isvoid' ; 
NOT : 'not' ; 
TILDA : '~' ; 
WHITESPACE : [ ' '|'\r'|'\n'|'\t']+ ->skip ; 
INTEGER : [0-9]+ ; 
ID : ['_'a-zA-Z][a-zA-Z0-9'_']* ; 
ADD : '+' ; 
MULTIPLY : '*' ; 
SUB : '-' ; 
DIV : '/' ; 
OPENP : '(' ; 
CLOSEP : ')' ; 
EQUALS : '=' ; 
LARGERTHAN : '<' ; 
LARGEREQ : '<=' ; 
POINTTOLEFT : '<-' ; 
POINTTORIGHT : '=>' ; 
STRING : '"'(~[\r\n])*'"' ; 

Это версия код COOL грамматики в ANTLR. части, которые прокомментированы в основном коде, неоднозначны (средства обнуляются двусмысленности!) и лево-рекурсия освобождаются во второй части (правило mathex).

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

благодарит заранее!

ответ

1

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

Ваше первое несоответствие между ожидаемыми и фактическими выходами - это изменение линий 16 и 27. Ваш ожидаемый результат будет возникать только в том случае, если токен + на вашем входе появился перед маркером на вашем входе, но, очевидно, вы видите, что это не так. Второе несоответствие происходит по той же причине; в частности, это связано с тем, что ожидаемый результат предполагал, что маркер * появится раньше в вашей грамматике, чем токен 3.


Я заметил, что вы изначально написал левую рекурсию expr правила и включены внедренные действия в ней. Следующая информация не связана с решением вашего конкретного вопроса, но важно понимать, если вы решили раскомментировать этот код и использовать леворекурсивную форму expr.

Рассмотрим следующее леворекурсивное правило, позволяющее простое добавление идентификаторов с добавлением двух встроенных действий.

expr 
    : {a();} ID 
    | {b();} expr '+' ID 
    ; 

Как вы, вероятно, узнали, этот синтаксис не будет компилироваться с ANTLR. Мы обнаружили, что оценка выражения {b();} в том месте, где я его показал, привела к огромному (отрицательному) результату воздействия на сгенерированный код, поэтому мы решили не допускать его. Результатом будет вывод Polish prefix form выражения, в то время как синтаксический анализатор фактически пытается работать на входе с использованием infix notation.Решение состоит в том, чтобы вместо того, чтобы излучать инфиксное обозначение:

expr 
    : {a();} ID 
    | expr {b();} '+' ID 
    ; 

Собрав результаты звонков a и b, вы можете преобразовать результаты любой нотацию вам нравится перед записью результатов. Другой вариант - перемещать внедренные действия посетителю, который выполняется после завершения разбора, где тривиально, чтобы выполнить их в любом порядке.

Дальнейшее чтение: Infix, Postfix, and Prefix

+0

Я думаю, что ваш ответ не был на самом деле ответ, скорее уловка, чтобы изменить выход в любом случае мы хотим, я прав? И вы также подразумеваете, что желаемый результат неправильный, и мой вывод на самом деле нормально? –

+0

@AshkanKzme Первая часть моего ответа (выше часа) объясняет, что именно и почему вы получаете результат, который вы видели. Вторая часть - это дополнительная информация для вас, потому что я заметил, что вы прокомментировали леворекурсивную форму правила 'expr' и решили, что вам, возможно, захочется узнать, почему она не работает. –

+0

Итак, вы на самом деле не отвечаете на вопрос, просто добавляя к нему подобную информацию. извините, не может принять это как ответ. –

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

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