使用 antlr4 解析 XML 标记和属性时出现问题



我正在编写一个简化的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]

相关内容

  • 没有找到相关文章

最新更新