具有简单语法的Antlr MissingTokenException

时间:2012-03-02 05:41:39

标签: parsing antlr lexer

我有我认为世界上最简单的语法,解析dir1 / dir2 / filename形式的文件系统路径(没有前导/)。我已经删除了一些细节,以获得一个展示问题的小样本。

compilationUnit : relativePath;
identifier: IdentifierStart IdentifierPart*;    
relativePath : identifier (SLASH identifier)*;

SLASH   :   '/';
fragment IdentifierPart : 'a'..'z' | 'A'..'Z' | '_' | '0'..'9';
fragment IdentifierStart :  'a'..'z' | 'A'..'Z' | '_';    

如果我提供类似foo / aa / bb的东西,我会得到一个MissingTokenException。它标识一个标识符,然后获取SLASH,并且我在标识符上挂起了一个MissingTokenException。必须是我缺少的基本东西,但是什么?

1 个答案:

答案 0 :(得分:2)

如果将关键字fragment放在词法分析器规则之前,则无法在解析器规则中使用此规则。 fragment只能在其他词法规则中使用。这些规则永远不会成为令牌,它们只能用作其他令牌的一部分(其他词法规则)。

换句话说:从语法中删除这些fragment个关键字:

// parser rules
compilationUnit : relativePath;
relativePath    : identifier (SLASH identifier)*;
identifier      : IdentifierStart (IdentifierStart | Digit)*;    

// lexer rules
SLASH           : '/';
IdentifierStart : 'a'..'z' | 'A'..'Z' | '_';   
Digit           : '0'..'9';

但是,也可以将相对路径制作为单个标记,在这种情况下,可以保留fragment关键字,但必须将一些解析器规则放入词法分析器规则,如下所示:

// parser rule
compilationUnit : RelativePath;

// lexer rules
RelativePath    : Identifier ('/' Identifier)*;

fragment Identifier      : IdentifierStart IdentifierPart*;
fragment IdentifierPart  : 'a'..'z' | 'A'..'Z' | '_' | '0'..'9';
fragment IdentifierStart : 'a'..'z' | 'A'..'Z' | '_';    

但是,因为RelativePath匹配单个Identifier,所以永远不会为解析器创建Identifier标记。因此,Identifier也应该是fragment。所以也许这不是你想要的。