ANTLR4:匹配具有相同规则但在语法中具有不同位置的令牌

时间:2017-09-26 16:22:34

标签: antlr antlr4

我希望解析以下声明:

in(name,(Silver,Gold))
  • in:是一个函数。
  • name:是一个ID。
  • (Silver,Gold):是字符串数组,元素为“Silver”和“Gold”。

解析器总是混淆为ID和字符串数组元素具有相同的规则。对字符串使用引号或双引号会有所帮助,但这不是这种情况。

此外,谓词并没有多大帮助。

语法:

grammar Rql;

statement
 : EOF
 | query EOF
 ;

query
 : function
 ;

function
 : FUNCTION_IN OPAR id COMMA OPAR array CPAR CPAR
 ;

array
 : VALUE (COMMA VALUE)*
 ;

FUNCTION_IN: 'in';

id
 : {in(}? ID
 ;

ID
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;

VALUE
 : STRING
 | INT
 | FLOAT
 ;

OPAR : '(';
CPAR : ')';
COMMA : ',';

INT
 : [0-9]+
 ;

FLOAT
 : [0-9]+ '.' [0-9]*
 | '.' [0-9]+
 ;

SPACE
 : [ \t\r\n] -> skip
 ;

STRING
 :  [a-zA-Z_] [a-zA-Z_0-9]*
 ;

OTHER
 : .
 ;

1 个答案:

答案 0 :(得分:1)

想法是在某些条件下更改令牌的类型。在这里第一次看到一个ID,将一个开关设置为true。下次匹配ID时,词法分析器将执行if并将类型设置为ID_VALUE。我想在输入规则function时重置开关,但它不起作用:

function
@init {QuestionLexer.id_seen = false; System.out.println("id_seen has been reset" + QuestionLexer.id_seen);}
 : FUNCTION_IN OPAR ID COMMA OPAR array CPAR CPAR

ID=name1  seen ? false
ID=Silver  seen ? true
...
ID=Platinum  seen ? true
[@0,0:1='in',<'in'>,1:0]
[@1,2:2='(',<'('>,1:2]
[@2,3:7='name1',<ID>,1:3]
[@3,8:8=',',<','>,1:8]
[@4,9:9='(',<'('>,1:9]
[@5,10:15='Silver',<10>,1:10]
...
[@12,27:31='name2',<10>,2:3]
...
[@20,52:51='<EOF>',<EOF>,3:0]
Question last update 1336
id_seen has been reset false
id_seen has been reset false
line 2:3 mismatched input 'name2' expecting ID

这就是我在FUNCTION_IN规则中重置它的原因。

语法问题.4:

grammar Question;

@lexer::members {
    static boolean id_seen = false;
}

tokens { ID_VALUE }

question
@init {System.out.println("Question last update 1352");}
 : function+ EOF
 ;

function
 : FUNCTION_IN OPAR ID COMMA OPAR array CPAR CPAR
 ;

array
 : value (COMMA value)*
 ;

value
 : ID_VALUE
 | INT
 | FLOAT
 ;

FUNCTION_IN: 'in' {id_seen = false;} ;

ID : [a-zA-Z_] [a-zA-Z_0-9]*
     {System.out.println("ID=" + getText() + "  seen ? " + id_seen);
      if (id_seen) setType(QuestionParser.ID_VALUE); id_seen = true; } ;

OPAR : '(';
CPAR : ')';
COMMA : ',';

INT
 : [0-9]+
 ;

FLOAT
 : [0-9]+ '.' [0-9]*
 | '.' [0-9]+
 ;

SPACE
 : [ \t\r\n] -> skip
 ;

OTHER
 : .
 ;

文件t.text:

in(name1,(Silver,Gold))
in(name2,(Copper,Platinum))

使用ANTLR 4.6执行:

$ grun Question question -tokens -diagnostics t.text
ID=name1  seen ? false
ID=Silver  seen ? true
ID=Gold  seen ? true
ID=name2  seen ? false
ID=Copper  seen ? true
ID=Platinum  seen ? true
[@0,0:1='in',<'in'>,1:0]
[@1,2:2='(',<'('>,1:2]
[@2,3:7='name1',<ID>,1:3]
[@3,8:8=',',<','>,1:8]
[@4,9:9='(',<'('>,1:9]
[@5,10:15='Silver',<10>,1:10]
[@6,16:16=',',<','>,1:16]
[@7,17:20='Gold',<10>,1:17]
[@8,21:21=')',<')'>,1:21]
[@9,22:22=')',<')'>,1:22]
[@10,24:25='in',<'in'>,2:0]
[@11,26:26='(',<'('>,2:2]
[@12,27:31='name2',<ID>,2:3]
[@13,32:32=',',<','>,2:8]
[@14,33:33='(',<'('>,2:9]
[@15,34:39='Copper',<10>,2:10]
[@16,40:40=',',<','>,2:16]
[@17,41:48='Platinum',<10>,2:17]
[@18,49:49=')',<')'>,2:25]
[@19,50:50=')',<')'>,2:26]
[@20,52:51='<EOF>',<EOF>,3:0]
Question last update 1352

类型&lt; 10&gt;在ID_VALUE文件中可以看到.tokens

$ cat Question.tokens 
FUNCTION_IN=1
...
OTHER=9
ID_VALUE=10
'in'=1