Как добавить атрибут в TerminalNode - PullRequest
1 голос
/ 11 марта 2020

Я работаю над грамматикой antlr, у которой есть правило типа operation : REGISTER '=' OPERATION TYPE OPERATOR ',' OPERATOR. Тип определяется следующим образом: TYPE : 'int' NUMBER '*'?. Теперь я создал базового c посетителя, который переопределяет visitOperation и все работает нормально.

На данный момент я хотел бы иметь возможность определить, был ли тип указателем или нет в зависимости от присутствия из *. Я пытался использовать locals, @parser и @lexer, но ни один из них не позволяет мне что-то делать ctx->TYPE()->isPointer(). Я заметил, что TYPE - это TerminalNode, поэтому это может быть невозможно.

Что вы рекомендуете тогда? Просто создайте локальный HashMap и сохраните там какой-нибудь идентификатор?

РЕДАКТИРОВАТЬ:

Я упростил грамматику, чтобы лучше описать мой вариант использования. Я хотел бы иметь возможность разобрать инструкции, такие как:

r4 = add int32* a,b
r5 = add int8 c,d

Я использую грамматику:

grammar G;      

prog:   (expr NEWLINE)+;

expr    : operation
    ;

operation   : REGISTER '=' 'add' TYPE WORD ',' WORD
        ;

REGISTER    :   'r' NUMBER
        ;

TYPE        : 'int' NUMBER '*'?
        ;

WORD        :   (LETTER)+
        ;

NEWLINE  : [\r\n]+ ;
WS: [ \t\n\r]+ -> skip ;
INT      : [0-9] ;

LETTER   : [a-z] ;

NUMBER  : (INT)+
    ;

Кажется, все работает нормально:

grun G expr -tokens main.txt
[@0,0:1='r4',<REGISTER>,1:0]
[@1,3:3='=',<'='>,1:3]
[@2,5:7='add',<'add'>,1:5]
[@3,9:14='int32*',<TYPE>,1:9]
[@4,16:16='a',<WORD>,1:16]
[@5,17:17=',',<','>,1:17]
[@6,18:18='b',<WORD>,1:18]
[@7,19:19='\n',<NEWLINE>,1:19]
[@8,20:21='r5',<REGISTER>,2:0]
[@9,23:23='=',<'='>,2:3]
[@10,25:27='add',<'add'>,2:5]
[@11,29:33='int8*',<TYPE>,2:9]
[@12,35:35='c',<WORD>,2:15]
[@13,36:36=',',<','>,2:16]
[@14,37:37='d',<WORD>,2:17]
[@15,38:38='\n',<NEWLINE>,2:18]
[@16,39:38='<EOF>',<EOF>,3:0]

К сожалению, сейчас я не знаю, как что-то получить ctx->TYPE()->isAPointer().

Спасибо

1 Ответ

1 голос
/ 11 марта 2020

Почему бы не сделать что-то вроде этого:

operation
 : REGISTER '=' 'add' type WORD ',' WORD
 ;

type
 : TYPE STAR?
 ;

TYPE
 : 'int' NUMBER
 ;

STAR
 : '*'
 ;

Внутри вашего visitOperation() вы можете сделать:

boolean isAPointer = ctx.type().STAR() != null;
...