2016-04-13 6 views
0

私は再帰的降下構文解析プログラムを作成しようとしています。これまでのところ、すべての基礎がありました。文法を強制するためのいくつかの関数を適切に実装するだけです。私はすべてが正しいと思った、それはそれを見ますが、私はAopExpr、またはTerm機能が何か間違っていると思います。入力ストリームが途切れてしまい、物事が認識されないことがあります。私はしかし、どのように表示されません。BNF文法ルールを実際のC++関数/コードに変換する

詳細については、コード例を参照して説明するサイトまたはソースがありますか?私が見たことはすべて非常に一般的ですが、これは問題ありませんが、私は実装についていません。

注:2016年4月17日編集:私の機能はかなり良く、プログラムのコンテキストのためにうまく構成されていました。私が気付いていた問題は、特定のインスタンスでgetTokenを呼び出すときに入力ストリームから文字を摂取したということでした。場合によってはこれは問題ありませんが、それ以外の場合は入力ストリームをリセットする必要があります。だから、文字列charをcharに戻す必要がある場合には、小さなループを追加するだけです。例えば:

if(t.getType() !=Token::EQOP) 
    { 
     //cout<<"You know it" << endl; 
     int size = t.getLexeme().size(); 


     while(size>0) 
     { 
     br->putback(t.getLexeme().at(size-1)); 
     size--; 
     } 

     return ex; 
    } 

だからそれは言われて、私はかなりそれに応じて私のプログラムを編集することができたと私は文字を食べていたものを見たら、すべてが働きました。

これは文法です:

Program::= StmtList 
    StmtList::= Stmt | StmtList 
    Stmt::= PRINTKW Aop SC | INTKW VAR SC | STRKW VAR SC | Aop SC 
    Expr::= Expr PLUSOP Term | Expr MINUSOP Term | Term 
    Term::= Term STAROP Primary | Primary 
    Primary::= SCONST | ICONST | VAR | LPAREN Aop RPAREN 

は、ここですべての機能を持つ主なプログラムです:私が最もトラブルを抱えているように見えるhttp://pastebin.com/qMB8h8vE

機能がAssignmentOperator(Aop)Expression(Expr)、およびTermです。私はここにそれらをリストアップします。

ParseTree* Aop(istream *br) 
{ 
    ParseTree * element = Expr(br); 
    if(element!=0) 
    { 
     if(element->isVariable()) 
     { 
      Token t= getToken(br); 

      if(t==Token::EQOP) 
      {     
       cout<<"No" << endl; 
       ParseTree * rhs = Aop(br); 
       if(rhs==0) 
        return 0; 
       else 
       { 
        return new AssignOp(element, rhs); 
       } 
      } 
      else 
      { 
       return element; 
      } 
     } 
    } 

    return 0; 
} 

ParseTree* Expr(istream *br) 
{ 
    ParseTree * element = Term(br); 
    if(element!=0) 
    { 
     Token t=getToken(br); 
     if(t==Token::MINUSOP || t==Token::PLUSOP) 
     { 
      if(t==Token::PLUSOP) 
      { 
       ParseTree* rhs = Expr(br); 
       if(rhs==0) 
        return 0; 
       else 
       { 
        return new AddOp(element, rhs); 
       } 
      } 

      if(t==Token::MINUSOP) 
      { 
       ParseTree* rhs = Expr(br); 
       if(rhs==0) 
        return 0; 
       else 
       { 
        return new SubtractOp(element, rhs); //or switch the inputs idk 
       } 
      } 
     } 
     else 
     { 
      return element; 
     } 
    } 

    return 0; 
} 

ParseTree* Term(istream *br) 
{ 
    ParseTree *element = Primary(br); 

    if(element!=0) 
    { 
     Token t=getToken(br); 
     if(t==Token::STAROP) 
     { 
      ParseTree* rhs =Term(br); 
      if(rhs==0) 
       return 0; 
      else 
      { 
       return new MultiplyOp(element, rhs); 
      } 
     } 
     else 
     { 
      return element; 
     } 
    } 

    return 0; 
} 
+1

人々に読ませたい場合は、コードを(構造に対応した形で)インデントしてください。 – rici

+0

どうすればそれを読むことができますか?ワオ。 –

+1

再帰的降下パーサーの記述方法に関する私の答えを参照してください:http://stackoverflow.com/questions/2245962/is-there-an-alternative-for-flex-bison-that-is-usable-on-8bit -embedded-systems/2336769#2336769 –

答えて

1

recusrive下降パーサを書くためには、あなたはleft recursionの取り払う、LLフォームにご希望の文法を変換する必要があります。あなたがpeekTokenを必要としている

ParseTree *Term(istream *br) { 
    ParseTree *element = Primary(br); 
    while (element && peekToken(br) == Token::STAROP) { 
     Token t = getToken(br); 
     ParseTree *rhs = Primary(br); 
     if (!rhs) return 0; 
     element = new MulOp(element, rhs); } 
    return element; 
} 

注:これは、その後のような関数の何かになり

Term ::= Primary Term' 
Term' ::= epsilon | STAROP Primary Term' 

:ルール

Term::= Term STAROP Primary | Primary 

のために、あなたのような何かを得るでしょう次のトークンを消費することなく先読みする機能また、同じことを行うにはgetToken + ungetTokenを使用することも可能です。

+0

ありがとうございました。私は明日これを実装しようとし、それがうまくいくかどうかを調べるつもりです。私はまだ私のAop関数については気をつけていませんが、これはよく必要な情報を追加します。 BNFをEBNFに変換しましたが、それは私の好きなだけの助けには見えませんでした。いずれにせよ、ありがとう。 – Abe

関連する問題