сложное правило перезаписи AST в ANTLR

После проблемы с правилом перезаписи AST с методом разделения групп на Правило перезаписи AST с * + в antlr.

У меня опять проблема с генерацией AST в ANTLR :) Вот мой код antlr:

start   :   noun1+=n (prep noun2+=n (COMMA noun3+=n)*)*
        ->  ^(NOUN $noun1) (^(PREP prep) ^(NOUN $noun2) ^(NOUN $noun3)*)*
    ;
n       :    'noun1'|'noun2'|'noun3'|'noun4'|'noun5';
prep    :    'and'|'in';
COMMA   :     ',';

Теперь, с вводом: «существительное1 и существительное2, существительное3 в существительном4, существительное5», я получил следующий неожиданный AST:

введите описание изображения здесь

Сравните с «деревом синтаксического анализа» в ANLRwork:

введите описание изображения здесь

Я думаю, что переменная $ noun3 содержит список всех "n" в "COMMA noun3 + = n". Следовательно, синтаксический анализатор AST ^ (NOUN $ noun3) * будет рисовать все «n» без указания того, какое «n» на самом деле принадлежит «Prep».

Есть ли способ сделать разделение в "(^ (PREP Prep) ^ (NOUN $ noun2) ^ (NOUN $ noun3)) " . Все, что я хочу сделать, это то, что AST должен рисовать точно, без лексемы COMMA, с «деревом разбора» в ANTLRwork.

Спасибо за помощь !


person Trung L    schedule 20.12.2012    source источник


Ответы (1)


Получить желаемое разделение проще всего, если вы нарушите правило start. Вот пример (без записи COMMAs в AST):

start   :   prepphrase             //one prepphrase is required.
            (COMMA! prepphrase)*   //"COMMA!" means "match a COMMA but don't write it to the AST"
        ;

prepphrase: noun1=n                //You can use "noun1=n" instead of "noun1+=n" when you're only using it to store one value
            (prep noun2=n)? 
            -> ^(NOUN $noun1) ^(PREP prep)? ^(NOUN $noun2)?
        ;

prepphrase - существительное, за которым может следовать предлог другого существительного. Правило start ищет prepphrase, разделенных запятыми.

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


Если вы предпочитаете явно записывать AST с помощью -> или если вам не нравится синтаксис типа COMMA!, вы можете вместо этого написать правило start. Две разные формы функционально эквивалентны.

start   :   prepphrase             //one prepphrase is required.
            (COMMA prepphrase)*
            -> prepphrase+         //write each prepphrase, which doesn't include commas
        ;
person user1201210    schedule 20.12.2012
comment
Большое спасибо ! Это действительно целебно - person Trung L; 20.12.2012