给定g4语法:
grammar smaller;
root
: ( componentDefinition )* EOF;
componentDefinition
: Addr
Id?
Lbrace
Rbrace
Semi
;
ExprElem
: Num
| Id
;
Addr : 'addr' {System.out.println("addr");};
Lbrace : '{' ;
Rbrace : '}' ;
Semi : ';' ;
Id : [a-zA-z0-9_]+ {System.out.println("id");};
Num : [0-9]+;
//------------------------------------------------
// Whitespace and Comments
//------------------------------------------------
Wspace : [ t]+ -> skip;
Newline : ('r' 'n'?
| 'n'
) -> skip;
和这个文件来解析
addr basic {
};
此cmdline:
rm *.class *.java ; java -Xmx500M org.antlr.v4.Tool smaller.g4 ; javac *.java ; cat basic | java org.antlr.v4.runtime.misc.TestRig smaller root -tree
我得到这个错误:
line 2:0 mismatched input 'addr' expecting {<EOF>, 'addr'}
(root addr basic { } ;)
如果我删除ExprLem(它在语法中的其他地方没有使用),解析器就会工作:
addr
id
(root (componentDefinition addr basic { } ;) <EOF>)
为什么?请注意,这是一个大大简化的语法版本。通常情况下,表达式确实有目的。
Addr是一个文字,所以它不应该像其他问题一样与Id冲突。
您的规则ExprElem
是lexer规则,而不是解析器规则(它以supercase开头),并且正在屏蔽Addr
规则,因此,没有Addr
:(
此外,由于ExprElem
是lexer规则,它依赖于Id
或Num
规则。因此,当找到Id
时,ANTLR lexer给它ExprElem
令牌类型,而不是Id
令牌类型。
因此,有两件事,您可以将ExprElem
规则重写为exprElem
(假设您想要一个解析器规则):
exprElem : Num | Id;
或者,您可以在ExprElem
中使用Id
令牌作为规则的一部分,但您需要能够区分ExprElem
和Id
的东西(下面的示例,但我确实认为您需要一个解析器规则):
Addr : 'addr' {System.out.println("addr");};
ExprElem
: Sharp Num // This token use others but defines its own 'pattern'
| Sharp Id
;
Lbrace : '{' ;
Rbrace : '}' ;
Semi : ';' ;
Id : [a-zA-z0-9_]+ {System.out.println("id");};
Num : [0-9]+;
Sharp : '#';
据我所知,这绝对不是您想要的,但我把它放在这里只是为了说明lexer规则如何重用其他规则。
当您对代币的作用有疑问时,请毫不犹豫地显示识别代币。以下是我经常使用的Java代码片段(在本例中,我将语法命名为test
):
public class Main {
public static void main(String[] args) throws InterruptedException {
String txt =
"addr Basic {n"
+ "n"
+ "};";
TestLexer lexer = new TestLexer(new ANTLRInputStream(txt));
CommonTokenStream tokens = new CommonTokenStream(lexer);
TestParser parser = new TestParser(tokens);
parser.root();
for (Token t : tokens.getTokens()) {
System.out.println(t);
}
}
}
注意:顺便说一句,Num
永远不会被识别为Id
规则可以匹配相同的东西。试试这个:
Id : Letter (Letter | [0-9])*;
Num : [0-9]+;
fragment Letter : [a-zA-z_];