#ifndef ASTDEFS_H #define ASTDEFS_H /* astdefs.h XIDEK: Extensible Script Language Development Kit Abstract Syntax Tree Definitions Copyright (c) 1996-2002 Parsifal Software. All Rights Reserved. For further information about this program or the AnaGram parser generator, please contact: Parsifal Software http://www.parsifalsoft.com info@parsifalsoft.com +1-800-879-2577, Voice/Fax +1-508-358-2564 P.O. Box 219 Wayland, MA 01778 USA */ #include "opcodes.h" #include "agarray.h" // Enumerate node types typedef enum { typeNull, typeScript, typeIfStatement, typeIfElseStatement, typeWhileStatement, typeForStatement, typeSimpleFor, typeDoStatement, typeRepeatStatement, typeBreak, typeContinue, typeExpressionStatement, typeStatementBlock, typeCommaExpression, typeAssignment, typeConditionalExpression, typeLogicalOrExpression, typeLogicalAndExpression, typeBinary, typeUnary, typeConstant, typeVariable, typeFunctionCall, typeDump, typePrint, typeReturn, } NodeType; // Array specifies number of subnodes for a given type of node extern const int nSubnodes[]; // AstNode structure to implement Abstract Syntax Tree class AstNode { friend class AbstractSyntaxTree; public: const NodeType type; // specify the type of the node FileLocation context; // Context of the node in the script // anonymous union allows subnode access by name or as an array of nodes union { AstNode *subnode[5]; struct { AstNode *statementList; } subnodesScript; struct { AstNode *condition, *statement; } subnodesIfStatement; struct { AstNode *condition, *onTrue, *onFalse; } subnodesIfElseStatement; struct { AstNode *condition, *statement; } subnodesWhileStatement; struct { AstNode *init, *cond, *inc, *statement; } subnodesForStatement; struct { AstNode *lvalue, *begin, *inc, *end, *statement; } subnodesSimpleFor; struct { AstNode *statement, *condition; } subnodesDoStatement; struct { AstNode *statement, *condition; } subnodesRepeatStatement; struct { AstNode *expression; } subnodesExpressionStatement; struct { AstNode *left, *right; } subnodesCommaExpression; struct { AstNode *lvalue; AstNode *expression; } subnodesAssignment; struct { AstNode *condition, *onTrue, *onFalse; } subnodesConditionalExpression; struct { AstNode *left, *right; } subnodesLogicalOrExpression; struct { AstNode *left, *right; } subnodesLogicalAndExpression; struct { AstNode *left, *right; } subnodesBinary; struct { AstNode *operand; } subnodesUnary; struct { AstNode *expression; } subnodesReturn; }; protected: // AstNode constructor: subnode specifiers default to 0 // No default constructor. A node _must_ have a context and a type AstNode(const FileLocation &, NodeType t, AstNode * =0, AstNode * =0, AstNode * =0, AstNode * =0, AstNode * =0); virtual ~AstNode() {} public: void reportError(const char *msg) const; }; // Special node classes class ListNode : public AstNode { friend class AbstractSyntaxTree; public: AgArray list; protected: ListNode(const FileLocation &, NodeType t, const AgStack&); ~ListNode() {} }; class AssignmentNode : public AstNode { friend class AbstractSyntaxTree; public: Opcode opcode; protected: AssignmentNode(const FileLocation &, AstNode *d, Opcode op, AstNode *x); ~AssignmentNode() {} }; class BinaryNode : public AstNode { friend class AbstractSyntaxTree; public: Opcode opcode; protected: BinaryNode(const FileLocation &, Opcode op, AstNode *, AstNode *); ~BinaryNode() {} }; class UnaryNode : public AstNode { friend class AbstractSyntaxTree; public: Opcode opcode; protected: UnaryNode(const FileLocation &, Opcode op, AstNode *); ~UnaryNode() {} }; class ConstantNode : public AstNode { friend class AbstractSyntaxTree; public: Value value; protected: ConstantNode(const FileLocation &, const Value &); ~ConstantNode() {} }; class VariableNode : public AstNode { friend class AbstractSyntaxTree; public: const AgString name; protected: VariableNode(const FileLocation &, const AgString &); ~VariableNode() {} }; class FunctionCallNode : public AstNode { friend class AbstractSyntaxTree; public: const AgString name; const AgStack argList; FunctionCallNode(const FileLocation &, const AgString &, const AgStack &); }; class AbstractSyntaxTree { protected: AgStack nodeStack; AstNode *stackNode(AstNode *n) { nodeStack.push(n); return n;} virtual FileLocation context() const {return FileLocation();} public: AstNode *root; AbstractSyntaxTree() : root(0) {} AbstractSyntaxTree(const AbstractSyntaxTree &t) : nodeStack(t.nodeStack), root(t.root) {} virtual ~AbstractSyntaxTree(); AstNode *node(NodeType t, AstNode *x1 = 0, AstNode *x2 = 0, AstNode *x3 = 0, AstNode *x4 = 0, AstNode *x5 = 0) { return stackNode(new AstNode(context(), t, x1, x2, x3, x4, x5)); } AstNode *listNode(NodeType t, const AgStack &l) { return stackNode(new ListNode(context(), t, l)); } AstNode *assignmentNode(AstNode *d, Opcode op, AstNode *x) { return stackNode(new AssignmentNode(context(), d, op, x)); } AstNode *binaryNode(Opcode op, AstNode *left, AstNode *right) { return stackNode(new BinaryNode(context(), op, left, right)); } AstNode *unaryNode(Opcode op, AstNode *operand) { return stackNode(new UnaryNode(context(), op, operand)); } AstNode *constantNode(const Value &x) { return stackNode(new ConstantNode(context(), x)); } AstNode *variableNode( const AgString &name) { return stackNode(new VariableNode(context(), name)); } AstNode *functionCallNode(const AgString &name, const AgStack &n) { return stackNode(new FunctionCallNode(context(), name, n)); } }; // Function to build an abstract syntax tree AbstractSyntaxTree buildTree(const char *); #endif