ANTLR如何使用具有相同启动的词法分析器规则?

Ast*_*tor 5 grammar antlr lexer

如何使用具有相同启动的词法分析器规则?

我试图使用两个类似的词法分析器规则(具有相同的起始):

TIMECONSTANT: ('0'..'9')+ ':' ('0'..'9')+;
INTEGER     : ('0'..'9')+;
COLON       : ':';
Run Code Online (Sandbox Code Playgroud)

这是我的示例语法:

grammar TestTime;

text      : (timeexpr | caseblock)*;

timeexpr  : TIME;
caseblock : INT COLON ID;

TIME      : ('0'..'9')+ ':' ('0'..'9')+;
INT       : ('0'..'9')+;
COLON     : ':';
ID        : ('a'..'z')+;

WS        : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
Run Code Online (Sandbox Code Playgroud)

当我尝试解析文本时:

12:44
123 : abc
123: abc
Run Code Online (Sandbox Code Playgroud)

前两行正确解析,第三行 - 生成错误.出于某种原因,'123:'ANTLR解析为TIME(虽然它不是)...

那么,有可能用这样的词汇来制作语法吗?

在我的语言中使用这些规则对于使用case-blocks和datetime常量是必要的.例如,在我的语言中,可以写:

case MyInt of
  1: a := 01.01.2012;
  2: b := 12:44;
  3: ....
end;
Run Code Online (Sandbox Code Playgroud)

Bar*_*ers 6

一旦DIGIT+ ':'匹配,词法分析器预计会跟随另一个DIGIT匹配a TIMECONSTANT.如果没有发生这种情况,它就不能回到匹配的另一个词法分析器规则上,DIGIT+ ':'而词法分析器也不会放弃已经匹配':'的匹配器INTEGER.

一种可能的解决方案是':' DIGIT+INTEGER规则结束时可选地匹配,并在匹配时更改令牌的类型:

grammar T;  

parse
 : (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
 ;

INTEGER      : DIGIT+ ((':' DIGIT)=> ':' DIGIT+ {$type=TIMECONSTANT;})?;
COLON        : ':';
SPACE        : ' ' {skip();};

fragment DIGIT : '0'..'9';
fragment TIMECONSTANT : ;
Run Code Online (Sandbox Code Playgroud)

解析输入时:

11: 12:13 : 14
Run Code Online (Sandbox Code Playgroud)

将打印以下内容:

INTEGER         '11'
COLON           ':'
TIMECONSTANT    '12:13'
COLON           ':'
INTEGER         '14'
Run Code Online (Sandbox Code Playgroud)

编辑

不太好,但有效......

真正.然而,这不是一个短暂的ANTLR:我知道的大多数词法生成器会有一个问题正确地标记这样的TIMECONSTANT(当时INTEGERCOLON也存在).ANTLR至少有助于在词法分析器中处理它:)

可以让解析器而不是词法分析器来处理它:

time_const : INTEGER COLON INTEGER;
INTEGER    : '0'..'9'+;
COLON      : ':';
SPACE      : ' ' {skip();};
Run Code Online (Sandbox Code Playgroud)

但是,如果您的语言词法分析器忽略空格,则输入如下:

12 :    34
Run Code Online (Sandbox Code Playgroud)

当然,也会受到time_const规则的匹配.