Parsing 具有简单语法的Antlr MissingTokenException

Parsing 具有简单语法的Antlr MissingTokenException,parsing,antlr,lexer,Parsing,Antlr,Lexer,我有我认为是世界上最简单的语法,解析文件系统路径,格式为dir1/dir2/filename(没有前导/)。我删去了一些细节,得到了一个小样本,显示了这个问题 compilationUnit : relativePath; identifier: IdentifierStart IdentifierPart*; relativePath : identifier (SLASH identifier)*; SLASH : '/'; fragment IdentifierPart

我有我认为是世界上最简单的语法,解析文件系统路径,格式为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。它标识一个标识符,然后得到斜杠,然后我得到一个挂起标识符的MissingTokenException。一定是我错过了一些基本的东西,但是什么呢

将关键字
片段
放在lexer规则前面时,不能在解析器规则中使用此规则。
片段
只能在其他lexer规则中使用。这些规则永远不会单独成为令牌,它们只能作为其他令牌(其他lexer规则)的一部分使用

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

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

// lexer rules
SLASH           : '/';
IdentifierStart : 'a'..'z' | 'A'..'Z' | '_';   
Digit           : '0'..'9';
但是,也可以将相对路径设置为单个标记,在这种情况下,您可以保留
片段
关键字,但必须将一些解析器规则设置为lexer规则,如下所示:

// 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与单个
标识符
匹配,因此永远不会为解析器创建
标识符
标记。因此,
标识符
也应该是
片段
。所以,也许这不是你想要的。

我最后在antlr列表上问了这个问题。提供的解释是,通过大写将标识符转换为解析器规则应该可以解决问题,因为解析器永远不会看到IdenifierStart和identifiernd片段。在lexer中运行规则解决了这个问题。@seven,我不明白你为什么在那里问:我已经给出了答案,没有?