2017-02-05 7 views
0

これは、解析領域の最初の日です。 JavaCCの中に私の最初の例として、コードは、それがint +(INT + INT)のようなケースを扱うことができ、なぜ私が疑問に思う算術式のJavaCCのパーサーの例

SKIP: { " " | "\t" | "\n" | "\r"     } 
TOKEN: { "(" | ")" | "+" | "*" | <NUM: (["0"-"9"])+> } 

void S(): {} { E() <EOF>   } 
void E(): {} { T() ("+" T())*  } 
void T(): {} { F() ("*" F())*  } 
void F(): {} { <NUM> | "(" E() ")" } 

です。そのアルゴリズムでは、この式を[int] & [(int)& [int]]としてTsと解析し、解析できないと考えています。それが意図したとおりに解析されたのはなぜですか?

+0

DEBUG_PARSERオプションをオンにすると、その解析方法を正確に説明するトレースが表示されます。 –

答えて

1

は、これは次のようにこの配列は)(S由来することができるトークン

<NUM> "+" "(" <NUM> "+" <NUM> ")" <EOF> 

のシーケンスとしてlexes入力文字列 "1 +(2 + 3)" を考えてみます。 。どのトークンが消費されたかを示します。トークンが消費されると、。移動右

  . S() 
      ~~~ expand 
    ==> . E() <EOF> 
      ~~~ expand 
    ==> . T() ("+" T())* <EOF> 
      ~~~ expand 
    ==> . F() ("*" F())* ("+" T())* <EOF> 
      ~~~ expand 
    ==> . (<NUM> | "(" E() ")") ("*" F())* ("+" T())* <EOF> 
      ~~~~~~~~~~~~~~~~~~~~~ choose first and consume 
    ==> <NUM> . ("*" F())* ("+" T())* <EOF> 
       ~~~~~~~~~~ delete 
    ==> <NUM> . ("+" T())* <EOF> 
       ~~~~~~~~~~ unroll and consume 
    ==> <NUM> "+" . T() ("+" T())* <EOF> 
        ~~~ expand 
    ==> <NUM> "+" . F() ("*" F())* ("+" T())* <EOF> 
        ~~~~ 
    ==> <NUM> "+" . (<NUM> | "(" E() ")") ("*" F())* ("+" T())* <EOF> 
        ~~~~~~~~~~~~~~~~~~~~~ choose second and consume 
    ==> <NUM> "+" "(" . E() ")" ("*" F())* ("+" T())* <EOF> 
         ~~ expand 
    ==> <NUM> "+" "(" . T() ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
         ~~~ expand 
    ==> <NUM> "+" "(" . F() ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
         ~~~ expand 
    ==> <NUM> "+" "(" . (<NUM> | "(" E() ")") ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
         ~~~~~~~~~~~~~~~~~~~~~ choose first and consume 
    ==> <NUM> "+" "(" <NUM> . ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
           ~~~~~~~~~~ delete 
    ==> <NUM> "+" "(" <NUM> . ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
           ~~~~~~~~~~~~~~ unroll and consume 
    ==> <NUM> "+" "(" <NUM> "+" . T() ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
            ~~~ expand 
    ==> <NUM> "+" "(" <NUM> "+" . F() ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
            ~~~ expand 
    ==> <NUM> "+" "(" <NUM> "+" . (<NUM> | "(" E() ")") ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
            ~~~~~~~~~~~~~~~~~~~~~ choose first and consume 
    ==> <NUM> "+" "(" <NUM> "+" <NUM> . ("*" F())* ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
             ~~~~~~~~~~ delete 
    ==> <NUM> "+" "(" <NUM> "+" <NUM> . ("+" T())* ")" ("*" F())* ("+" T())* <EOF> 
             ~~~~~~~~~~ delete and consume 
    ==> <NUM> "+" "(" <NUM> "+" <NUM> ")" . ("*" F())* ("+" T())* <EOF> 
              ~~~~~~~~~~ delete 
    ==> <NUM> "+" "(" <NUM> "+" <NUM> ")" . ("+" T())* <EOF> 
              ~~~~~~~~~~ delete and consume 
    ==> <NUM> "+" "(" <NUM> "+" <NUM> ")" <EOF> . 

キー:

  • 拡大:その定義と非終端を交換してください。
  • 選択します(S | T)を交換SまたはTのいずれかで
  • アンロール:削除
  • * S(S)と*(S)を交換:何も

で*(S)を交換上の導出は左から右の導出です。私は、JavaCCの仕組みを反映しているため、左右の派生を表示することを選択します。