我正在编写一个简化的antlr4 XML语法来解析这个例子:
<root>
<field a="1">
random text
</field>
</root>
语法是:
grammar TestKo;
root : '<root>' WS* field* WS* '</root>' ;
field : '<field' attr* '>' chardata* '</field>' ; // fails
attr : TEXT '=' '"' TEXT '"';
chardata : TEXT | WS ;
WS : (' '|'t'|'r'? 'n')+ -> skip;
TEXT : ~[<&]+ ;
使用antlr4:运行
$ antlr4 TestKo.g4 && javac -cp /usr/share/java/antlr4-runtime.jar TestKo*java
$ cat ./test.xml | grun TestKo root -tree
line 4:2 mismatched input '</field>' expecting '='
(root <root> (field <field (attr a="1">ntrandom textn </field>)) </root>)
正确解析field
和'>'
之间的属性缺少什么
谢谢你的建议。
在解析器考虑任何解析器规则之前,lexer会运行到完成。推论:解析器规则评估不能影响lexer规则评估。因此,规则
TEXT : ~[<&]+ ;
将消耗[>="/]
,从而防止解析器看到相应的隐式令牌。(这是语法的主要错误。(
说明:隐式标记是在解析器中为字符串生成的。这是对";解析器不影响lexer";真理。它们在内部被定义为放置在lexer规则列表的顶部,即通过魔术,因此具有最高的单字符匹配优先级。
TEXT
规则可以匹配多个字符串,并且对于这些字符串,具有更高的绝对匹配优先级:在多个lexer规则可以匹配给定输入的情况下,匹配长度最长的规则获胜;如果长度相同,则列出的第一条规则获胜。
出于各种实际原因——清晰度和;可维护性——最好不要依赖于隐式令牌。
建议:解析XML并不简单。正如当前语法所尝试的那样,区分random text
和标签将是有问题的。假设标签提供了清晰的保护字符——<
和>
——使用Antlrmode
功能将结构化的标签内词汇表与random text
的词汇表干净地分离,将使语法更容易设计和维护。
顺便说一句,-> skip
完全按照它所说的做:不会产生代币。因此,解析器规则
chardata : TEXT | WS ;
将永远看不到CCD_ 11令牌。
如果你是Antlr的新手,TDAR非常值得一读。
当我检查问题并准备答案时,你已经有了答案。。。
负令牌很难管理,它们可能会占用文件的其余部分。将你的语法重命名为Question和你的数据:
$ grun Question root -tokens data.txt
[@0,0:5='<root>',<'<root>'>,1:0]
[@1,9:14='<field',<'<field'>,2:2]
[@2,15:40=' a="1">n random textn ',<TEXT>,2:8]
[@3,41:48='</field>',<'</field>'>,4:2]
[@4,50:56='</root>',<'</root>'>,5:0]
[@5,58:57='<EOF>',<EOF>,6:0]
line 4:2 mismatched input '</field>' expecting '='
它找不到=,因为它已在令牌@2中被attr
的第一个TEXT
规则消耗。试试这个:
grammar Question;
root : '<root>' WS* field* WS* '</root>' ;
field : '<field' attr* '>' chardata* '</field>' ;
attr : TEXT '=' STRING ;
chardata : TEXT | WS ;
STRING : '"' .*? '"' ;
WS : (' '|'t'|'r'? 'n')+ -> skip;
TEXT : ~[=<>&]+ ;
执行:
$ export CLASSPATH=".:/usr/local/lib/antlr-4.6-complete.jar"
$ alias a4='java -jar /usr/local/lib/antlr-4.6-complete.jar'
$ alias grun='java org.antlr.v4.gui.TestRig'
$ a4 Question.g4
$ javac Question*.java
$ grun Question root -tokens data.txt
[@0,0:5='<root>',<'<root>'>,1:0]
[@1,9:14='<field',<'<field'>,2:2]
[@2,15:16=' a',<TEXT>,2:8]
[@3,17:17='=',<'='>,2:10]
[@4,18:20='"1"',<STRING>,2:11]
[@5,21:21='>',<'>'>,2:14]
[@6,22:40='n random textn ',<TEXT>,2:15]
[@7,41:48='</field>',<'</field>'>,4:2]
[@8,50:56='</root>',<'</root>'>,5:0]
[@9,58:57='<EOF>',<EOF>,6:0]