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>)*、次の 2 つのトークンが になったらすぐにこのループから抜け出したいのです<UPPER_CHAR> <ARROW>

于 2012-10-25T11:37:14.240 に答える