2009-12-02 5 views
0

저는 작은 언어 용 컴파일러를 작성하고 있습니다. 파서 클래스는 현재 나중에 사용할 수 있도록 AST를 작성하고 있습니다. 그러나 자식 노드가있는 각 AST 노드의 벡터가 올바르게 작동하지 않기 때문에 재귀식이 올바르게 작동하지 않습니다. 현재 내 AST의 헤더 파일은 다음과 같습니다구문 분석 오류를 일으키는 복사 생성자 버그는 무엇입니까?

class AST 
{ 
public: 
    enum ASTtype {nil, fdecl, pdecl, vdecl, rd, wr, set, rdLV, setLV, exprLV, add, sub, mul, fcall, 
     divide, mod, lt, gt, lte, gte, eq, ne, aAnd, aOr, aNot, aNeg, nConst, t, f, vs, dl, loop, 
     cond, ss}; 
    enum scalarType {tNA, tINVALID, tINT, tLONG, tBOOL}; 
    AST(); 
    AST (AST const&); 
    AST (ASTtype); 
    AST (ASTtype, std::string); 
    void addChild(AST); 
    ASTtype getNodeType(); 
    std::string text; 
    ASTtype nodeType; 
    int size; 
    scalarType evalType; 
    std::vector<AST> children; 
}; 

여기에 문제의 원인이되는 표현 구문 분석 코드입니다 :

void Parser::e(AST& parent) 
{ 
    AST expr; 
    AST::ASTtype check = AST::nil; 
    bool binOp = false; 

    switch (lookahead.type) 
    { 
     case Lexer::AND : check = AST::aAnd ; binOp = true; break; 
     case Lexer::OR  : check = AST::aOr ; binOp = true; break; 
     case Lexer::NOT : check = AST::aNot ; break; 
     case Lexer::NEG : check = AST::aNeg ; break; 
     case Lexer::PLUS : check = AST::add ; binOp = true; break; 
     case Lexer::MINUS : check = AST::sub ; binOp = true; break; 
     case Lexer::SPLAT : check = AST::mul ; binOp = true; break; 
     case Lexer::FSLASH : check = AST::divide; binOp = true; break; 
     case Lexer::MOD : check = AST::mod ; binOp = true; break; 
     case Lexer::EQ  : check = AST::eq ; binOp = true; break; 
     case Lexer::LT  : check = AST::lt ; binOp = true; break; 
     case Lexer::GT  : check = AST::gt ; binOp = true; break; 
     case Lexer::GTE : check = AST::gte ; binOp = true; break; 
     case Lexer::LTE : check = AST::lte ; binOp = true; break; 
     case Lexer::NE  : check = AST::ne ; binOp = true; break; 
    } 
    if (check != AST::nil && binOp) 
    { 
     match(lookahead.type); 
     expr = AST(check); 
     e(expr); 
     e(expr); 
    } else if (check != AST::nil && !binOp) { 
     match(lookahead.type); 
     expr = AST(check); 
    } else if (lookahead.type == Lexer::IDENT) { 

     if (symbols.resolve(lookahead.text).sym_type == symbol::FUNC) 
     { 
      expr = AST(AST::fcall, lookahead.text); 
      match(Lexer::IDENT); 
      while (lookahead.type != Lexer::BANG) 
      { 
       e(expr); 
      } 
      match(Lexer::BANG); 
     } else { 
      expr = AST(AST::exprLV); 
      lv(expr); 
     } 
    } else if (lookahead.type == Lexer::T) { 
     match(Lexer::T); //true 
     expr = AST(AST::t); 
    } else if (lookahead.type == Lexer::F) { 
     match(Lexer::F); //false 
     expr = AST(AST::f); 
    } else { 
     expr = AST(AST::nConst, lookahead.text); 
     match(Lexer::NUM); 
    } 
    parent.children.push_back(expr); 
} 

작동하지 않습니다 예를 발현 + 1 + 2 + 3 4입니다. + [1 + [2 + [3, 4], 을 대신 나는이 얻을 : 그것은이 같은 AST로 해석해야하는지에 + [1 + []]

어떤 조언을 I 내가 잘못 했니?

+0

"copy constructor bug"에 대한 자세한 정보를 제공 할 수 있습니까? '아이들'에 다른 AST가있는 'AST'가 올바로 복사되지 않는다면 말입니까? 복사 생성자에 버그가있는 경우 왜 복사 생성자가 아닌'e()'에 대한 코드를 포함 시켰습니까? –

+0

복사 생성자를 추측으로 말합니다. 나는 솔직히 문제를 일으키는 것이 무엇인지 모르겠다. 누군가가 e()를 보았을 때 나는 간과 한 C++의 버그 또는 근본적인 오해를 드러 낼 수 있다고 생각했다. – iand675

답변

0

parent.children.push_back(expr)은 표현식을 복사합니다. 따라서 AST::AST(AST const&)이 호출됩니다. 버그는 분명히 당신이 보는 문제를 일으킬 수 있습니다. 그러나 코드가 없으면 버그가 발견되지 않습니다.