我正在为一组CFG编写解析器。 (注意:RHS只能是一个大写字母)
/ *忽略声明和东西,这是代码* /
的主要部分void
start():
{
}
{
(
<UPPER_CHAR>
<ARROW>
<STRING>
( <PIPE> <STRING> )*
)*
}
TOKEN:
{
<ARROW: "=>" >
|
<PIPE: "|">
|
<UPPER_CHAR: (["A"-"Z"])>
}
TOKEN: {<STRING: (<LETTER> | <DIGIT> | <SYMBOL>)+ > }
这显然错过了一些边缘案例,其中一些包括:
A => A | a | D E => e
那我做错了什么?
答案 0 :(得分:1)
我猜SYMBOL包含“=”和“&gt;”但不是“|”。在这种情况下。 STRING将匹配整个“D E =&gt; e”。
为什么你想要STRING?为什么不这样做呢。
void start() : {} {
(
<UPPER_CHAR> <ARROW>
choices()
)*
}
void choices() : {} {
choice() ( <PIPE> choice())*
}
void choice() : {} {
LOOKAHEAD(<UPPER_CHAR> <ARROW> )
{}
|
(<UPPER_CHAR> | <LOWER_CHAR>) choice()
|
{}
}
我为choice
使用递归的原因是没有办法使用语法前瞻来退出循环。即你想要的是(<UPPER_CHAR> | <LOWER_CHAR>)*
,但是当你接下来的两个代币是<UPPER_CHAR> <ARROW>
时,你想要摆脱这个循环。