我已经在理解方面遇到了很多问题,即如何在 JavaCC 中优雅地(或以某种方式)处理模棱两可的标记。让我们看这个例子:
我想解析 XML 处理指令。
格式是:"<?" <target> <data> "?>"
:target
是一个 XML 名称,data
可以是除之外的任何内容?>
,因为它是结束标记。
所以,让我们在 JavaCC 中定义它:(
在这种情况下,我使用词法状态DEFAULT
和PROC_INST
)
TOKEN : <#NAME : (very-long-definition-from-xml-1.1-goes-here) >
TOKEN : <WSS : (" " | "\t")+ > // WSS = whitespaces
<DEFAULT> TOKEN : {<PI_START : "<?" > : PROC_INST}
<PROC_INST> TOKEN : {<PI_TARGET : <NAME> >}
<PROC_INST> TOKEN : {<PI_DATA : ~[] >} // accept everything
<PROC_INST> TOKEN : {<PI_END : "?>" > : DEFAULT}
现在识别处理指令的部分:
void PROC_INSTR() : {} {
(
<PI_START>
(t=<PI_TARGET>){System.out.println("target: " + t.image);}
<WSS>
(t=<PI_DATA>){System.out.println("data: " + t.image);}
<PI_END>
) {}
}
让我们测试一下<?mytarget here-goes-some-data?>
:
目标被识别:"target: mytarget"
。但现在我得到了我最喜欢的JavaCC 解析错误:
!! procinstparser.ParseException: Encountered "" at line 1, column 15.
!! Was expecting one of:
!!
什么都没遇到?什么都没期待吗?或者是什么?谢谢你,JavaCC!
我知道,我可以使用MORE
JavaCC 的关键字,但这会给我整个处理指令作为一个标记,所以我不得不自己进一步解析/标记它。我为什么要那么做?我在写一个不解析的解析器吗?
问题是(我猜):因此<PI_DATA>
承认“一切”,我的定义是错误的。我应该告诉 JavaCC 将“除?>
”之外的所有内容识别为处理指令数据。
但是怎么做呢?
注意:我只能使用排除单个字符~["a"|"b"|"c"]
,不能排除诸如or之类的字符串。JavaCC 的另一个很棒的反特性。~["abc"]
~["?>"]
谢谢你。