From 73ce62f3b9c2bbfc1e655a9df343389a733dc795 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 8 Nov 2016 22:36:07 +0200 Subject: [PATCH] Implement an actual expression parser Doing pretty much anything interesting with the syntax tree requires having access to expressions. --- source/programcompiler.cpp | 91 ++++++++++++-- source/programcompiler.h | 8 +- source/programparser.cpp | 238 ++++++++++++++++++++++++++++++------- source/programparser.h | 29 ++++- source/programsyntax.cpp | 71 ++++++++--- source/programsyntax.h | 144 +++++++++++++++++++--- 6 files changed, 490 insertions(+), 91 deletions(-) diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index b08f1737..19148312 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -59,14 +59,65 @@ ProgramCompiler::Formatter::Formatter(): else_if(false) { } -string ProgramCompiler::Formatter::format_expression(Expression &expr) +void ProgramCompiler::Formatter::visit(Literal &literal) { - return join(expr.tokens.begin(), expr.tokens.end(), string()); + formatted += literal.token; +} + +void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr) +{ + formatted += '('; + parexpr.expression->visit(*this); + formatted += ')'; +} + +void ProgramCompiler::Formatter::visit(VariableReference &var) +{ + formatted += var.name; +} + +void ProgramCompiler::Formatter::visit(MemberAccess &memacc) +{ + memacc.left->visit(*this); + formatted += format(".%s", memacc.member); +} + +void ProgramCompiler::Formatter::visit(UnaryExpression &unary) +{ + if(unary.prefix) + formatted += unary.oper; + unary.expression->visit(*this); + if(!unary.prefix) + formatted += unary.oper; +} + +void ProgramCompiler::Formatter::visit(BinaryExpression &binary) +{ + binary.left->visit(*this); + if(binary.assignment) + formatted += format(" %s ", binary.oper); + else + formatted += binary.oper; + binary.right->visit(*this); + formatted += binary.after; +} + +void ProgramCompiler::Formatter::visit(FunctionCall &call) +{ + formatted += format("%s(", call.name); + for(vector >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + { + if(i!=call.arguments.begin()) + formatted += ", "; + (*i)->visit(*this); + } + formatted += ')'; } void ProgramCompiler::Formatter::visit(ExpressionStatement &expr) { - formatted += format("%s;", format_expression(expr.expression)); + expr.expression->visit(*this); + formatted += ';'; } void ProgramCompiler::Formatter::visit(Block &block) @@ -84,7 +135,7 @@ void ProgramCompiler::Formatter::visit(Block &block) bool change_indent = (!formatted.empty() && !else_if); indent += change_indent; string spaces(indent*2, ' '); - for(vector::const_iterator i=block.body.begin(); i!=block.body.end(); ++i) + for(vector >::iterator i=block.body.begin(); i!=block.body.end(); ++i) { if(i!=block.body.begin()) formatted += '\n'; @@ -129,9 +180,17 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var) formatted += format("%s ", var.interface); formatted += format("%s %s", var.type, var.name); if(var.array) - formatted += format("[%s]", format_expression(var.array_size)); - if(!var.init_expression.empty()) - formatted += format(" = %s", format_expression(var.init_expression)); + { + formatted += '['; + if(var.array_size) + var.array_size->visit(*this); + formatted += ']'; + } + if(var.init_expression) + { + formatted += " = "; + var.init_expression->visit(*this); + } if(!parameter_list) formatted += ';'; } @@ -147,7 +206,7 @@ void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) { formatted += format("%s %s(", func.return_type, func.name); parameter_list = true; - for(vector::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) { if(i!=func.parameters.begin()) formatted += ", "; @@ -171,7 +230,11 @@ void ProgramCompiler::Formatter::visit(Conditional &cond) formatted += ' '; else_if = false; } - formatted += format("if(%s)\n", format_expression(cond.condition)); + + formatted += "if("; + cond.condition->visit(*this); + formatted += ")\n"; + cond.body.visit(*this); if(!cond.else_body.body.empty()) { @@ -186,13 +249,19 @@ void ProgramCompiler::Formatter::visit(Iteration &iter) { formatted += "for("; iter.init_statement->visit(*this); - formatted += format(" %s; %s)\n", format_expression(iter.condition), format_expression(iter.loop_expression)); + formatted += ' '; + iter.condition->visit(*this); + formatted += "; "; + iter.loop_expression->visit(*this); + formatted += ")\n"; iter.body.visit(*this); } void ProgramCompiler::Formatter::visit(Return &ret) { - formatted += format("return %s;", format_expression(ret.expression)); + formatted += "return "; + ret.expression->visit(*this); + formatted += ';'; } } // namespace GL diff --git a/source/programcompiler.h b/source/programcompiler.h index 9a825489..1959618f 100644 --- a/source/programcompiler.h +++ b/source/programcompiler.h @@ -21,8 +21,14 @@ public: Formatter(); - std::string format_expression(ProgramSyntax::Expression &); virtual void visit(ProgramSyntax::Block &); + virtual void visit(ProgramSyntax::Literal &); + virtual void visit(ProgramSyntax::ParenthesizedExpression &); + virtual void visit(ProgramSyntax::VariableReference &); + virtual void visit(ProgramSyntax::MemberAccess &); + virtual void visit(ProgramSyntax::UnaryExpression &); + virtual void visit(ProgramSyntax::BinaryExpression &); + virtual void visit(ProgramSyntax::FunctionCall &); virtual void visit(ProgramSyntax::ExpressionStatement &); virtual void visit(ProgramSyntax::Layout &); virtual void visit(ProgramSyntax::StructDeclaration &); diff --git a/source/programparser.cpp b/source/programparser.cpp index 1981f474..bf2d42da 100644 --- a/source/programparser.cpp +++ b/source/programparser.cpp @@ -9,6 +9,55 @@ namespace GL { using namespace ProgramSyntax; +ProgramParser::Operator ProgramParser::operators[] = +{ + { "[", 2, BINARY, LEFT_TO_RIGHT }, + { "(", 2, BINARY, LEFT_TO_RIGHT }, + { ".", 2, BINARY, LEFT_TO_RIGHT }, + { "++", 2, POSTFIX, LEFT_TO_RIGHT }, + { "--", 2, POSTFIX, LEFT_TO_RIGHT }, + { "++", 3, PREFIX, RIGHT_TO_LEFT }, + { "--", 3, PREFIX, RIGHT_TO_LEFT }, + { "+", 3, PREFIX, RIGHT_TO_LEFT }, + { "-", 3, PREFIX, RIGHT_TO_LEFT }, + { "~", 3, PREFIX, RIGHT_TO_LEFT }, + { "!", 3, PREFIX, RIGHT_TO_LEFT }, + { "*", 4, BINARY, LEFT_TO_RIGHT }, + { "/", 4, BINARY, LEFT_TO_RIGHT }, + { "%", 4, BINARY, LEFT_TO_RIGHT }, + { "+", 5, BINARY, LEFT_TO_RIGHT }, + { "-", 5, BINARY, LEFT_TO_RIGHT }, + { "<<", 6, BINARY, LEFT_TO_RIGHT }, + { ">>", 6, BINARY, LEFT_TO_RIGHT }, + { "<", 7, BINARY, LEFT_TO_RIGHT }, + { ">", 7, BINARY, LEFT_TO_RIGHT }, + { "<=", 7, BINARY, LEFT_TO_RIGHT }, + { ">=", 7, BINARY, LEFT_TO_RIGHT }, + { "==", 8, BINARY, LEFT_TO_RIGHT }, + { "!=", 8, BINARY, LEFT_TO_RIGHT }, + { "&", 9, BINARY, LEFT_TO_RIGHT }, + { "^", 10, BINARY, LEFT_TO_RIGHT }, + { "|", 11, BINARY, LEFT_TO_RIGHT }, + { "&&", 12, BINARY, LEFT_TO_RIGHT }, + { "^^", 13, BINARY, LEFT_TO_RIGHT }, + { "||", 14, BINARY, LEFT_TO_RIGHT }, + { "?", 15, BINARY, RIGHT_TO_LEFT }, + { ":", 15, BINARY, RIGHT_TO_LEFT }, + { "=", 16, BINARY, RIGHT_TO_LEFT }, + { "+=", 16, BINARY, RIGHT_TO_LEFT }, + { "-=", 16, BINARY, RIGHT_TO_LEFT }, + { "*=", 16, BINARY, RIGHT_TO_LEFT }, + { "/=", 16, BINARY, RIGHT_TO_LEFT }, + { "%=", 16, BINARY, RIGHT_TO_LEFT }, + { "<<=", 16, BINARY, RIGHT_TO_LEFT }, + { ">>=", 16, BINARY, RIGHT_TO_LEFT }, + { "&=", 16, BINARY, RIGHT_TO_LEFT }, + { "^=", 16, BINARY, RIGHT_TO_LEFT }, + { "|=", 16, BINARY, RIGHT_TO_LEFT }, + { ",", 17, BINARY, LEFT_TO_RIGHT }, + { { 0 }, 18, NO_OPERATOR, LEFT_TO_RIGHT } +}; + Module &ProgramParser::parse(const string &s) { source = s; @@ -129,14 +178,24 @@ string ProgramParser::parse_number() string ProgramParser::parse_other() { - string token; - while(iter!=source.end()) + if(iter==source.end()) + return string(); + + string token(1, *iter++); + for(unsigned i=1; (i<3 && iter!=source.end()); ++i) { - if(isalnum(*iter) || *iter=='_' || isspace(*iter)) + bool matched = false; + for(const Operator *j=operators; (!matched && j->type); ++j) + { + matched = (j->token[i]==*iter); + for(unsigned k=0; (matched && ktoken[k]); ++k) + matched = (j->token[k]==token[k]); + } + + if(!matched) break; + token += *iter++; - if(*iter==';' || *iter=='(' || *iter==')' || *iter=='[' || *iter==']') - break; } return token; @@ -214,9 +273,8 @@ string ProgramParser::expect_type() string ProgramParser::expect_identifier() { - static Regex re("^[a-zA-Z_][a-zA-Z0-9_]*$"); string token = parse_token(); - if(!re.match(token)) + if(!is_identifier(token)) throw runtime_error(format("Parse error at '%s': expected an identifier", token)); return token; } @@ -255,6 +313,12 @@ bool ProgramParser::is_type(const string &token) return is_builtin_type(token) || cur_module->structs.count(token); } +bool ProgramParser::is_identifier(const string &token) +{ + static Regex re("^[a-zA-Z_][a-zA-Z0-9_]*$"); + return re.match(token); +} + Node *ProgramParser::parse_global_declaration() { string token = peek_token(); @@ -298,7 +362,7 @@ Node *ProgramParser::parse_statement() else if(!token.empty()) { RefPtr expr = new ExpressionStatement; - parse_expression(expr->expression); + expr->expression = parse_expression(); expect(";"); return expr.release(); @@ -343,16 +407,13 @@ void ProgramParser::parse_block(Block &block, bool require_braces) if(have_braces) expect("{"); - while(1) + if(have_braces) { - string token = peek_token(); - if(token=="}") - break; - - block.body.push_back(parse_statement()); - if(!have_braces) - break; + while(peek_token()!="}") + block.body.push_back(parse_statement()); } + else + block.body.push_back(parse_statement()); block.use_braces = (require_braces || block.body.size()!=1); @@ -360,26 +421,124 @@ void ProgramParser::parse_block(Block &block, bool require_braces) expect("}"); } -void ProgramParser::parse_expression(Expression &expr) +Expression *ProgramParser::parse_expression(unsigned precedence) { - unsigned nesting_level = 0; - while(iter!=source.end()) + RefPtr left; + VariableReference *left_var = 0; + while(1) { string token = peek_token(); - if(token=="(" || token=="[") - ++nesting_level; - else if(token==")" || token=="]") + + const Operator *oper = 0; + for(Operator *i=operators; (!oper && i->type); ++i) + if(token==i->token && (!left || i->type!=PREFIX) && (left || i->type!=POSTFIX)) + oper = i; + + if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence)) { - if(!nesting_level) - break; - --nesting_level; + if(left) + return left.release(); + else + throw runtime_error(format("Parse error at '%s': expected an expression", token)); } - else if(token==";") - break; + else if(left) + { + if(token=="(") + { + if(!left_var) + throw runtime_error(format("Parse error at '%s': function name must be an identifier", token)); + left = parse_function_call(left_var); + } + else if(token==".") + { + RefPtr memacc = new MemberAccess; + memacc->left = left.release(); + parse_token(); + memacc->member = expect_identifier(); + left = memacc; + } + else if(oper && oper->type==POSTFIX) + { + RefPtr unary = new UnaryExpression; + unary->oper = parse_token(); + unary->prefix = false; + unary->expression = left.release(); + left = unary; + } + else if(oper && oper->type==BINARY) + left = parse_binary(left.release(), oper); + else + throw runtime_error(format("Parse error at '%s': expected an operator", token)); + left_var = 0; + } + else + { + if(token=="(") + { + parse_token(); + RefPtr parexpr = new ParenthesizedExpression; + parexpr->expression = parse_expression(); + expect(")"); + left = parexpr; + } + else if(is_identifier(token)) + { + RefPtr var = new VariableReference; + var->name = expect_identifier(); + left = var; + left_var = var.get(); + } + else if(oper && oper->type==PREFIX) + { + RefPtr unary = new UnaryExpression; + unary->oper = parse_token(); + unary->prefix = true; + unary->expression = parse_expression(oper->precedence); + left = unary; + } + else if(isdigit(token[0])) + { + RefPtr literal = new Literal; + literal->token = parse_token(); + left = literal; + } + else + throw runtime_error(format("Parse error at '%s': expected an expression", token)); + } + } +} - parse_token(); - expr.tokens.push_back(token); +BinaryExpression *ProgramParser::parse_binary(Expression *left, const Operator *oper) +{ + RefPtr binary = new BinaryExpression; + binary->left = left; + binary->oper = parse_token(); + if(binary->oper=="[") + { + binary->right = parse_expression(); + expect("]"); + binary->after = "]"; } + else + binary->right = parse_expression(oper->precedence+(oper->assoc==RIGHT_TO_LEFT)); + binary->assignment = (oper->precedence==16); + return binary.release(); +} + +FunctionCall *ProgramParser::parse_function_call(VariableReference *var) +{ + RefPtr call = new FunctionCall; + call->name = var->name; + call->constructor = is_type(call->name); + expect("("); + while(peek_token()!=")") + { + if(!call->arguments.empty()) + expect(","); + call->arguments.push_back(parse_expression()); + } + expect(")"); + return call.release(); } StructDeclaration *ProgramParser::parse_struct_declaration() @@ -424,13 +583,13 @@ VariableDeclaration *ProgramParser::parse_variable_declaration() var->array = true; if(!check("]")) { - parse_expression(var->array_size); + var->array_size = parse_expression(); expect("]"); } } if(check("=")) - parse_expression(var->init_expression); + var->init_expression = parse_expression(); expect(";"); return var.release(); @@ -461,12 +620,9 @@ FunctionDeclaration *ProgramParser::parse_function_declaration() void ProgramParser::parse_function_parameter_list(FunctionDeclaration &func) { expect("("); - while(1) + while(peek_token()!=")") { - string token = peek_token(); - if(token==")") - break; - else if(!func.parameters.empty()) + if(!func.parameters.empty()) expect(","); RefPtr var = new VariableDeclaration; @@ -497,7 +653,7 @@ Conditional *ProgramParser::parse_conditional() expect("if"); expect("("); RefPtr cond = new Conditional; - parse_expression(cond->condition); + cond->condition = parse_expression(); expect(")"); parse_block(cond->body, false); @@ -523,13 +679,13 @@ Iteration *ProgramParser::parse_iteration() else { RefPtr expr = new ExpressionStatement; - parse_expression(expr->expression); + expr->expression = parse_expression(); expect(";"); loop->init_statement = expr.release(); } - parse_expression(loop->condition); + loop->condition = parse_expression(); expect(";"); - parse_expression(loop->loop_expression); + loop->loop_expression = parse_expression(); expect(")"); parse_block(loop->body, false); @@ -541,7 +697,7 @@ Return *ProgramParser::parse_return() { expect("return"); RefPtr ret = new Return; - parse_expression(ret->expression); + ret->expression = parse_expression(); expect(";"); return ret.release(); } diff --git a/source/programparser.h b/source/programparser.h index 0a91c500..4bd6b70e 100644 --- a/source/programparser.h +++ b/source/programparser.h @@ -13,12 +13,36 @@ namespace GL { class ProgramParser { private: + enum OperatorType + { + NO_OPERATOR, + BINARY, + PREFIX, + POSTFIX + }; + + enum Associativity + { + LEFT_TO_RIGHT, + RIGHT_TO_LEFT + }; + + struct Operator + { + const char token[4]; + unsigned precedence; + OperatorType type; + Associativity assoc; + }; + std::string source; std::string::const_iterator iter; std::deque next_tokens; ProgramSyntax::Module main_module; ProgramSyntax::Module *cur_module; + static Operator operators[]; + public: ProgramSyntax::Module &parse(const std::string &); ProgramSyntax::Module &parse(IO::Base &); @@ -43,12 +67,15 @@ private: static bool is_qualifier(const std::string &); static bool is_builtin_type(const std::string &); bool is_type(const std::string &); + bool is_identifier(const std::string &); ProgramSyntax::Node *parse_global_declaration(); ProgramSyntax::Node *parse_statement(); ProgramSyntax::Layout *parse_layout(); void parse_block(ProgramSyntax::Block &, bool); - void parse_expression(ProgramSyntax::Expression &); + ProgramSyntax::Expression *parse_expression(unsigned = 0); + ProgramSyntax::BinaryExpression *parse_binary(ProgramSyntax::Expression *, const Operator *); + ProgramSyntax::FunctionCall *parse_function_call(ProgramSyntax::VariableReference *); ProgramSyntax::StructDeclaration *parse_struct_declaration(); ProgramSyntax::VariableDeclaration *parse_variable_declaration(); ProgramSyntax::FunctionDeclaration *parse_function_declaration(); diff --git a/source/programsyntax.cpp b/source/programsyntax.cpp index 09ba82c3..5b39d7f3 100644 --- a/source/programsyntax.cpp +++ b/source/programsyntax.cpp @@ -10,13 +10,61 @@ Block::Block(): use_braces(false) { } -Block::~Block() +void Block::visit(NodeVisitor &visitor) { - for(vector::iterator i=body.begin(); i!=body.end(); ++i) - delete *i; + visitor.visit(*this); } -void Block::visit(NodeVisitor &visitor) + +void Literal::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +void ParenthesizedExpression::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +void VariableReference::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +void MemberAccess::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +UnaryExpression::UnaryExpression(): + prefix(true) +{ } + +void UnaryExpression::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +BinaryExpression::BinaryExpression(): + assignment(false) +{ } + +void BinaryExpression::visit(NodeVisitor &visitor) +{ + visitor.visit(*this); +} + + +FunctionCall::FunctionCall(): + constructor(false) +{ } + +void FunctionCall::visit(NodeVisitor &visitor) { visitor.visit(*this); } @@ -71,12 +119,6 @@ FunctionDeclaration::FunctionDeclaration(): definition(false) { } -FunctionDeclaration::~FunctionDeclaration() -{ - for(vector::iterator i=parameters.begin(); i!=parameters.end(); ++i) - delete *i; -} - void FunctionDeclaration::visit(NodeVisitor &visitor) { visitor.visit(*this); @@ -95,15 +137,6 @@ void Return::visit(NodeVisitor &visitor) } -Iteration::Iteration(): - init_statement(0) -{ } - -Iteration::~Iteration() -{ - delete init_statement; -} - void Iteration::visit(NodeVisitor &visitor) { visitor.visit(*this); diff --git a/source/programsyntax.h b/source/programsyntax.h index 0013d82a..99ce8b9c 100644 --- a/source/programsyntax.h +++ b/source/programsyntax.h @@ -13,33 +13,130 @@ struct NodeVisitor; struct Node { +private: + Node &operator=(const Node &); +public: virtual ~Node() { } + virtual Node *clone() const = 0; virtual void visit(NodeVisitor &) = 0; }; +template +class NodePtr +{ +private: + T *node; + +public: + NodePtr(T *n = 0): node(n) { } + NodePtr(const NodePtr &p): node(clone(p.node)) { } + NodePtr &operator=(const NodePtr &p) { delete node; node = clone(p.node); return *this; } + ~NodePtr() { delete node; } + +private: + static T *clone(T *n) { return n ? n->clone() : 0; } + +public: + T *operator->() { return node; } + const T *operator->() const { return node; } + operator void *() const { return node; } +}; + +struct VariableDeclaration; + struct Block: Node { - std::vector body; + std::vector > body; bool use_braces; Block(); - virtual ~Block(); + virtual Block *clone() const { return new Block(*this); } + virtual void visit(NodeVisitor &); +}; + +struct Expression: Node +{ + virtual Expression *clone() const = 0; +}; + +struct Literal: Expression +{ + std::string token; + + virtual Literal *clone() const { return new Literal(*this); } + virtual void visit(NodeVisitor &); +}; + +struct ParenthesizedExpression: Expression +{ + NodePtr expression; + + virtual ParenthesizedExpression *clone() const { return new ParenthesizedExpression(*this); } + virtual void visit(NodeVisitor &); +}; + +struct VariableReference: Expression +{ + std::string name; + + virtual VariableReference *clone() const { return new VariableReference(*this); } + virtual void visit(NodeVisitor &); +}; + +struct MemberAccess: Expression +{ + NodePtr left; + std::string member; + + virtual MemberAccess *clone() const { return new MemberAccess(*this); } + virtual void visit(NodeVisitor &); +}; + +struct UnaryExpression: Expression +{ + std::string oper; + NodePtr expression; + bool prefix; + + UnaryExpression(); + + virtual UnaryExpression *clone() const { return new UnaryExpression(*this); } virtual void visit(NodeVisitor &); }; -struct Expression +struct BinaryExpression: Expression { - std::vector tokens; + NodePtr left; + std::string oper; + NodePtr right; + std::string after; + bool assignment; + + BinaryExpression(); - bool empty() const { return tokens.empty(); } + virtual BinaryExpression *clone() const { return new BinaryExpression(*this); } + virtual void visit(NodeVisitor &); +}; + +struct FunctionCall: Expression +{ + std::string name; + bool constructor; + std::vector > arguments; + + FunctionCall(); + + virtual FunctionCall *clone() const { return new FunctionCall(*this); } + virtual void visit(NodeVisitor &); }; struct ExpressionStatement: Node { - Expression expression; + NodePtr expression; + virtual ExpressionStatement *clone() const { return new ExpressionStatement(*this); } virtual void visit(NodeVisitor &); }; @@ -54,6 +151,7 @@ struct Layout: Node std::vector qualifiers; std::string interface; + virtual Layout *clone() const { return new Layout(*this); } virtual void visit(NodeVisitor &); }; @@ -64,6 +162,7 @@ struct StructDeclaration: Node StructDeclaration(); + virtual StructDeclaration *clone() const { return new StructDeclaration(*this); } virtual void visit(NodeVisitor &); }; @@ -75,11 +174,12 @@ struct VariableDeclaration: Node std::string type; std::string name; bool array; - Expression array_size; - Expression init_expression; + NodePtr array_size; + NodePtr init_expression; VariableDeclaration(); + virtual VariableDeclaration *clone() const { return new VariableDeclaration(*this); } virtual void visit(NodeVisitor &); }; @@ -91,6 +191,7 @@ struct InterfaceBlock: Node InterfaceBlock(); + virtual InterfaceBlock *clone() const { return new InterfaceBlock(*this); } virtual void visit(NodeVisitor &); }; @@ -98,42 +199,42 @@ struct FunctionDeclaration: Node { std::string return_type; std::string name; - std::vector parameters; + std::vector > parameters; bool definition; Block body; FunctionDeclaration(); - ~FunctionDeclaration(); + virtual FunctionDeclaration *clone() const { return new FunctionDeclaration(*this); } virtual void visit(NodeVisitor &); }; struct Conditional: Node { - Expression condition; + Expression *condition; Block body; Block else_body; + virtual Conditional *clone() const { return new Conditional(*this); } virtual void visit(NodeVisitor &); }; struct Iteration: Node { - Node *init_statement; - Expression condition; - Expression loop_expression; + NodePtr init_statement; + NodePtr condition; + NodePtr loop_expression; Block body; - Iteration(); - virtual ~Iteration(); - + virtual Iteration *clone() const { return new Iteration(*this); } virtual void visit(NodeVisitor &); }; struct Return: Node { - Expression expression; + NodePtr expression; + virtual Return *clone() const { return new Return(*this); } virtual void visit(NodeVisitor &); }; @@ -142,6 +243,13 @@ struct NodeVisitor virtual ~NodeVisitor() { } virtual void visit(Block &) { } + virtual void visit(Literal &) { } + virtual void visit(ParenthesizedExpression &) { } + virtual void visit(VariableReference &) { } + virtual void visit(MemberAccess &) { } + virtual void visit(UnaryExpression &) { } + virtual void visit(BinaryExpression &) { } + virtual void visit(FunctionCall &) { } virtual void visit(ExpressionStatement &) { } virtual void visit(Layout &) { } virtual void visit(StructDeclaration &) { } -- 2.43.0