2016-04-13 17 views
0

Yinelemeli bir yoklama ayrıştırıcısı oluşturmaya çalışıyorum. Şimdiye kadar tüm temel setlere sahibim, dilbilgisini zorlamak için sadece birkaç işlevi yerine getirmem gerekiyor. Her şeyin doğru olduğunu düşündüm, öyle görünüyor, ama sanırım Aop, Expr veya Term işlevlerim yanlış bir şey yapıyor. Bazen giriş akışı kesilir ve işler tanınmaz. Nasıl olduğunu göremiyorum.BNF dilbilgisi kurallarını gerçek C++ işlevlerine/koduna dönüştürme

Kod örnekleri ile bunu daha ayrıntılı olarak açıklayan herhangi bir site veya kaynak var mı? Gördüğüm her şey çok genel, ki bu iyi, ama uygulamaya takılıyorum.

NOT: 17 Nisan 2016'yı düzenle: İşlevlerim, programımın içeriği için oldukça iyi ve iyi yapılandırılmıştı. Anladığım ve fark etmediğim sorun, getToken'i çağırdığım bazı durumlarda giriş akışından gelen karakterleri "yedim" idi. Bazen bu iyi, diğer zamanlarda değildi ve giriş akışının sıfırlanması gerekiyordu. Bu yüzden karakterleri char char ile arkamıza koymam gerektiği durumlarda küçük bir döngü ekliyorum. Örneğin: bununla

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; 
    } 

Yani

söyleniyor, hemen hemen ben buna göre programımı düzenlemek mümkün oldu ve karakterleri yiyip bitiriyordu gördükten sonra her şey çalıştı.

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 

İşte tüm fonksiyonlarında azalmaya ana program var: Ben AssignmentOperator(Aop) olduğu ile Expression(Expr) en fazla sorun yaşıyor gibisin http://pastebin.com/qMB8h8vE

işlevleri ve Term

Bu

dilbilgisi olduğunu . Onları burada listeleyeceğim. Bir recusrive iniş ayrıştırıcı yazmak için

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

İnsanların okumasını istiyorsanız, lütfen kodunuzu (yapıya uygun bir şekilde) girin. – rici

+0

_you_ nasıl okuyabilir? Vay. –

+1

Özyineli soy ayrıştırıcılarının nasıl yazılacağına dair cevabımı görün: http://stackoverflow.com/questions/2245962/is-there-an-alternative-for-flex-bison-that-is-usable-on-8-bit -embedded-systems/2336769 # 2336769 –

cevap

1

, sen left recursion kurtulmak, LL forma dilbilgisi dönüştürmek gerekir. Bir peekToken ihtiyacımız olacak

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; 
} 

Not: Bu daha sonra böyle bir işlev şeye dönüşüyor

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

: kurallara

Term::= Term STAROP Primary | Primary 

için aşağıdaki gibi bir şey çıkacak onu tüketmeden bir sonraki belirtecin ileriye bakma işlevi. Aynı şeyi yapmak için getToken + ungetToken'u da kullanmak mümkündür.

+0

Bilgi için teşekkürler. Bunu yarın uygulamaya çalışacağım ve işe yarayıp yaramadığına bakacağım. Hala benim Aop fonksiyonum hakkında leary, ama bu biraz gerekli bilgi ekler. Ayrıca, sol özyineleme konusunu da dikkate aldım, bu yüzden BNF'yi EBNF'ye dönüştürdüm, ama bu bana istediğim kadar yardımcı olmadı. Her iki şekilde de, teşekkürler. – Abe