0

我正在为一组 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

那么我做错了什么?

4

1 回答 1

1

我猜 SYMBOL 包括“=”和“>”,但不包括“|”。在这种情况下。STRING 将匹配整个“DE => 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>

于 2012-10-25T11:37:14.240 回答