views:

102

answers:

1

I'm writing a compiler for a small language, and my Parser class is currently in charge of building an AST for use later. However, recursive expressions are not working correctly because the vector in each AST node that holds child nodes are not working correctly. Currently my AST's header file looks like this:

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

Here's the expression parsing code that is causing trouble:

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

An example expression that doesn't work is + 1 + 2 + 3 4. It should parse into an AST like this: + [1, + [2, + [3, 4]], but instead I get this: + [1, + []]

Any advice on what I'm doing wrong?

A: 

parent.children.push_back(expr) copies the expression. Hence, it calls AST::AST(AST const&). A bug in that could certainly cause the problem you see. However, without the code, we can't find bugs in it.

MSalters