1

给定词法分析器

fragment
FRAGID : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
ID  : FRAGID;
NAME: FRAGID ('.' FRAGID)*;

鉴于语法

var_def: type=ID vname=ID ASSIGN expr       
   -> ^(VARDEF $type $vname expr) 
   ; 

有选项

options
{
  language=CSharp3; 
  output=AST;
}

并给出代码

int i = 0

一切正常。

但是,当我想允许在赋值中使用 NAME 时(引用另一个对象)

var_def
  : type=(NAME|ID) vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

我在运行时遇到RewriteEmptyStreamException

Antlr.Runtime.Tree.RewriteEmptyStreamException :令牌类型

在 c:\dev\stringtemplate_main\antlr\antlr3-main\runtime\CSharp3\Sources\Antlr3.Runtime\Tree\RewriteRuleElementStream.cs 中的 Antlr.Runtime.Tree.RewriteRuleElementStream.NextCore():第 200 行

在 c:\dev\stringtemplate_main\antlr\antlr3-main\runtime\CSharp3\Sources\Antlr3.Runtime\Tree\RewriteRuleTokenStream.cs 中的 Antlr.Runtime.Tree.RewriteRuleTokenStream.NextNode():第 62 行

用语法做更多的调查

var_def
  : type=NAME vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

我得到一个

Antlr.Runtime.Tree.RewriteEarlyExitException :引发了“Antlr.Runtime.Tree.RewriteEarlyExitException”类型的异常。

4

1 回答 1

1

The 'i' in:

int i = 0

will always become an ID token. Because both ID and NAME match a single FRAGID, and since ID is defined before NAME, there will never be a NAME token (in case of a single FRAGID). It will always become an ID token.

That is why this won't work:

var_def
  : type=NAME vname=ID ASSIGN expr 
  -> ^(VARDEF $type $vname expr) 
  ;

You must realize that the lexer does not create tokens depending on what token the parser is trying to match at a specific time. The lexer works independently from the parser.

Try avoiding the assignment of a label to a parenthesized group of tokens/rules. Instead of:

var_def
  : type=(NAME|ID) vname=ID ASSIGN expr -> ^(VARDEF $type $vname expr) 
  ;

do this:

var_def
 : type ID ASSIGN expr -> ^(VARDEF type ID expr) 
 ;

type
 : NAME
 | ID
 ;
于 2012-08-28T08:11:30.990 回答