// $Id: ast.h,v 1.5 1999/03/09 14:37:15 shields Exp $ copyright notice #ifndef ast_INCLUDED #define ast_INCLUDED #include "config.h" #include <assert.h> #include <string.h> #include <stdlib.h> #include "stream.h" #include "symbol.h" class Parser; class SemanticEnvironment; // // Global function used when the space for a dynamic object is // preallocated,but we need to call a constructor to initialize the // space. // // inline static void *operator new(size_t, void *p) { return p; } // //********************************************************************************** // // This file contains the definitions of the classes used to construct the // AST representation of a Java program. // // The node Ast is a base class of all other classes. (The name of the other classes // start with the prefix "Ast".) The nodes associated with executable statements // (e.g., AstIfStatement) are subclasses of AstStatement and nodes associated with // expressions (e.g., AstBinaryExpression) are subclasses of AstExpression. // // The information contained in the AST nodes is described by a grammar where // each rule consists of a left-hand side nonterminal followed by "-->" followed // by a right-hand side symbol or a sequence enclosed in the pair of symbols // "<" and ">". In defining the symbols, the following notation is used: // // Symbols that are capitalized (e.g., Type) are nonterminals. Symbols that are // in all upper case (e.g., PACKAGE) represent node kinds. Symbols that contain // the substring "_token" represents tokens in the source file. The suffix "_opt" // indicates that a symbol is optional. For example, if Super_opt appears in a // rule, it indicates that either Super or null can be expected. When a symbol // is plural (e.g., Modifiers), it indicates zero or more instances of such a // symbol (a list to be precised) can be expected. Thus, when "Modifiers" is // specified in the right-hand side of a rule either no Modifier or a sequence // of them may appear. // // Implementation Notes: // // A complete AST tree for a Java program always contains an // AstCompilationUnit root node. The kind of that node is // Ast::EMPTY_COMPILATION for a tree with no type declaration, // Ast::COMPILATION for a tree constructed from an otherwise valid program // and Ast::BAD_COMPILATION for a tree constructed from an invalid program. // // Since the AST is a tree data structure, each node contains a virtual // destructor that can delete its subtrees. Therefore, a user can dispose of // a whole ast tree (or subtree) by simply deleting the root node. // // When the preprocessor variable TEST is defined the user may print out // an AST tree to standard output by calling the virtual function "print" // for the root node of the tree. // // DynamicArrays are used to implement lists. This representation has the // advantage of being very flexible and easy to use. However, it may be slightly // less time-efficient than a straightforward linked list. My guess is no more // that 10% which justifies this use, but that should be checked at some point... // //********************************************************************************** // // This is a complete list of all Ast nodes declared here to allow // forward references. // class Ast; class AstListNode; class AstStatement; class AstExpression; class AstPrimitiveType; class AstArrayType; class AstSimpleName; class AstPackageDeclaration; class AstImportDeclaration; class AstCompilationUnit; class AstModifier; class AstEmptyDeclaration; class AstClassDeclaration; class AstClassBody; class AstArrayInitializer; class AstBrackets; class AstVariableDeclaratorId; class AstVariableDeclarator; class AstFieldDeclaration; class AstFormalParameter; class AstMethodDeclarator; class AstMethodDeclaration; class AstStaticInitializer; class AstThisCall; class AstSuperCall; class AstConstructorBlock; class AstConstructorDeclaration; class AstInterfaceDeclaration; class AstBlock; class AstLocalVariableDeclarationStatement; class AstIfStatement; class AstEmptyStatement; class AstExpressionStatement; class AstCaseLabel; class AstDefaultLabel; class AstSwitchBlockStatement; class AstSwitchStatement; class AstWhileStatement; class AstDoStatement; class AstForStatement; class AstBreakStatement; class AstContinueStatement; class AstReturnStatement; class AstThrowStatement; class AstSynchronizedStatement; class AstCatchClause; class AstFinallyClause; class AstTryStatement; class AstIntegerLiteral; class AstLongLiteral; class AstFloatingPointLiteral; class AstDoubleLiteral; class AstTrueLiteral; class AstFalseLiteral; class AstStringLiteral; class AstCharacterLiteral; class AstNullLiteral; class AstThisExpression; class AstSuperExpression; class AstParenthesizedExpression; class AstClassInstanceCreationExpression; class AstDimExpr; class AstArrayCreationExpression; class AstFieldAccess; class AstMethodInvocation; class AstArrayAccess; class AstPostUnaryExpression; class AstPreUnaryExpression; class AstCastExpression; class AstBinaryExpression; class AstTypeExpression; class AstConditionalExpression; class AstAssignmentExpression; class CaseElement; class StoragePool; // // The Ast base node. // class Ast { public: // // These tags are used to identify nodes that can represent more than // one kind of objects. // enum AstTag { NO_TAG, PRIMITIVE_TYPE, STATEMENT, EXPRESSION, MODIFIER, STATIC_FIELD, UNPARSED, _num_tags = MODIFIER }; // // These are the different kinds for the Ast objects. // enum AstKind { AST, IDENTIFIER, DOT, INTEGER_LITERAL, LONG_LITERAL, FLOATING_POINT_LITERAL, DOUBLE_LITERAL, TRUE_LITERAL, FALSE_LITERAL, STRING_LITERAL, CHARACTER_LITERAL, NULL_LITERAL, ARRAY_ACCESS, CALL, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTHESIZED_EXPRESSION, CLASS_CREATION, ARRAY_CREATION, POST_UNARY, PRE_UNARY, CAST, CHECK_AND_CAST, BINARY, TYPE, CONDITIONAL, ASSIGNMENT, _num_expression_kinds, DIM = _num_expression_kinds, LIST_NODE, INT, DOUBLE, CHAR, LONG, FLOAT, BYTE, SHORT, BOOLEAN, VOID_TYPE, ARRAY, COMPILATION, BAD_COMPILATION, EMPTY_COMPILATION, PACKAGE_COMPONENT, PACKAGE_NAME, PACKAGE, IMPORT, EMPTY_DECLARATION, CLASS, CLASS_BODY, PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE, STRICTFP, SYNCHRONIZED, TRANSIENT, VOLATILE, FIELD, VARIABLE_DECLARATOR, VARIABLE_DECLARATOR_NAME, BRACKETS, METHOD, METHOD_DECLARATOR, PARAMETER, CONSTRUCTOR, INTERFACE, ARRAY_INITIALIZER, STATIC_INITIALIZER, THIS_CALL, SUPER_CALL, BLOCK, CONSTRUCTOR_BLOCK, LOCAL_VARIABLE_DECLARATION, IF, EMPTY_STATEMENT, EXPRESSION_STATEMENT, SWITCH, SWITCH_BLOCK, CASE, DEFAULT, WHILE, DO, FOR, BREAK, CONTINUE, RETURN, THROW, SYNCHRONIZED_STATEMENT, TRY, CATCH, FINALLY, _num_kinds }; #ifdef TEST typedef AstKind Kind; typedef AstTag Tag; #else typedef unsigned short Kind; typedef unsigned char Tag; #endif Kind kind; // every node has a unique kind... Tag class_tag; // Some subsets of nodes are grouped together to form a class of nodes. unsigned char generated; // "generated" is a boolean value that indicates whether ot not a node // is associated with a construct in a source file or that is was generated // by the compiler. See functions "gen_ ..." and "new_ ..." below. #ifdef TEST unsigned id; static unsigned count; Ast() : id(++count) {} #endif virtual ~Ast(); #ifdef TEST virtual void Print(LexStream &); #endif // // Given an Ast tree, check whether or not it is a Name - simple or qualified. // bool IsName(); bool IsLeftHandSide(); bool IsGenerated(); // // The Conversion functions below are provided as a convenient way to // cast a generic Ast node into a specific node. Note that if one knows // the type of a node for sure, it is more efficient to use a specific // cast expression. For example, if one knows that a "Ast *p" pointer // dereferences a FieldDeclaration then a cast expression should be // used to cast p, as follows: // // AstFieldDeclaration *fp = (FieldDeclaration *) p; // // However, if p points to a ClassBodyDeclaration which may be // either a FieldDeclaration, MethodDeclaration, ConstructorDeclaration // StaticInitializer, ClassDeclaration, InterfaceDeclaration or a block // then the following sequence of code may be used: // // AstFieldDeclaration *fp; // AstMethodDeclaration *mp; // AstConstructorDeclaration *cp; // AstStaticInitializer *sp; // AstClassDeclaration *Cp; // 1.1 only // AstInterfaceDeclaration *Ip; // 1.1 only // AstBlock *Bp; // 1.1 only // // if (fp = p -> FieldDeclaration()) // ... // else if (mp = p -> MethodDeclaration()) // ... // else if (cp = p -> ConstructorDeclaration()) // ... // else if (sp = p -> StaticInitializer()) // ... // else if (Cp = p -> ClassDeclaration()) // ... // else if (Ip = p -> InterfaceDeclaration()) // ... // else if (Bp = p -> Block()) // ... // // // These cast functions are used for classes that represent more than // one kind of nodes. // AstStatement *StatementCast() { return (AstStatement *) (class_tag == STATEMENT ? this : NULL); } AstExpression *ExpressionCast() { return (AstExpression *) (class_tag == EXPRESSION ? this : NULL); } AstPrimitiveType *PrimitiveTypeCast() { return (AstPrimitiveType *) (class_tag == PRIMITIVE_TYPE ? this : NULL); } AstModifier *ModifierCast() { return (AstModifier *) (class_tag == MODIFIER ? this : NULL); } AstFieldDeclaration *StaticFieldCast() { return (AstFieldDeclaration *) (class_tag == STATIC_FIELD ? this : NULL); } AstClassBody *UnparsedClassBodyCast() { return (AstClassBody *) (class_tag == UNPARSED ? this : NULL); } AstInterfaceDeclaration *UnparsedInterfaceBodyCast() { return (AstInterfaceDeclaration *) (class_tag == UNPARSED ? this : NULL); } // // These cast functions are used for classes that represent exactly // one kind of node. // AstListNode *ListNodeCast() { return (AstListNode *) (kind == LIST_NODE ? this : NULL); } AstArrayType *ArrayTypeCast() { return (AstArrayType *) (kind == ARRAY ? this : NULL); } AstSimpleName *SimpleNameCast() { return (AstSimpleName *) (kind == IDENTIFIER ? this : NULL); } AstPackageDeclaration *PackageDeclarationCast() { return (AstPackageDeclaration *) (kind == PACKAGE ? this : NULL); } AstImportDeclaration *ImportDeclarationCast() { return (AstImportDeclaration *) (kind == IMPORT ? this : NULL); } AstCompilationUnit *CompilationUnitCast() { return (AstCompilationUnit *) (kind == COMPILATION || kind == BAD_COMPILATION || kind == EMPTY_COMPILATION ? this : NULL); } AstCompilationUnit *BadCompilationUnitCast() { return (AstCompilationUnit *) (kind == BAD_COMPILATION ? this : NULL); } AstCompilationUnit *EmptyCompilationUnitCast() { return (AstCompilationUnit *) (kind == EMPTY_COMPILATION ? this : NULL); } AstEmptyDeclaration *EmptyDeclarationCast() { return (AstEmptyDeclaration *) (kind == EMPTY_DECLARATION ? this : NULL); } AstClassDeclaration *ClassDeclarationCast() { return (AstClassDeclaration *) (kind == CLASS ? this : NULL); } AstArrayInitializer *ArrayInitializerCast() { return (AstArrayInitializer *) (kind == ARRAY_INITIALIZER ? this : NULL); } AstBrackets *BracketsCast() { return (AstBrackets *) (kind == BRACKETS ? this : NULL); } AstVariableDeclaratorId *VariableDeclaratorIdCast() { return (AstVariableDeclaratorId *) (kind == VARIABLE_DECLARATOR_NAME ? this : NULL); } AstVariableDeclarator *VariableDeclaratorCast() { return (AstVariableDeclarator *) (kind == VARIABLE_DECLARATOR ? this : NULL); } AstFieldDeclaration *FieldDeclarationCast() { return (AstFieldDeclaration *) (kind == FIELD ? this : NULL); } AstFormalParameter *FormalParameterCast() { return (AstFormalParameter *) (kind == PARAMETER ? this : NULL); } AstMethodDeclarator *MethodDeclaratorCast() { return (AstMethodDeclarator *) (kind == METHOD_DECLARATOR ? this : NULL); } AstMethodDeclaration *MethodDeclarationCast() { return (AstMethodDeclaration *) (kind == METHOD ? this : NULL); } AstStaticInitializer *StaticInitializerCast() { return (AstStaticInitializer *) (kind == STATIC_INITIALIZER ? this : NULL); } AstThisCall *ThisCallCast() { return (AstThisCall *) (kind == THIS_CALL ? this : NULL); } AstSuperCall *SuperCallCast() { return (AstSuperCall *) (kind == SUPER_CALL ? this : NULL); } AstConstructorBlock *ConstructorBlockCast() { return (AstConstructorBlock *) (kind == CONSTRUCTOR_BLOCK ? this : NULL); } AstConstructorDeclaration *ConstructorDeclarationCast() { return (AstConstructorDeclaration *) (kind == CONSTRUCTOR ? this : NULL); } AstInterfaceDeclaration *InterfaceDeclarationCast() { return (AstInterfaceDeclaration *) (kind == INTERFACE ? this : NULL); } AstBlock *BlockCast() { return (AstBlock *) (kind == BLOCK ? this : NULL); } AstLocalVariableDeclarationStatement *LocalVariableDeclarationStatementCast() { return (AstLocalVariableDeclarationStatement *) (kind == LOCAL_VARIABLE_DECLARATION ? this : NULL); } AstIfStatement *IfStatementCast() { return (AstIfStatement *) (kind == IF ? this : NULL); } AstEmptyStatement *EmptyStatementCast() { return (AstEmptyStatement *) (kind == EMPTY_STATEMENT ? this : NULL); } AstExpressionStatement *ExpressionStatementCast() { return (AstExpressionStatement *) (kind == EXPRESSION_STATEMENT ? this : NULL); } AstCaseLabel *CaseLabelCast() { return (AstCaseLabel *) (kind == CASE ? this : NULL); } AstDefaultLabel *DefaultLabelCast() { return (AstDefaultLabel *) (kind == DEFAULT ? this : NULL); } AstSwitchBlockStatement *SwitchBlockStatementCast() { return (AstSwitchBlockStatement *) (kind == SWITCH_BLOCK ? this : NULL); } AstSwitchStatement *SwitchStatementCast() { return (AstSwitchStatement *) (kind == SWITCH ? this : NULL); } AstWhileStatement *WhileStatementCast() { return (AstWhileStatement *) (kind == WHILE ? this : NULL); } AstDoStatement *DoStatementCast() { return (AstDoStatement *) (kind == DO ? this : NULL); } AstForStatement *ForStatementCast() { return (AstForStatement *) (kind == FOR ? this : NULL); } AstBreakStatement *BreakStatementCast() { return (AstBreakStatement *) (kind == BREAK ? this : NULL); } AstContinueStatement *ContinueStatementCast() { return (AstContinueStatement *) (kind == CONTINUE ? this : NULL); } AstReturnStatement *ReturnStatementCast() { return (AstReturnStatement *) (kind == RETURN ? this : NULL); } AstThrowStatement *ThrowStatementCast() { return (AstThrowStatement *) (kind == THROW ? this : NULL); } AstSynchronizedStatement *SynchronizedStatementCast() { return (AstSynchronizedStatement *) (kind == SYNCHRONIZED_STATEMENT ? this : NULL); } AstCatchClause *CatchClauseCast() { return (AstCatchClause *) (kind == CATCH ? this : NULL); } AstFinallyClause *FinallyClauseCast() { return (AstFinallyClause *) (kind == FINALLY ? this : NULL); } AstTryStatement *TryStatementCast() { return (AstTryStatement *) (kind == TRY ? this : NULL); } AstIntegerLiteral *IntegerLiteralCast() { return (AstIntegerLiteral *) (kind == INTEGER_LITERAL ? this : NULL); } AstLongLiteral *LongLiteralCast() { return (AstLongLiteral *) (kind == LONG_LITERAL ? this : NULL); } AstFloatingPointLiteral *FloatingPointLiteralCast() { return (AstFloatingPointLiteral *) (kind == FLOATING_POINT_LITERAL ? this : NULL); } AstDoubleLiteral *DoubleLiteralCast() { return (AstDoubleLiteral *) (kind == DOUBLE_LITERAL ? this : NULL); } AstTrueLiteral *TrueLiteralCast() { return (AstTrueLiteral *) (kind == TRUE_LITERAL ? this : NULL); } AstFalseLiteral *FalseLiteralCast() { return (AstFalseLiteral *) (kind == FALSE_LITERAL ? this : NULL); } AstStringLiteral *StringLiteralCast() { return (AstStringLiteral *) (kind == STRING_LITERAL ? this : NULL); } AstCharacterLiteral *CharacterLiteralCast() { return (AstCharacterLiteral *) (kind == CHARACTER_LITERAL ? this : NULL); } AstNullLiteral *NullLiteralCast() { return (AstNullLiteral *) (kind == NULL_LITERAL ? this : NULL); } AstThisExpression *ThisExpressionCast() { return (AstThisExpression *) (kind == THIS_EXPRESSION ? this : NULL); } AstSuperExpression *SuperExpressionCast() { return (AstSuperExpression *) (kind == SUPER_EXPRESSION ? this : NULL); } AstParenthesizedExpression *ParenthesizedExpressionCast() { return (AstParenthesizedExpression *) (kind == PARENTHESIZED_EXPRESSION ? this : NULL); } AstClassInstanceCreationExpression *ClassInstanceCreationExpressionCast() { return (AstClassInstanceCreationExpression *) (kind == CLASS_CREATION ? this : NULL); } AstDimExpr *DimExprCast() { return (AstDimExpr *) (kind == DIM ? this : NULL); } AstArrayCreationExpression *ArrayCreationExpressionCast() { return (AstArrayCreationExpression *) (kind == ARRAY_CREATION ? this : NULL); } AstFieldAccess *FieldAccessCast() { return (AstFieldAccess *) (kind == DOT ? this : NULL); } AstMethodInvocation *MethodInvocationCast() { return (AstMethodInvocation *) (kind == CALL ? this : NULL); } AstArrayAccess *ArrayAccessCast() { return (AstArrayAccess *) (kind == ARRAY_ACCESS ? this : NULL); } AstPostUnaryExpression *PostUnaryExpressionCast() { return (AstPostUnaryExpression *) (kind == POST_UNARY ? this : NULL); } AstPreUnaryExpression *PreUnaryExpressionCast() { return (AstPreUnaryExpression *) (kind == PRE_UNARY ? this : NULL); } AstCastExpression *CastExpressionCast() { return (AstCastExpression *) (kind == CAST || kind == CHECK_AND_CAST ? this : NULL); } AstBinaryExpression *BinaryExpressionCast() { return (AstBinaryExpression *) (kind == BINARY ? this : NULL); } AstTypeExpression *TypeExpressionCast() { return (AstTypeExpression *) (kind == TYPE ? this : NULL); } AstConditionalExpression *ConditionalExpressionCast() { return (AstConditionalExpression *) (kind == CONDITIONAL ? this : NULL); } AstAssignmentExpression *AssignmentExpressionCast() { return (AstAssignmentExpression *) (kind == ASSIGNMENT ? this : NULL); } virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return 0; } virtual LexStream::TokenIndex RightToken() { return 0; } }; // // This AstArray template class can be used to construct a dynamic // array of arbitrary objects. The space for the array is allocated in // blocks of size 2**LOG_BLKSIZE. In declaring a Ast array the user // may specify a value for LOG_BLKSIZE which by default is 6. Also, // as the array is implemented using a base+offset strategy, the user // may also specify the number of "slots" to add to the base when the // current base runs out of space. Each slot points to a block. // template <class T> class AstArray { enum { DEFAULT_LOG_BLKSIZE = 4, DEFAULT_BASE_INCREMENT = 16 }; T **base; int base_size, top, size; StoragePool *pool; unsigned short log_blksize, base_increment; inline size_t Blksize() { return (1 << log_blksize); } // // Allocate another block of storage for the Ast array. // inline void AllocateMoreSpace(); public: // // This function is used to reset the size of a Ast array without // allocating or deallocting space. It may be invoked with an integer // argument n which indicates the new size or with no argument which // indicates that the size should be reset to 0. // void Reset(const int n = 0) { if (n < 0 || n > size) assert(0); top = n; } // // Return length of the Ast array. // int Length() { return top; } // // Return a reference to the ith element of the Ast array. // // Note that no check is made here to ensure that 0 <= i < top. // Such a check might be useful for debugging and a range exception // should be thrown if it yields true. // T& operator[](const int i) { return base[i >> log_blksize][i]; } // // Add an element to the Ast array and return the top index. // int NextIndex() { int i = top++; if (i == size) AllocateMoreSpace(); return i; } // // Add an element to the Ast array and return a reference to // that new element. // T& Next() { int i = NextIndex(); return base[i >> log_blksize][i]; } // // Constructor of a ast array. // AstArray(StoragePool *pool_, unsigned estimate = 0) : pool(pool_) { if (estimate == 0) { log_blksize = DEFAULT_LOG_BLKSIZE; base_increment = DEFAULT_BASE_INCREMENT; } else { for (log_blksize = 1; (((unsigned) 1 << log_blksize) < estimate) && (log_blksize < 31); log_blksize++) ; if (log_blksize <= DEFAULT_LOG_BLKSIZE) base_increment = 1; else if (log_blksize < 13) { base_increment = (unsigned) 1 << (log_blksize - 4); log_blksize = 4; } else { base_increment = (unsigned) 1 << (log_blksize - 8); log_blksize = 8; } base_increment++; // add a little margin to avoid reallocating the base. } base_size = 0; size = 0; top = 0; base = NULL; } // // Destructor of an Ast array. // ~AstArray() { assert(0); } }; // // The Ast base node. // class AstListNode : public Ast { public: AstListNode *next; Ast *element; unsigned index; AstListNode() { Ast::kind = Ast::LIST_NODE; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; #ifdef TEST --count; // don't count these nodes #endif } ~AstListNode() {} }; class AstStatement : public Ast { public: bool is_reachable, can_complete_normally; // // Note that for efficiency reasons AstStatement does not have a constructor. // Therefore, subclasses that are derived from AstStatement are expected to // initialize the fields is_reachable and can_complete_normally appropriately. // virtual ~AstStatement(); virtual Ast *Clone(StoragePool *) { return (Ast *) NULL; } virtual LexStream::TokenIndex LeftToken() { return 0; } virtual LexStream::TokenIndex RightToken() { return 0; } }; class AstExpression : public Ast { public: LiteralValue *value; Symbol *symbol; // // Note that for efficiency reasons AstExpression does not have a constructor. // However, subclasses that are derived from AstExpression are expected to // initialize the fields value and symbol to NULL as indicated below: // // AstExpression() : value(NULL), // symbol(NULL) // {} // virtual ~AstExpression(); bool IsConstant() { return (value != NULL); } TypeSymbol *Type() { return (TypeSymbol *) (symbol ? (symbol -> Kind() == Symbol::TYPE ? (TypeSymbol *) symbol : (symbol -> Kind() == Symbol::VARIABLE ? ((VariableSymbol *) symbol) -> Type() : (symbol -> Kind() == Symbol::METHOD ? ((MethodSymbol *) symbol) -> Type((Semantic *) NULL) : NULL))) : NULL); } virtual Ast *Clone(StoragePool *) { return (Ast *) NULL; } virtual LexStream::TokenIndex LeftToken() { return 0; } virtual LexStream::TokenIndex RightToken() { return 0; } }; // // Block --> <BLOCK, {_token, BlockStatements, }_token> // // BlockStatement --> LocalVariableDeclarationStatement // | Statement // class AstBlock : public AstStatement { private: StoragePool *pool; AstArray<Ast *> *block_statements; public: BlockSymbol *block_symbol; LexStream::TokenIndex label_token_opt; int nesting_level; LexStream::TokenIndex left_brace_token; LexStream::TokenIndex right_brace_token; AstBlock(StoragePool *pool_) : pool(pool_), block_statements(NULL), block_symbol(NULL), label_token_opt(0), nesting_level(0) { Ast::kind = Ast::BLOCK; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; return; } virtual ~AstBlock(); inline Ast *&Statement(int i) { return (*block_statements)[i]; } inline int NumStatements() { return (block_statements ? block_statements -> Length() : 0); } inline void AllocateBlockStatements(int estimate = 0); inline void AddStatement(Ast *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_brace_token; } virtual LexStream::TokenIndex RightToken() { return right_brace_token; } }; // // Type --> PrimitiveType // | ReferenceType // // PrimitiveType --> <PrimitiveKind, PrimitiveName> // // PrimitiveKind --> BYTE | SHORT | INT | LONG | CHAR | FLOAT | DOUBLE | BOOLEAN | VOID // // PrimitiveName --> byte_token | short_token | int_token | long_token | // char_token | float_token | double_token | boolean_token | void_token // class AstPrimitiveType : public Ast { public: LexStream::TokenIndex primitive_kind_token; AstPrimitiveType(Ast::Kind kind_, LexStream::TokenIndex token_) : primitive_kind_token(token_) { Ast::kind = kind_; Ast::class_tag = Ast::PRIMITIVE_TYPE; Ast::generated = 0; } virtual ~AstPrimitiveType(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return primitive_kind_token; } virtual LexStream::TokenIndex RightToken() { return primitive_kind_token; } }; // // Brackets --> <BRACKETS, [_token, ]_token> // class AstBrackets : public Ast { public: LexStream::TokenIndex left_bracket_token; LexStream::TokenIndex right_bracket_token; AstBrackets(LexStream::TokenIndex left_, LexStream::TokenIndex right_) : left_bracket_token(left_), right_bracket_token(right_) { Ast::kind = Ast::BRACKETS; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstBrackets(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_bracket_token; } virtual LexStream::TokenIndex RightToken() { return right_bracket_token; } }; // // ReferenceType --> ClassType // | ArrayType // // ClassType --> Name // // ArrayType --> <ARRAY, ArrayKind, [_token, ]_token> // // ArrayKind --> PrimitiveType // | Name // | ArrayType // class AstArrayType : public Ast { private: StoragePool *pool; AstArray<AstBrackets *> *brackets; public: Ast *type; AstArrayType(StoragePool *pool_) : pool(pool_), brackets(NULL) { Ast::kind = Ast::ARRAY; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstArrayType(); inline AstBrackets *&Brackets(int i) { return (*brackets)[i]; } inline int NumBrackets() { return (brackets ? brackets -> Length() : 0); } inline void AllocateBrackets(int estimate = 0); inline void AddBrackets(AstBrackets *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return type -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return Brackets(NumBrackets() - 1) -> RightToken(); } }; // // Name --> SimpleName // | FieldAccess // // SimpleName --> <IDENTIFIER, identifier_token> // class AstSimpleName : public AstExpression { public: LexStream::TokenIndex identifier_token; // // When a simple_name refers to a member in an enclosing scope, // it is mapped into a new expression that creates a path to // the member in question. // AstExpression *resolution_opt; AstSimpleName(LexStream::TokenIndex token_) : identifier_token(token_), resolution_opt(NULL) { Ast::kind = Ast::IDENTIFIER; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstSimpleName(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return identifier_token; } virtual LexStream::TokenIndex RightToken() { return identifier_token; } }; // // PackageDeclaration --> <PACKAGE, package_token, Name, ;_token> // class AstPackageDeclaration : public Ast { public: LexStream::TokenIndex package_token; AstExpression *name; LexStream::TokenIndex semicolon_token; AstPackageDeclaration() { Ast::kind = Ast::PACKAGE; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstPackageDeclaration(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return package_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ImportDeclaration --> <IMPORT, import_token, Name, *_token_opt, ;_token> // class AstImportDeclaration : public Ast { public: LexStream::TokenIndex import_token; AstExpression *name; LexStream::TokenIndex star_token_opt; // import on demand LexStream::TokenIndex semicolon_token; AstImportDeclaration() { Ast::kind = Ast::IMPORT; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstImportDeclaration(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return import_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // CompilationUnit --> <COMPILATION, PackageDeclaration_opt, ImportDeclarations, TypeDeclarations> // | <BAD_COMPILATION, PackageDeclaration_opt, ImportDeclarations, TypeDeclarations> // | <EMPTY_COMPILATION, PackageDeclaration_opt, ImportDeclarations, TypeDeclarations> // class AstCompilationUnit : public Ast { private: StoragePool *pool; AstArray<AstImportDeclaration *> *import_declarations; AstArray<Ast *> *type_declarations; public: StoragePool *ast_pool; AstPackageDeclaration *package_declaration_opt; AstCompilationUnit(StoragePool *pool_) : pool(pool_), import_declarations(NULL), type_declarations(NULL) { Ast::kind = Ast::COMPILATION; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstCompilationUnit(); void FreeAst(); inline AstImportDeclaration *&ImportDeclaration(int i) { return (*import_declarations)[i]; } inline int NumImportDeclarations() { return (import_declarations ? import_declarations -> Length() : 0); } inline void AllocateImportDeclarations(int estimate = 0); inline void AddImportDeclaration(AstImportDeclaration *); inline void ResetTypeDeclarations(int n) { if (type_declarations) type_declarations -> Reset(n); } inline Ast *&TypeDeclaration(int i) { return (*type_declarations)[i]; } inline int NumTypeDeclarations() { return (type_declarations ? type_declarations -> Length() : 0); } inline void AllocateTypeDeclarations(int estimate = 0); inline void AddTypeDeclaration(Ast *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { if (package_declaration_opt) return package_declaration_opt -> LeftToken(); else if (NumImportDeclarations() > 0) return ImportDeclaration(0) -> LeftToken(); else if (NumTypeDeclarations() > 0) return TypeDeclaration(0) -> LeftToken(); return 0; } virtual LexStream::TokenIndex RightToken() { if (NumTypeDeclarations() > 0) return TypeDeclaration(NumTypeDeclarations() - 1) -> RightToken(); else if (NumImportDeclarations() > 0) return ImportDeclaration(NumImportDeclarations() - 1) -> RightToken(); else if (package_declaration_opt) return package_declaration_opt -> RightToken(); return 0; } }; // // Modifier --> <ModifierKind, ModifierName> // // ModifierKind --> PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL | NATIVE // SYNCHRONIZED | TRANSIENT | VOLATILE // // ModifierName --> public_token | protected_token | private_token | static_token | abstract_token | // final_token | native_token | synchronized_token | transient_token | volatile_token // class AstModifier : public Ast { public: LexStream::TokenIndex modifier_kind_token; AstModifier(Ast::Kind kind_, LexStream::TokenIndex token_) : modifier_kind_token(token_) { Ast::kind = kind_; Ast::class_tag = Ast::MODIFIER; Ast::generated = 0; } virtual ~AstModifier(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return modifier_kind_token; } virtual LexStream::TokenIndex RightToken() { return modifier_kind_token; } }; // // EmptyDeclaration --> <EMPTY_DECLARATION, ;_token> // class AstEmptyDeclaration : public Ast { public: LexStream::TokenIndex semicolon_token; AstEmptyDeclaration(LexStream::TokenIndex token_) : semicolon_token(token_) { Ast::kind = Ast::EMPTY_DECLARATION; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstEmptyDeclaration(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return semicolon_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ClassBody --> <CLASS_BODY, {_token, ClassBodyDeclarations, }_token> // class AstClassBody : public Ast { private: friend class Parser; StoragePool *pool; AstArray<Ast *> *class_body_declarations; AstArray<AstFieldDeclaration *> *instance_variables; AstArray<AstFieldDeclaration *> *class_variables; AstArray<AstMethodDeclaration *> *methods; AstArray<AstConstructorDeclaration *> *constructors; AstArray<AstStaticInitializer *> *static_initializers; AstArray<AstClassDeclaration *> *inner_classes; AstArray<AstInterfaceDeclaration *> *inner_interfaces; AstArray<AstBlock *> *blocks; AstArray<AstEmptyDeclaration *> *empty_declarations; public: AstConstructorDeclaration *default_constructor; AstBlock *this_block; // used by inner classes to initialize this$1, ...this$n fields LexStream::TokenIndex left_brace_token; LexStream::TokenIndex right_brace_token; inline void mark_unparsed() { Ast::class_tag = Ast::UNPARSED; } inline void mark_parsed() { Ast::class_tag = Ast::NO_TAG; } AstClassBody(StoragePool *pool_) : pool(pool_), class_body_declarations(NULL), default_constructor(NULL), instance_variables(NULL), class_variables(NULL), methods(NULL), constructors(NULL), static_initializers(NULL), inner_classes(NULL), inner_interfaces(NULL), blocks(NULL), empty_declarations(NULL), this_block(NULL) { Ast::kind = Ast::CLASS_BODY; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstClassBody(); inline Ast *&ClassBodyDeclaration(int i) { return (*class_body_declarations)[i]; } inline int NumClassBodyDeclarations() { return (class_body_declarations ? class_body_declarations -> Length() : 0); } inline void AllocateClassBodyDeclarations(int estimate = 0); inline void AddClassBodyDeclaration(Ast *); inline AstFieldDeclaration *&InstanceVariable(int i) { return (*instance_variables)[i]; } inline int NumInstanceVariables() { return (instance_variables ? instance_variables -> Length() : 0); } inline void AllocateInstanceVariables(int estimate = 0); inline void AddInstanceVariable(AstFieldDeclaration *); inline AstFieldDeclaration *&ClassVariable(int i) { return (*class_variables)[i]; } inline int NumClassVariables() { return (class_variables ? class_variables -> Length() : 0); } inline void AllocateClassVariables(int estimate = 0); inline void AddClassVariable(AstFieldDeclaration *); inline AstMethodDeclaration *&Method(int i) { return (*methods)[i]; } inline int NumMethods() { return (methods ? methods -> Length() : 0); } inline void AllocateMethods(int estimate = 0); inline void AddMethod(AstMethodDeclaration *); inline AstConstructorDeclaration *&Constructor(int i) { return (*constructors)[i]; } inline int NumConstructors() { return (constructors ? constructors -> Length() : 0); } inline void AllocateConstructors(int estimate = 0); inline void AddConstructor(AstConstructorDeclaration *); inline AstStaticInitializer *&StaticInitializer(int i) { return (*static_initializers)[i]; } inline int NumStaticInitializers() { return (static_initializers ? static_initializers -> Length() : 0); } inline void AllocateStaticInitializers(int estimate = 0); inline void AddStaticInitializer(AstStaticInitializer *); inline AstClassDeclaration *&NestedClass(int i) { return (*inner_classes)[i]; } inline int NumNestedClasses() { return (inner_classes ? inner_classes -> Length() : 0); } inline void AllocateNestedClasses(int estimate = 0); inline void AddNestedClass(AstClassDeclaration *); inline AstInterfaceDeclaration *&NestedInterface(int i) { return (*inner_interfaces)[i]; } inline int NumNestedInterfaces() { return (inner_interfaces ? inner_interfaces -> Length() : 0); } inline void AllocateNestedInterfaces(int estimate = 0); inline void AddNestedInterface(AstInterfaceDeclaration *); inline AstBlock *&Block(int i) { return (*blocks)[i]; } inline int NumBlocks() { return (blocks ? blocks -> Length() : 0); } inline void AllocateBlocks(int estimate = 0); inline void AddBlock(AstBlock *); inline AstEmptyDeclaration *&EmptyDeclaration(int i) { return (*empty_declarations)[i]; } inline int NumEmptyDeclarations() { return (empty_declarations ? empty_declarations -> Length() : 0); } inline void AllocateEmptyDeclarations(int estimate = 0); inline void AddEmptyDeclaration(AstEmptyDeclaration *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_brace_token; } virtual LexStream::TokenIndex RightToken() { return right_brace_token; } }; // // TypeDeclaration --> ClassDeclaration // | InterfaceDeclaration // | EmptyDeclaration // // ClassDeclaration --> <CLASS, ClassModifiers, class_token, identifier_token, Super_opt, Interfaces, ClassBody> // // Super --> Name // // Interface --> Name // // ClassModifier --> Modifier (ABSTRACT, FINAL or PUBLIC) // // ClassBodyDeclaration --> FieldDeclaration // | MethodDeclaration // | ConstructorDeclaration // | StaticInitializer // class AstClassDeclaration : public AstStatement { StoragePool *pool; AstArray<AstModifier *> *class_modifiers; AstArray<AstExpression *> *interfaces; public: SemanticEnvironment *semantic_environment; LexStream::TokenIndex class_token; LexStream::TokenIndex identifier_token; Ast *super_opt; AstClassBody *class_body; AstClassDeclaration(StoragePool *pool_) : pool(pool_), class_modifiers(NULL), interfaces(NULL), semantic_environment(NULL) { Ast::kind = Ast::CLASS; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstClassDeclaration(); bool IsValid() { return semantic_environment != NULL; } inline void MarkLocal() { Ast::class_tag = Ast::STATEMENT; AstStatement::is_reachable = true; AstStatement::can_complete_normally = true; } inline AstModifier *&ClassModifier(int i) { return (*class_modifiers)[i]; } inline int NumClassModifiers() { return (class_modifiers ? class_modifiers -> Length() : 0); } inline void AllocateClassModifiers(int estimate = 0); inline void AddClassModifier(AstModifier *); inline AstExpression *&Interface(int i) { return (*interfaces)[i]; } inline int NumInterfaces() { return (interfaces ? interfaces -> Length() : 0); } inline void AllocateInterfaces(int estimate = 0); inline void AddInterface(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumClassModifiers() > 0 ? (*class_modifiers)[0] -> LeftToken() : class_token); } virtual LexStream::TokenIndex RightToken() { return class_body -> RightToken(); } }; // // VariableInitializer --> Expression // | ArrayInitializer // // ArrayInitializer --> <ARRAY_INITIALIZER, {_token, VariableInitializers, }_token> // class AstArrayInitializer : public Ast { private: StoragePool *pool; AstArray<Ast *> *variable_initializers; public: LexStream::TokenIndex left_brace_token; LexStream::TokenIndex right_brace_token; AstArrayInitializer(StoragePool *pool_) : pool(pool_), variable_initializers(NULL) { Ast::kind = Ast::ARRAY_INITIALIZER; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstArrayInitializer(); inline Ast *&VariableInitializer(int i) { return (*variable_initializers)[i]; } inline int NumVariableInitializers() { return (variable_initializers ? variable_initializers -> Length() : 0); } inline void AllocateVariableInitializers(int estimate = 0); inline void AddVariableInitializer(Ast *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_brace_token; } virtual LexStream::TokenIndex RightToken() { return right_brace_token; } }; // // VariableDeclaratorId --> <VARIABLE_DECLARATOR_NAME, identifier_token, Brackets> // class AstVariableDeclaratorId : public Ast { private: StoragePool *pool; AstArray<AstBrackets *> *brackets; public: LexStream::TokenIndex identifier_token; AstVariableDeclaratorId(StoragePool *pool_) : pool(pool_), brackets(NULL) { Ast::kind = Ast::VARIABLE_DECLARATOR_NAME; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstVariableDeclaratorId(); inline AstBrackets *&Brackets(int i) { return (*brackets)[i]; } inline int NumBrackets() { return (brackets ? brackets -> Length() : 0); } inline void AllocateBrackets(int estimate = 0); inline void AddBrackets(AstBrackets *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return identifier_token; } virtual LexStream::TokenIndex RightToken() { return (NumBrackets() > 0 ? (*brackets)[NumBrackets() - 1] -> RightToken() : identifier_token); } }; // // VariableDeclarator --> <VARIABLE_DECLARATOR, VariableDeclaratorId, VariableInitializer_opt> // class AstVariableDeclarator : public Ast { public: VariableSymbol *symbol; bool pending; // when true, this variable signals that the variable_initializer_opt for this variable is currently being evaluated AstVariableDeclaratorId *variable_declarator_name; Ast *variable_initializer_opt; AstVariableDeclarator() : symbol(NULL), pending(false) { Ast::kind = Ast::VARIABLE_DECLARATOR; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstVariableDeclarator(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return variable_declarator_name -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return (variable_initializer_opt ? variable_initializer_opt -> RightToken() : variable_declarator_name -> RightToken()); } }; // // FieldDeclaration --> <FIELD, VariableModifiers, Type, VariableDeclarators, ;_token> // // FieldModifier --> Modifier (PUBLIC, PROTECTED, PRIVATE, FINAL, STATIC, TRANSIENT or VOLATILE) // class AstFieldDeclaration : public Ast { StoragePool *pool; AstArray<AstModifier *> *variable_modifiers; AstArray<AstVariableDeclarator *> *variable_declarators; public: Ast *type; LexStream::TokenIndex semicolon_token; AstFieldDeclaration(StoragePool *pool_) : pool(pool_), variable_modifiers(NULL), variable_declarators(NULL) { Ast::kind = Ast::FIELD; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstFieldDeclaration(); inline void MarkStatic() { Ast::class_tag = Ast::STATIC_FIELD; } inline AstModifier *&VariableModifier(int i) { return (*variable_modifiers)[i]; } inline int NumVariableModifiers() { return (variable_modifiers ? variable_modifiers -> Length() : 0); } inline void AllocateVariableModifiers(int estimate = 0); inline void AddVariableModifier(AstModifier *); inline AstVariableDeclarator *&VariableDeclarator(int i) { return (*variable_declarators)[i]; } inline int NumVariableDeclarators() { return (variable_declarators ? variable_declarators -> Length() : 0); } inline void AllocateVariableDeclarators(int estimate = 0); inline void AddVariableDeclarator(AstVariableDeclarator *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumVariableModifiers() > 0 ? (*variable_modifiers)[0] -> LeftToken() : type -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // FormalParameter --> <PARAMETER, Type, VariableDeclaratorId> // class AstFormalParameter : public Ast { StoragePool *pool; AstArray<AstModifier *> *parameter_modifiers; public: VariableSymbol *parameter_symbol; Ast *type; AstVariableDeclaratorId *variable_declarator_name; AstFormalParameter(StoragePool *pool_) : pool(pool_), parameter_modifiers(NULL) { Ast::kind = Ast::PARAMETER; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstFormalParameter(); inline AstModifier *&ParameterModifier(int i) { return (*parameter_modifiers)[i]; } inline int NumParameterModifiers() { return (parameter_modifiers ? parameter_modifiers -> Length() : 0); } inline void AllocateParameterModifiers(int estimate = 0); inline void AddParameterModifier(AstModifier *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumParameterModifiers() > 0 ? (*parameter_modifiers)[0] -> LeftToken() : type -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return variable_declarator_name -> RightToken(); } }; // // MethodDeclarator --> <METHOD_DECLARATOR, identifier_token, (_token, FormalParameters, )_token, Brackets> // class AstMethodDeclarator : public Ast { private: StoragePool *pool; AstArray<AstBrackets *> *brackets; AstArray<AstFormalParameter *> *formal_parameters; public: LexStream::TokenIndex identifier_token; LexStream::TokenIndex left_parenthesis_token; LexStream::TokenIndex right_parenthesis_token; AstMethodDeclarator(StoragePool *pool_) : pool(pool_), brackets(NULL), formal_parameters(NULL) { Ast::kind = Ast::METHOD_DECLARATOR; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstMethodDeclarator(); inline AstBrackets *&Brackets(int i) { return (*brackets)[i]; } inline int NumBrackets() { return (brackets ? brackets -> Length() : 0); } inline void AllocateBrackets(int estimate = 0); inline void AddBrackets(AstBrackets *); inline AstFormalParameter *&FormalParameter(int i) { return (*formal_parameters)[i]; } inline int NumFormalParameters() { return (formal_parameters ? formal_parameters -> Length() : 0); } inline void AllocateFormalParameters(int estimate = 0); inline void AddFormalParameter(AstFormalParameter *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return identifier_token; } virtual LexStream::TokenIndex RightToken() { return (NumBrackets() ? Brackets(NumBrackets() - 1) -> RightToken() : right_parenthesis_token); } }; // // MethodDeclaration --> <METHOD, MethodModifiers, Type, MethodDeclarator, Throws, MethodBody> // // MethodModifier --> Modifier (PUBLIC, PROTECTED, PRIVATE, STATIC, ABSTRACT, FINAL, NATIVE or SYNCHRONIZED) // // Throws --> Names // // MethodBody --> Block // | EmptyStatement // class AstMethodDeclaration : public Ast { StoragePool *pool; AstArray<AstModifier *> *method_modifiers; AstArray<AstExpression *> *throws; public: MethodSymbol *method_symbol; Ast *type; AstMethodDeclarator *method_declarator; AstStatement *method_body; AstMethodDeclaration(StoragePool *pool_) : pool(pool_), method_modifiers(NULL), throws(NULL), method_symbol(NULL) { Ast::kind = Ast::METHOD; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstMethodDeclaration(); bool IsValid() { return method_symbol != NULL; } bool IsSignature() { return (method_body -> EmptyStatementCast() != NULL); } inline AstModifier *&MethodModifier(int i) { return (*method_modifiers)[i]; } inline int NumMethodModifiers() { return (method_modifiers ? method_modifiers -> Length() : 0); } inline void AllocateMethodModifiers(int estimate = 0); inline void AddMethodModifier(AstModifier *); inline AstExpression *&Throw(int i) { return (*throws)[i]; } inline int NumThrows() { return (throws ? throws -> Length() : 0); } inline void AllocateThrows(int estimate = 0); inline void AddThrow(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumMethodModifiers() > 0 ? (*method_modifiers)[0] -> LeftToken() : type -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return method_body -> RightToken(); } }; // // StaticInitializer --> <STATIC_INITIALIZER, static_token, Block> // class AstStaticInitializer : public Ast { public: LexStream::TokenIndex static_token; AstBlock *block; AstStaticInitializer() { Ast::kind = Ast::STATIC_INITIALIZER; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstStaticInitializer(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return static_token; } virtual LexStream::TokenIndex RightToken() { return block -> RightToken(); } }; // // ThisCall --> <THIS_CALL, this_token, (_token, Arguments, )_token, ;_token> // // Argument --> Expression // class AstThisCall : public AstStatement { private: StoragePool *pool; AstArray<AstExpression *> *arguments; AstArray<AstExpression *> *local_arguments_opt; // used only for local classes that use enclosed local variables public: MethodSymbol *symbol; AstExpression *base_opt; LexStream::TokenIndex dot_token_opt; LexStream::TokenIndex this_token; LexStream::TokenIndex left_parenthesis_token; LexStream::TokenIndex right_parenthesis_token; LexStream::TokenIndex semicolon_token; AstThisCall(StoragePool *pool_) : pool(pool_), arguments(NULL), local_arguments_opt(NULL), symbol(NULL) { Ast::kind = Ast::THIS_CALL; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstThisCall(); inline AstExpression *&Argument(int i) { return (*arguments)[i]; } inline int NumArguments() { return (arguments ? arguments -> Length() : 0); } inline void AllocateArguments(int estimate = 0); inline void AddArgument(AstExpression *); inline AstExpression *&LocalArgument(int i) { return (*local_arguments_opt)[i]; } inline int NumLocalArguments() { return (local_arguments_opt ? local_arguments_opt -> Length() : 0); } inline void AllocateLocalArguments(int estimate = 0); inline void AddLocalArgument(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return this_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // SuperCall --> <SUPER_CALL, super_token, (_token, Arguments, )_token, ;_token> // | <SUPER_CALL, SuperField, (_token, Arguments, )_token, ;_token> // class AstSuperCall : public AstStatement { private: StoragePool *pool; AstArray<AstExpression *> *arguments; AstArray<AstExpression *> *local_arguments_opt; // used only for local classes that use enclosed local variables public: MethodSymbol *symbol; AstExpression *base_opt; LexStream::TokenIndex dot_token_opt; LexStream::TokenIndex super_token; LexStream::TokenIndex left_parenthesis_token; LexStream::TokenIndex right_parenthesis_token; LexStream::TokenIndex semicolon_token; AstSuperCall(StoragePool *pool_) : pool(pool_), arguments(NULL), local_arguments_opt(NULL), symbol(NULL) { Ast::kind = Ast::SUPER_CALL; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstSuperCall(); inline AstExpression *&Argument(int i) { return (*arguments)[i]; } inline int NumArguments() { return (arguments ? arguments -> Length() : 0); } inline void AllocateArguments(int estimate = 0); inline void AddArgument(AstExpression *); inline AstExpression *&LocalArgument(int i) { return (*local_arguments_opt)[i]; } inline int NumLocalArguments() { return (local_arguments_opt ? local_arguments_opt -> Length() : 0); } inline void AllocateLocalArguments(int estimate = 0); inline void AddLocalArgument(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (base_opt ? base_opt -> LeftToken() : super_token); } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ConstructorDeclaration --> <CONSTRUCTOR, Constructormodifiers, MethodDeclarator, Throws, ConstructorBody> // // ConstructorBody --> <CONSTRUCTOR_BLOCK, {_token, ExplicitConstructorInvocation, BlockStatements, }_token> // | MethodBody // // ConstructorModifier --> Modifier (PUBLIC, PROTECTED or PRIVATE) // // ExplicitConstructorInvocation --> ThisCall // | SuperCall // class AstConstructorBlock : public AstStatement { private: StoragePool *pool; AstArray<AstStatement *> *local_init_statements; public: BlockSymbol *block_symbol; LexStream::TokenIndex left_brace_token; Ast *explicit_constructor_invocation_opt; AstBlock *block; LexStream::TokenIndex right_brace_token; AstExpressionStatement *original_constructor_invocation; AstConstructorBlock(StoragePool *pool_) : pool(pool_), local_init_statements(NULL), block_symbol(NULL), original_constructor_invocation(NULL) { Ast::kind = Ast::CONSTRUCTOR_BLOCK; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstConstructorBlock(); inline AstStatement *&LocalInitStatement(int i) { return (*local_init_statements)[i]; } inline int NumLocalInitStatements() { return (local_init_statements ? local_init_statements -> Length() : 0); } inline void AllocateLocalInitStatements(int estimate = 0); inline void AddLocalInitStatement(AstStatement *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_brace_token; } virtual LexStream::TokenIndex RightToken() { return right_brace_token; } }; class AstConstructorDeclaration : public Ast { StoragePool *pool; AstArray<AstModifier *> *constructor_modifiers; AstArray<AstExpression *> *throws; public: MethodSymbol *constructor_symbol; int index; AstMethodDeclarator *constructor_declarator; AstConstructorBlock *constructor_body; AstConstructorDeclaration(StoragePool *pool_) : pool(pool_), throws(NULL), constructor_modifiers(NULL), constructor_symbol(NULL), index(CycleChecker::OMEGA) { Ast::kind = Ast::CONSTRUCTOR; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstConstructorDeclaration(); bool IsValid() { return constructor_symbol != NULL; } inline AstModifier *&ConstructorModifier(int i) { return (*constructor_modifiers)[i]; } inline int NumConstructorModifiers() { return (constructor_modifiers ? constructor_modifiers -> Length() : 0); } inline void AllocateConstructorModifiers(int estimate = 0); inline void AddConstructorModifier(AstModifier *); inline AstExpression *&Throw(int i) { return (*throws)[i]; } inline int NumThrows() { return (throws ? throws -> Length() : 0); } inline void AllocateThrows(int estimate = 0); inline void AddThrow(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumConstructorModifiers() > 0 ? (*constructor_modifiers)[0] -> LeftToken() : constructor_declarator -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return constructor_body -> RightToken(); } }; // // InterfaceDeclaration --> <INTERFACE, Interfacemodifiers, interface_token, identifier_token, ExtendsInterfaces, {_token, InterfaceMemberDeclarations, }_token> // // InterfaceModifier --> Modifier (PUBLIC, ABSTRACT) // // ExtendsInterfaces --> Names // // // InterfaceMemberDeclaration --> ConstantDeclaration // | AbstractMethodDeclaration // // ConstantDeclaration --> FieldDeclaration (where the FieldModifierList is a Constantmodifiers) // // ConstantModifier --> Modifier (PUBLIC, STATIC or FINAL) // // AbstractMethodDeclaration --> MethodDeclaration (where MethodModifierList is a SignatureModifierList and the // MethodBody is an EmptyStatement) // // SignatureModifier --> Modifier (PUBLIC or ABSTRACT) // class AstInterfaceDeclaration : public Ast { private: friend class Parser; StoragePool *pool; AstArray<AstModifier *> *interface_modifiers; AstArray<AstExpression *> *extends_interfaces; AstArray<Ast *> *interface_member_declarations; AstArray<AstFieldDeclaration *> *class_variables; AstArray<AstMethodDeclaration *> *methods; AstArray<AstClassDeclaration *> *inner_classes; AstArray<AstInterfaceDeclaration *> *inner_interfaces; AstArray<AstEmptyDeclaration *> *empty_declarations; public: SemanticEnvironment *semantic_environment; LexStream::TokenIndex interface_token; LexStream::TokenIndex identifier_token; LexStream::TokenIndex left_brace_token; LexStream::TokenIndex right_brace_token; inline void mark_unparsed() { Ast::class_tag = Ast::UNPARSED; } inline void mark_parsed() { Ast::class_tag = Ast::NO_TAG; } AstInterfaceDeclaration(StoragePool *pool_) : pool(pool_), interface_modifiers(NULL), extends_interfaces(NULL), interface_member_declarations(NULL), semantic_environment(NULL), class_variables(NULL), methods(NULL), inner_classes(NULL), inner_interfaces(NULL), empty_declarations(NULL) { Ast::kind = Ast::INTERFACE; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstInterfaceDeclaration(); bool IsValid() { return semantic_environment != NULL; } inline AstModifier *&InterfaceModifier(int i) { return (*interface_modifiers)[i]; } inline int NumInterfaceModifiers() { return (interface_modifiers ? interface_modifiers -> Length() : 0); } inline void AllocateInterfaceModifiers(int estimate = 0); inline void AddInterfaceModifier(AstModifier *); inline AstExpression *&ExtendsInterface(int i) { return (*extends_interfaces)[i]; } inline int NumExtendsInterfaces() { return (extends_interfaces ? extends_interfaces -> Length() : 0); } inline void AllocateExtendsInterfaces(int estimate = 0); inline void AddExtendsInterface(AstExpression *); inline Ast *&InterfaceMemberDeclaration(int i) { return (*interface_member_declarations)[i]; } inline int NumInterfaceMemberDeclarations() { return (interface_member_declarations ? interface_member_declarations -> Length() : 0); } inline void AllocateInterfaceMemberDeclarations(int estimate = 0); inline void AddInterfaceMemberDeclaration(Ast *); inline AstFieldDeclaration *&ClassVariable(int i) { return (*class_variables)[i]; } inline int NumClassVariables() { return (class_variables ? class_variables -> Length() : 0); } inline void AllocateClassVariables(int estimate = 0); inline void AddClassVariable(AstFieldDeclaration *); inline AstMethodDeclaration *&Method(int i) { return (*methods)[i]; } inline int NumMethods() { return (methods ? methods -> Length() : 0); } inline void AllocateMethods(int estimate = 0); inline void AddMethod(AstMethodDeclaration *); inline AstClassDeclaration *&NestedClass(int i) { return (*inner_classes)[i]; } inline int NumNestedClasses() { return (inner_classes ? inner_classes -> Length() : 0); } inline void AllocateNestedClasses(int estimate = 0); inline void AddNestedClass(AstClassDeclaration *); inline AstInterfaceDeclaration *&NestedInterface(int i) { return (*inner_interfaces)[i]; } inline int NumNestedInterfaces() { return (inner_interfaces ? inner_interfaces -> Length() : 0); } inline void AllocateNestedInterfaces(int estimate = 0); inline void AddNestedInterface(AstInterfaceDeclaration *); inline AstEmptyDeclaration *&EmptyDeclaration(int i) { return (*empty_declarations)[i]; } inline int NumEmptyDeclarations() { return (empty_declarations ? empty_declarations -> Length() : 0); } inline void AllocateEmptyDeclarations(int estimate = 0); inline void AddEmptyDeclaration(AstEmptyDeclaration *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumInterfaceModifiers() > 0 ? (*interface_modifiers)[0] -> LeftToken() : interface_token); } virtual LexStream::TokenIndex RightToken() { return right_brace_token; } }; // // LocalVariableDeclarationStatement --> <LOCAL_VARIABLE_DECLARATION, Type, VariableDeclarators, ;_token_opt> // class AstLocalVariableDeclarationStatement : public AstStatement { StoragePool *pool; AstArray<AstModifier *> *local_modifiers; AstArray<AstVariableDeclarator *> *variable_declarators; public: Ast *type; LexStream::TokenIndex semicolon_token_opt; AstLocalVariableDeclarationStatement(StoragePool *pool_) : pool(pool_), local_modifiers(NULL), variable_declarators(NULL) { Ast::kind = Ast::LOCAL_VARIABLE_DECLARATION; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstLocalVariableDeclarationStatement(); inline AstModifier *&LocalModifier(int i) { return (*local_modifiers)[i]; } inline int NumLocalModifiers() { return (local_modifiers ? local_modifiers -> Length() : 0); } inline void AllocateLocalModifiers(int estimate = 0); inline void AddLocalModifier(AstModifier *); inline AstVariableDeclarator *&VariableDeclarator(int i) { return (*variable_declarators)[i]; } inline int NumVariableDeclarators() { return (variable_declarators ? variable_declarators -> Length() : 0); } inline void AllocateVariableDeclarators(int estimate = 0); inline void AddVariableDeclarator(AstVariableDeclarator *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (NumLocalModifiers() > 0 ? (*local_modifiers)[0] -> LeftToken() : type -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return (semicolon_token_opt ? semicolon_token_opt : VariableDeclarator(NumVariableDeclarators() - 1) -> RightToken()); } }; // // Statement --> IfStatement // | WhileStatement // | ForStatement // | Block // | EmptyStatement // | ExpressionStatement // | SwitchStatement // | DoStatement // | BreakStatement // | ContinueStatement // | ReturnStatement // | SynchronizedStatement // | ThrowStatement // | TryStatement // // Label --> identifier_token // // IfStatement --> <IF, Label_opt, if_token, Expression, TrueStatement, FalseStatement_opt> // // TrueStatement --> Statement // // FalseStatement --> Statement // class AstIfStatement : public AstStatement { public: LexStream::TokenIndex if_token; AstExpression *expression; AstStatement *true_statement; AstStatement *false_statement_opt; AstIfStatement() : expression(NULL) { Ast::kind = Ast::IF; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstIfStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return if_token; } virtual LexStream::TokenIndex RightToken() { return (false_statement_opt ? false_statement_opt -> RightToken() : true_statement -> RightToken()); } }; // // EmptyStatement --> <EMPTY_STATEMENT, Label_opt, ;_token> // class AstEmptyStatement : public AstStatement { public: LexStream::TokenIndex semicolon_token; AstEmptyStatement(LexStream::TokenIndex token_) : semicolon_token(token_) { Ast::kind = Ast::EMPTY_STATEMENT; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstEmptyStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return semicolon_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ExpressionStatement --> <EXPRESSION_STATEMENT, Label_opt, Expression, ;_token_opt> // class AstExpressionStatement : public AstStatement { public: AstExpression *expression; LexStream::TokenIndex semicolon_token_opt; AstExpressionStatement() { Ast::kind = Ast::EXPRESSION_STATEMENT; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstExpressionStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return expression -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return (semicolon_token_opt ? semicolon_token_opt : expression -> RightToken()); } }; // // SwitchLabel --> CaseLabel // | DefaultLabel // // CaseLabel --> <CASE, case_token, Expression, :_token> // class AstCaseLabel : public Ast { public: LexStream::TokenIndex case_token; AstExpression *expression; LexStream::TokenIndex colon_token; int map_index; AstCaseLabel() { Ast::kind = Ast::CASE; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstCaseLabel(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return case_token; } virtual LexStream::TokenIndex RightToken() { return colon_token; } }; // // DefaultLabel --> <DEFAULT, default_token, :_token> // class AstDefaultLabel : public Ast { public: LexStream::TokenIndex default_token; LexStream::TokenIndex colon_token; AstDefaultLabel() { Ast::kind = Ast::DEFAULT; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstDefaultLabel(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return default_token; } virtual LexStream::TokenIndex RightToken() { return colon_token; } }; // // SwitchBlockStatement --> <SWITCH_BLOCK, SwitchLabels, BlockStatements> // class AstSwitchBlockStatement : public Ast { private: StoragePool *pool; AstArray<AstStatement *> *block_statements; AstArray<Ast *> *switch_labels; public: AstSwitchBlockStatement(StoragePool *pool_) : pool(pool_), block_statements(NULL), switch_labels(NULL) { Ast::kind = Ast::SWITCH_BLOCK; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstSwitchBlockStatement(); inline AstStatement *&Statement(int i) { return (*block_statements)[i]; } inline int NumStatements() { return (block_statements ? block_statements -> Length() : 0); } inline void AllocateBlockStatements(int estimate = 0); inline void AddStatement(AstStatement *); inline Ast *&SwitchLabel(int i) { return (*switch_labels)[i]; } inline int NumSwitchLabels() { return (switch_labels ? switch_labels -> Length() : 0); } inline void AllocateSwitchLabels(int estimate = 0); inline void AddSwitchLabel(Ast *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return SwitchLabel(0) -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return Statement(NumStatements() - 1) -> RightToken(); } }; class CaseElement { public: AstSwitchBlockStatement *switch_block_statement; AstExpression *expression; int index; int Value() { return ((IntLiteralValue *) (expression -> value)) -> value; } inline AstStatement *&Statement(int i) { return switch_block_statement -> Statement(i); } inline int NumStatements() { return switch_block_statement -> NumStatements(); } }; // // SwitchStatement --> <SWITCH, Label_opt, switch_token, Expression, {_token, SwitchBlockStatements, SwitchLabels_opt, }_token> // class AstSwitchStatement : public AstStatement { public: AstArray<CaseElement *> map; CaseElement default_case; LexStream::TokenIndex switch_token; AstExpression *expression; AstBlock *switch_block; AstSwitchStatement(StoragePool *pool) : map(pool) { Ast::kind = Ast::SWITCH; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstSwitchStatement(); void SortCases(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return switch_token; } virtual LexStream::TokenIndex RightToken() { return switch_block -> RightToken(); } }; // // WhileStatement --> <WHILE, Label_opt, while_token, Expression, Statement> // class AstWhileStatement : public AstStatement { public: LexStream::TokenIndex while_token; AstExpression *expression; AstStatement *statement; AstWhileStatement() { Ast::kind = Ast::WHILE; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstWhileStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return while_token; } virtual LexStream::TokenIndex RightToken() { return statement -> RightToken(); } }; // // DoStatement --> <DO, Label_opt, do_token, Expression, Statement, ;_token> // class AstDoStatement : public AstStatement { public: LexStream::TokenIndex do_token; AstStatement *statement; LexStream::TokenIndex while_token; AstExpression *expression; LexStream::TokenIndex semicolon_token; AstDoStatement() { Ast::kind = Ast::DO; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstDoStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return do_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ForStatement --> <FOR, Label_opt, for_token, ForInits, Expression_opt, ForUpdates, Statement> // // ForInit --> ExpressionStatement // | LocalVariableDeclarationStatement // // ForUpdate --> ExpressionStatement // class AstForStatement : public AstStatement { private: StoragePool *pool; AstArray<AstStatement *> *for_init_statements; AstArray<AstExpressionStatement *> *for_update_statements; public: LexStream::TokenIndex for_token; AstExpression *end_expression_opt; AstStatement *statement; AstForStatement(StoragePool *pool_) : pool(pool_), for_init_statements(NULL), for_update_statements(NULL) { Ast::kind = Ast::FOR; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstForStatement(); inline AstStatement *&ForInitStatement(int i) { return (*for_init_statements)[i]; } inline int NumForInitStatements() { return (for_init_statements ? for_init_statements -> Length() : 0); } inline void AllocateForInitStatements(int estimate = 0); inline void AddForInitStatement(AstStatement *); inline AstExpressionStatement *&ForUpdateStatement(int i) { return (*for_update_statements)[i]; } inline int NumForUpdateStatements() { return (for_update_statements ? for_update_statements -> Length() : 0); } inline void AllocateForUpdateStatements(int estimate = 0); inline void AddForUpdateStatement(AstExpressionStatement *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return for_token; } virtual LexStream::TokenIndex RightToken() { return statement -> RightToken(); } }; // // BreakStatement --> <BREAK, Label_opt, break_token, identifier_token_opt, ;_token> // class AstBreakStatement : public AstStatement { public: LexStream::TokenIndex break_token; LexStream::TokenIndex identifier_token_opt; LexStream::TokenIndex semicolon_token; int nesting_level; AstBreakStatement() { Ast::kind = Ast::BREAK; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstBreakStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return break_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ContinueStatement --> <CONTINUE, Label_opt, continue_token, SimpleName_opt, ;_token> // class AstContinueStatement : public AstStatement { public: LexStream::TokenIndex continue_token; LexStream::TokenIndex identifier_token_opt; LexStream::TokenIndex semicolon_token; int nesting_level; AstContinueStatement() { Ast::kind = Ast::CONTINUE; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstContinueStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return continue_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ReturnStatement --> <RETURN, Label_opt, return_token, Expression_opt, ;_token> // class AstReturnStatement : public AstStatement { public: LexStream::TokenIndex return_token; AstExpression *expression_opt; LexStream::TokenIndex semicolon_token; AstReturnStatement() { Ast::kind = Ast::RETURN; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstReturnStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return return_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // ThrowStatement --> <THROW, Label_opt, throw_token, Expression, ;_token> // class AstThrowStatement : public AstStatement { public: LexStream::TokenIndex throw_token; AstExpression *expression; LexStream::TokenIndex semicolon_token; AstThrowStatement() { Ast::kind = Ast::THROW; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstThrowStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return throw_token; } virtual LexStream::TokenIndex RightToken() { return semicolon_token; } }; // // SynchronizedStatement --> <SYNCHRONIZED_STATEMENT, Label_opt, synchronized_token, Expression, Block> // class AstSynchronizedStatement : public AstStatement { public: LexStream::TokenIndex synchronized_token; AstExpression *expression; AstBlock *block; AstSynchronizedStatement() { Ast::kind = Ast::SYNCHRONIZED_STATEMENT; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstSynchronizedStatement(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return synchronized_token; } virtual LexStream::TokenIndex RightToken() { return block -> RightToken(); } }; // // CatchClause --> <CATCH, catch_token, FormalParameter, Block> // class AstCatchClause : public Ast { public: VariableSymbol *parameter_symbol; LexStream::TokenIndex catch_token; AstFormalParameter *formal_parameter; AstBlock *block; AstCatchClause() : parameter_symbol(NULL) { Ast::kind = Ast::CATCH; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstCatchClause(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return catch_token; } virtual LexStream::TokenIndex RightToken() { return block -> RightToken(); } }; // // FinallyClause --> <FINALLY, finally_token, Block> // class AstFinallyClause : public Ast { public: LexStream::TokenIndex finally_token; AstBlock *block; AstFinallyClause() { Ast::kind = Ast::FINALLY; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstFinallyClause(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return finally_token; } virtual LexStream::TokenIndex RightToken() { return block -> RightToken(); } }; // // TryStatement --> <TRY, Label_opt, try-token, Block CatchClauses, FinallyClause_opt> // class AstTryStatement : public AstStatement { private: StoragePool *pool; AstArray<AstCatchClause *> *catch_clauses; public: LexStream::TokenIndex try_token; AstBlock *block; AstFinallyClause *finally_clause_opt; AstTryStatement(StoragePool *pool_) : pool(pool_), catch_clauses(NULL) { Ast::kind = Ast::TRY; Ast::class_tag = Ast::STATEMENT; Ast::generated = 0; AstStatement::is_reachable = false; AstStatement::can_complete_normally = false; } virtual ~AstTryStatement(); inline AstCatchClause *&CatchClause(int i) { return (*catch_clauses)[i]; } inline int NumCatchClauses() { return (catch_clauses ? catch_clauses -> Length() : 0); } inline void AllocateCatchClauses(int estimate = 0); inline void AddCatchClause(AstCatchClause *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return try_token; } virtual LexStream::TokenIndex RightToken() { // // when the Finally clause is null, there must be one or more catch clauses // return (finally_clause_opt ? finally_clause_opt -> RightToken() : CatchClause(NumCatchClauses() - 1) -> RightToken()); } }; // // Expression --> Primary // | UnaryExpression // | BinaryExpression // | ConditionalExpression // | AssignmentExpression // // Primary --> Literal // | NullLiteral // | ThisExpression // | SuperExpression // | ParenthesizedExpression // | ClassInstanceCreationExpression // | ArrayCreationExpression // | FieldAccess // | MethodInvocation // | ArrayAccess // // Literal --> IntegerLiteral // | LongLiteral // | FloatingPointLiteral // | DoubleLiteral // | BooleanLiteral // | StringLiteral // | CharacterLiteral // // BooleanLiteral --> TrueLiteral // | FalseLiteral // // // IntegerLiteral --> <INTEGER_LITERAL, integer_literal_token, value> // class AstIntegerLiteral : public AstExpression { public: LexStream::TokenIndex integer_literal_token; AstIntegerLiteral(LexStream::TokenIndex token_) : integer_literal_token(token_) { Ast::kind = Ast::INTEGER_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstIntegerLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return integer_literal_token; } virtual LexStream::TokenIndex RightToken() { return integer_literal_token; } }; // // LongLiteral --> <LONG_LITERAL, long_literal_token, value> // class AstLongLiteral : public AstExpression { public: LexStream::TokenIndex long_literal_token; AstLongLiteral(LexStream::TokenIndex token_) : long_literal_token(token_) { Ast::kind = Ast::LONG_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstLongLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return long_literal_token; } virtual LexStream::TokenIndex RightToken() { return long_literal_token; } }; // // FloatingPointLiteral --> <FLOATING_POINT_LITERAL, Literal, value> // class AstFloatingPointLiteral : public AstExpression { public: LexStream::TokenIndex floating_point_literal_token; AstFloatingPointLiteral(LexStream::TokenIndex token_) : floating_point_literal_token(token_) { Ast::kind = Ast::FLOATING_POINT_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstFloatingPointLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return floating_point_literal_token; } virtual LexStream::TokenIndex RightToken() { return floating_point_literal_token; } }; // // DoubleLiteral --> <DOUBLE_LITERAL, Literal, value> // class AstDoubleLiteral : public AstExpression { public: LexStream::TokenIndex double_literal_token; AstDoubleLiteral(LexStream::TokenIndex token_) : double_literal_token(token_) { Ast::kind = Ast::DOUBLE_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstDoubleLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return double_literal_token; } virtual LexStream::TokenIndex RightToken() { return double_literal_token; } }; // // TrueLiteral --> <TRUE_LITERAL, Literal, value> // class AstTrueLiteral : public AstExpression { public: LexStream::TokenIndex true_literal_token; AstTrueLiteral(LexStream::TokenIndex token_) : true_literal_token(token_) { Ast::kind = Ast::TRUE_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstTrueLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return true_literal_token; } virtual LexStream::TokenIndex RightToken() { return true_literal_token; } }; // // FalseLiteral --> <FALSE_LITERAL, Literal, value> // class AstFalseLiteral : public AstExpression { public: LexStream::TokenIndex false_literal_token; AstFalseLiteral(LexStream::TokenIndex token_) : false_literal_token(token_) { Ast::kind = Ast::FALSE_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstFalseLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return false_literal_token; } virtual LexStream::TokenIndex RightToken() { return false_literal_token; } }; // // StringLiteral --> <STRING_LITERAL, Literal, value> // class AstStringLiteral : public AstExpression { public: LexStream::TokenIndex string_literal_token; AstStringLiteral(LexStream::TokenIndex token_) : string_literal_token(token_) { Ast::kind = Ast::STRING_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstStringLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return string_literal_token; } virtual LexStream::TokenIndex RightToken() { return string_literal_token; } }; // // CharacterLiteral --> <CHARACTER_LITERAL, literal_token, value> // class AstCharacterLiteral : public AstExpression { public: LexStream::TokenIndex character_literal_token; AstCharacterLiteral(LexStream::TokenIndex token_) : character_literal_token(token_) { Ast::kind = Ast::CHARACTER_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstCharacterLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return character_literal_token; } virtual LexStream::TokenIndex RightToken() { return character_literal_token; } }; // // NullLiteral --> <NULL_EXPRESSION, null_token> // class AstNullLiteral : public AstExpression { public: LexStream::TokenIndex null_token; AstNullLiteral(LexStream::TokenIndex token_) : null_token(token_) { Ast::kind = Ast::NULL_LITERAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstNullLiteral(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return null_token; } virtual LexStream::TokenIndex RightToken() { return null_token; } }; // // ThisExpression --> <THIS, this_token> // class AstThisExpression : public AstExpression { public: LexStream::TokenIndex this_token; AstThisExpression(LexStream::TokenIndex token_) : this_token(token_) { Ast::kind = Ast::THIS_EXPRESSION; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstThisExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return this_token; } virtual LexStream::TokenIndex RightToken() { return this_token; } }; // // SuperExpression --> <SUPER, super_token> // class AstSuperExpression : public AstExpression { public: LexStream::TokenIndex super_token; AstSuperExpression(LexStream::TokenIndex token_) : super_token(token_) { Ast::kind = Ast::SUPER_EXPRESSION; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstSuperExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return super_token; } virtual LexStream::TokenIndex RightToken() { return super_token; } }; // // ParenthesizedExpression --> <PARENTHESIZED_EXPRESSION, (_token, Expression, )_token> // class AstParenthesizedExpression : public AstExpression { public: LexStream::TokenIndex left_parenthesis_token; AstExpression *expression; LexStream::TokenIndex right_parenthesis_token; AstParenthesizedExpression() { Ast::kind = Ast::PARENTHESIZED_EXPRESSION; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstParenthesizedExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_parenthesis_token; } virtual LexStream::TokenIndex RightToken() { return right_parenthesis_token; } }; // // TypeExpression --> <TYPE, Type> // class AstTypeExpression : public AstExpression { public: Ast *type; AstTypeExpression(Ast *type_) : type(type_) { Ast::kind = Ast::TYPE; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstTypeExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return type -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return type -> RightToken(); } }; // // ClassInstanceCreationExpression --> <CLASS_CREATION, new_token, TypeExpression, (_token, Arguments, )_token> // // Sometimes, during semantic analysis an artificial base_opt expression is constructed. // In such a case, the user can determine this condition by testing whether or not // dot_token_opt is 0; // class AstClassInstanceCreationExpression : public AstExpression { private: StoragePool *pool; AstArray<AstExpression *> *arguments; AstArray<AstExpression *> *local_arguments_opt; // used only for local classes that use enclosed local variables public: AstExpression *base_opt; LexStream::TokenIndex dot_token_opt; LexStream::TokenIndex new_token; AstTypeExpression *class_type; LexStream::TokenIndex left_parenthesis_token; LexStream::TokenIndex right_parenthesis_token; AstClassBody *class_body_opt; AstClassInstanceCreationExpression(StoragePool *pool_) : pool(pool_), arguments(NULL), local_arguments_opt(NULL) { Ast::kind = Ast::CLASS_CREATION; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstClassInstanceCreationExpression(); inline AstExpression *&Argument(int i) { return (*arguments)[i]; } inline int NumArguments() { return (arguments ? arguments -> Length() : 0); } inline void AllocateArguments(int estimate = 0); inline void AddArgument(AstExpression *); inline AstExpression *&LocalArgument(int i) { return (*local_arguments_opt)[i]; } inline int NumLocalArguments() { return (local_arguments_opt ? local_arguments_opt -> Length() : 0); } inline void AllocateLocalArguments(int estimate = 0); inline void AddLocalArgument(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (base_opt ? base_opt -> LeftToken() : new_token); } virtual LexStream::TokenIndex RightToken() { return (class_body_opt ? class_body_opt -> RightToken() : right_parenthesis_token); } }; // // DimExpr --> <DIM, [_token, Expression, ]_token> // class AstDimExpr : public Ast { public: LexStream::TokenIndex left_bracket_token; AstExpression *expression; LexStream::TokenIndex right_bracket_token; AstDimExpr() { Ast::kind = Ast::DIM; Ast::class_tag = Ast::NO_TAG; Ast::generated = 0; } virtual ~AstDimExpr(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_bracket_token; } virtual LexStream::TokenIndex RightToken() { return right_bracket_token; } }; // // ArrayCreationExpression --> <ARRAY_CREATION, new_token, Type, DimExprs, Brackets> // class AstArrayCreationExpression : public AstExpression { private: StoragePool *pool; AstArray<AstBrackets *> *brackets; AstArray<AstDimExpr *> *dim_exprs; public: LexStream::TokenIndex new_token; Ast *array_type; AstArrayInitializer *array_initializer_opt; AstArrayCreationExpression(StoragePool *pool_) : pool(pool_), brackets(NULL), dim_exprs(NULL) { Ast::kind = Ast::ARRAY_CREATION; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstArrayCreationExpression(); inline AstBrackets *&Brackets(int i) { return (*brackets)[i]; } inline int NumBrackets() { return (brackets ? brackets -> Length() : 0); } inline void AllocateBrackets(int estimate = 0); inline void AddBrackets(AstBrackets *); inline AstDimExpr *&DimExpr(int i) { return (*dim_exprs)[i]; } inline int NumDimExprs() { return (dim_exprs ? dim_exprs -> Length() : 0); } inline void AllocateDimExprs(int estimate = 0); inline void AddDimExpr(AstDimExpr *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return new_token; } virtual LexStream::TokenIndex RightToken() { return (array_initializer_opt ? array_initializer_opt -> RightToken() : (NumBrackets() > 0 ? Brackets(NumBrackets() - 1) -> RightToken() : DimExpr(NumDimExprs() - 1) -> RightToken())); } }; // // FieldAccess --> <DOT, Base, ._token, SimpleName> // | <DOT, TypeExpression, ._token, class_token> // | <DOT, TypeExpression, ._token, this_token> // // SuperField --> <DOT, TypeExpression, ._token, super_token> // // Base --> Primary // | Name // class AstFieldAccess : public AstExpression { public: enum FieldAccessTag { NONE, CLASS_TAG, THIS_TAG, SUPER_TAG, _num_kinds }; AstExpression *base; LexStream::TokenIndex dot_token; LexStream::TokenIndex identifier_token; // // When the right-side of a field access consists of // the keyword this, we resolve it either into a // "this" expression if it refers to "this" type or // to a method call that gives access to the relevant // (private) this$0. // // If the base expression of FieldAccess expression is // of the form expr.this.X, where X is a private variable // that is a member of an outer class, then we resolve it // into a method call to the read_mehod that gives access // to X. In some cases, we also need to resolve field accesses // of the form expr.class. // AstExpression *resolution_opt; AstFieldAccess(FieldAccessTag tag = NONE) : field_access_tag(tag), resolution_opt(NULL) { Ast::kind = Ast::DOT; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstFieldAccess(); bool IsNameAccess() { return field_access_tag == NONE; } bool IsThisAccess() { return field_access_tag == THIS_TAG; } bool IsSuperAccess() { return field_access_tag == SUPER_TAG; } bool IsClassAccess() { return field_access_tag == CLASS_TAG; } #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return base -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return identifier_token; } private: FieldAccessTag field_access_tag; }; // // MethodInvocation --> <CALL, Method, (_token, Arguments, )_token> // // Method --> SimpleName // | FieldAccess // class AstMethodInvocation : public AstExpression { private: StoragePool *pool; AstArray<AstExpression *> *arguments; public: AstExpression *method; LexStream::TokenIndex left_parenthesis_token; LexStream::TokenIndex right_parenthesis_token; AstMethodInvocation(StoragePool *pool_) : pool(pool_), arguments(NULL) { Ast::kind = Ast::CALL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstMethodInvocation(); inline AstExpression *&Argument(int i) { return (*arguments)[i]; } inline int NumArguments() { return (arguments ? arguments -> Length() : 0); } inline void AllocateArguments(int estimate = 0); inline void AddArgument(AstExpression *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return method -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return right_parenthesis_token; } }; // // ArrayAccess --> <ARRAY_ACCESS, Base, [_token, Expression, ]_token> // class AstArrayAccess : public AstExpression { public: AstExpression *base; LexStream::TokenIndex left_bracket_token; AstExpression *expression; LexStream::TokenIndex right_bracket_token; AstArrayAccess() { Ast::kind = Ast::ARRAY_ACCESS; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstArrayAccess(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return base -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return right_bracket_token; } }; // // UnaryExpression --> PreUnaryExpression // | PostUnaryExpression // | CastExpression // // PostUnaryExpression --> <POST_UNARY, PostUnaryTag, Expression, PostOperator> // // PostUnaryTag --> PLUSPLUS | MINUSMINUS // // PostOperator --> ++_token | --_token // class AstPostUnaryExpression : public AstExpression { public: enum PostUnaryExpressionTag { NONE, PLUSPLUS, MINUSMINUS, _num_kinds }; PostUnaryExpressionTag post_unary_tag; AstExpression *expression; LexStream::TokenIndex post_operator_token; // // When the left-hand side of an assignment is a name that refers // to a private field in an enclosing scope, the access method // that gives write-permission to that field is recorded here. // MethodSymbol *write_method; AstPostUnaryExpression(PostUnaryExpressionTag tag_) : post_unary_tag(tag_), write_method(NULL) { Ast::kind = Ast::POST_UNARY; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstPostUnaryExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return expression -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return post_operator_token; } }; // // PreUnaryExpression --> <PRE_UNARY, PreUnaryTag, PreOperator, Expression> // // PreUnaryTag --> PLUS | MINUS | TWIDDLE | NOT | PLUSPLUS | MINUSMINUS // // PreOperator --> +_token | -_token | ~_token | !_token | ++_token | --_token // class AstPreUnaryExpression : public AstExpression { public: enum PreUnaryExpressionTag { NONE, PLUSPLUS, MINUSMINUS, PLUS, MINUS, TWIDDLE, NOT, _num_kinds }; PreUnaryExpressionTag pre_unary_tag; LexStream::TokenIndex pre_operator_token; AstExpression *expression; // // When the left-hand side of an assignment is a name that refers // to a private field in an enclosing scope, the access method // that gives write-permission to that field is recorded here. // MethodSymbol *write_method; AstPreUnaryExpression(PreUnaryExpressionTag tag_) : pre_unary_tag(tag_), write_method(NULL) { Ast::kind = Ast::PRE_UNARY; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstPreUnaryExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return pre_operator_token; } virtual LexStream::TokenIndex RightToken() { return expression -> RightToken(); } }; // // CastExpression --> <cAstkind, (_token_opt, Type_opt, Brackets )_token_opt, Expression> // // cAstkind --> CAST // | CHECK_AND_CAST // // NOTE that the optional symbols above are absent only when the compiler inserts // a CAST conversion node into the program. // class AstCastExpression : public AstExpression { private: StoragePool *pool; AstArray<AstBrackets *> *brackets; public: LexStream::TokenIndex left_parenthesis_token_opt; Ast *type_opt; LexStream::TokenIndex right_parenthesis_token_opt; AstExpression *expression; AstCastExpression(StoragePool *pool_) : pool(pool_), brackets(NULL) { Ast::kind = Ast::CAST; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstCastExpression(); inline AstBrackets *&Brackets(int i) { return (*brackets)[i]; } inline int NumBrackets() { return (brackets ? brackets -> Length() : 0); } inline void AllocateBrackets(int estimate = 0); inline void AddBrackets(AstBrackets *); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return (left_parenthesis_token_opt ? left_parenthesis_token_opt : expression -> LeftToken()); } virtual LexStream::TokenIndex RightToken() { return expression -> RightToken(); } }; // // BinaryExpression --> <BINARY, BinaryTag, LeftExpression, BinaryOperator, RightExpression> // // LeftExpression --> Expression // // RightExpression --> Expression // | type // // BinaryTag --> STAR | SLASH | MOD | PLUS | MINUS | LEFT_SHIFT | RIGHT_SHIFT | UNSIGNED_RIGHT_SHIFT | // INSTANCEOF | LESS | GREATER | LESS_EQUAL | GREATER_EQUAL | EQUAL_EQUAL | NOT_EQUAL | // AND | XOR | IOR | AND_AND | OR_OR // // BinaryOperator --> *_token | /_token | %_token | +_token | -_token | <<_token | >>_token | >>>_token | // instanceof_token | <_token | >_token | <=_token | >=_token | ==_token | !=_token | // &_token | ^_token | |_token | &&_token | ||_token // class AstBinaryExpression : public AstExpression { public: enum BinaryExpressionTag { NONE, STAR, SLASH, MOD, PLUS, MINUS, LEFT_SHIFT, RIGHT_SHIFT, UNSIGNED_RIGHT_SHIFT, INSTANCEOF, LESS, GREATER, AND, XOR, IOR, AND_AND, OR_OR, LESS_EQUAL, GREATER_EQUAL, EQUAL_EQUAL, NOT_EQUAL, _num_kinds }; BinaryExpressionTag binary_tag; AstExpression *left_expression; LexStream::TokenIndex binary_operator_token; AstExpression *right_expression; AstBinaryExpression(BinaryExpressionTag tag_) : binary_tag(tag_) { Ast::kind = Ast::BINARY; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstBinaryExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_expression -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return right_expression -> RightToken(); } }; // // ConditionalExpression --> <CONDITIONAL, Expression, ?_token, Expression, :_token, Expression> // class AstConditionalExpression : public AstExpression { public: AstExpression *test_expression; LexStream::TokenIndex question_token; AstExpression *true_expression; LexStream::TokenIndex colon_token; AstExpression *false_expression; AstConditionalExpression() { Ast::kind = Ast::CONDITIONAL; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstConditionalExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return test_expression -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return false_expression -> RightToken(); } }; // // Assignment --> <ASSIGNMENT, AssignmentTag, LeftHandSide, AssignmentOperator, Expression> // // AssignmentTag --> EQUAL | STAR_EQUAL | SLASH_EQUAL | MOD_EQUAL | PLUS_EQUAL | MINUS_EQUAL | // LEFT_SHIFT_EQUAL | RIGHT_SHIFT_EQUAL | UNSIGNED_RIGHT_SHIFT_EQUAL | // AND_EQUAL | XOR_EQUAL | IOR_EQUAL // // LeftHandSide --> Name | FieldAccess | ArrayAccess // | <cAstkind, (_token_opt, Type_opt, Brackets )_token_opt, Name> // | <cAstkind, (_token_opt, Type_opt, Brackets )_token_opt, FieldAccess> // | <cAstkind, (_token_opt, Type_opt, Brackets )_token_opt, ArrayAccess> // // NOTE: that a LeftHandSide appears as a cast node only when the assignment_operator in question // is of the form "op=" and the application of the operator requires a casting of the value of the // left-hand side. // // AssignmentOperator --> =_token | *=_token | /=_token | %=_token | +=_token | -=_token | // <<=_token | >>=_token | >>>=_token | &=_token | ^=_token | |=_token // class AstAssignmentExpression : public AstExpression { public: enum AssignmentExpressionTag { NONE, EQUAL, STAR_EQUAL, SLASH_EQUAL, MOD_EQUAL, PLUS_EQUAL, MINUS_EQUAL, LEFT_SHIFT_EQUAL, RIGHT_SHIFT_EQUAL, UNSIGNED_RIGHT_SHIFT_EQUAL, AND_EQUAL, XOR_EQUAL, IOR_EQUAL, _num_kinds }; // // When the left-hand side of an assignment is a name that refers // to a private field in an enclosing scope, the access method // that gives write-permission to that field is recorded here. // MethodSymbol *write_method; AssignmentExpressionTag assignment_tag; AstExpression *left_hand_side; LexStream::TokenIndex assignment_operator_token; AstExpression *expression; AstAssignmentExpression(AssignmentExpressionTag tag_, LexStream::TokenIndex token_) : assignment_tag(tag_), assignment_operator_token(token_), write_method(NULL) { Ast::kind = Ast::ASSIGNMENT; Ast::class_tag = Ast::EXPRESSION; Ast::generated = 0; AstExpression::value = NULL; AstExpression::symbol = NULL; } virtual ~AstAssignmentExpression(); #ifdef TEST virtual void Print(LexStream &); #endif virtual Ast *Clone(StoragePool *); virtual LexStream::TokenIndex LeftToken() { return left_hand_side -> LeftToken(); } virtual LexStream::TokenIndex RightToken() { return expression -> RightToken(); } }; // // Given an Ast tree, check whether or not it is a Name - simple or qualified. // inline bool Ast::IsName() { Ast *name = this; for (AstFieldAccess *field_access = name -> FieldAccessCast(); field_access && field_access -> IsNameAccess(); field_access = name -> FieldAccessCast()) name = field_access -> base; return (name -> SimpleNameCast() != NULL); } // // Given an Ast tree, check whether or not it is a Name - simple or qualified. // inline bool Ast::IsLeftHandSide() { return (this -> SimpleNameCast() || this -> FieldAccessCast() || this -> ArrayAccessCast()); } // // Given an Ast tree, check whether or not it is a Name - simple or qualified. // inline bool Ast::IsGenerated() { return (generated == 1); } // // This Storage pool is modeled after the Dynamic arrays. The difference is that // instead of a Next() function we have an alloc(size_t) function. The value // of the size_t argument represents the size of the object to allocate. // class StoragePool { typedef void * Cell; Cell **base; int base_size, top, size; size_t log_blksize, base_increment; inline size_t Blksize() { return (1 << log_blksize); } // // Allocate another block of storage for the storage pool // inline void AllocateMoreSpace() { // // The variable size always indicates the maximum number of // cells that has been allocated for the storage pool. // Initially, it is set to 0 to indicate that the pool is empty. // The pool of available elements is divided into segments of size // 2**log_blksize each. Each segment is pointed to by a slot in // the array base. // // By dividing size by the size of the segment we obtain the // index for the next segment in base. If base is full, it is // reallocated. // // int k = size >> log_blksize; /* which segment? */ // // If the base is overflowed, reallocate it and initialize the new elements to NULL. // if (k == base_size) { int old_base_size = base_size; Cell **old_base = base; base_size += base_increment; base = ::new Cell*[base_size]; if (old_base != NULL) { memmove(base, old_base, old_base_size * sizeof(Cell *)); delete [] old_base; } memset(&base[old_base_size], 0, (base_size - old_base_size) * sizeof(Cell *)); } // // If the slot "k" does not already contain a segment, // we allocate a new segment and place its adjusted address in // base[k]. The adjustment allows us to index the segment directly, // instead of having to perform a subtraction for each reference. // See operator[] below. // if (base[k] == NULL) { base[k] = ::new Cell[Blksize()]; base[k] -= size; } // // Finally, we update SIZE. // size += Blksize(); return; } public: // // Constructor of a storage pool // StoragePool(size_t num_tokens) { // // Make a guess on the size that will be required for the ast // based on the number of tokens. The ratio for the bodies is // usually 40 to 1. We will double the base to add to account // for the headers // size_t estimate = num_tokens * 10; // recall that each cell is a-byte word. So, 10 * 4 = 40 // // Find a block of size 2**log_blksize that is large enough // to satisfy our estimate. // for (log_blksize = 8; (((unsigned) 1 << log_blksize) < estimate) && (log_blksize < 31); log_blksize++) ; // // If the size of the block found is < 1k, allocate a block of size 1k // with one slot to spare, just in case. // If the size is less than 16k, then break it up into equal blocks // of size 1k; // Otherwise, fragment it into pieces of size 16k. // if (log_blksize < 8) { base_increment = 1; log_blksize = 8; } else if (log_blksize < 13) { base_increment = (unsigned) 1 << (log_blksize - 8); log_blksize = 8; } else if (log_blksize < 17) { base_increment = (unsigned) 1 << (log_blksize - 10); log_blksize = 10; } else { base_increment = (unsigned) 1 << (log_blksize - 12); // assume we won't be allocating more than this many blocks. log_blksize = 12; } // // Double the size of the base in order to allocate extra space for the headers // and add a little margin for stuff like extra Cast node and computation of // static expressions that require cloning. // base_increment = (base_increment << 1) + 3; base_size = 0; size = 0; top = 0; base = NULL; } // // Destructor of a storage pool // ~StoragePool() { for (int k = (size >> log_blksize) - 1; k >= 0; k--) { size -= Blksize(); base[k] += size; delete [] base[k]; } delete [] base; } // // alloc allocates an object of size n in the pool and // returns a pointer to it. // inline void *Alloc(size_t n) { size_t i = top; top += ((n + sizeof(Cell) - 1) / sizeof(Cell)); if (top > size) { if (n > Blksize()) // we cannot allocate a chunk of storage that is larger than the block ! assert(0); i = size; top = size + ((n + sizeof(Cell) - 1) / sizeof(Cell)); AllocateMoreSpace(); } return ((void *) &(base[i >> log_blksize] [i])); } // // Return length of the amount of storage that has been allocated so far. // inline size_t Length() { return top; } // // This function is used to reset the Storage pool. This action automatically // invalidates all objects that had been allocated in the pool. At least, // YOU should assume it does!!! // inline void Reset(const int n = 0) { if (n < 0 || n > size) assert(0); top = n; } // // This function frees up all dynamic space that // was allocated for this storage pool. // inline void Destroy() { for (int k = (size >> log_blksize) - 1; k >= 0; k--) { size -= Blksize(); base[k] += size; delete [] base[k]; base[k] = NULL; } delete [] base; base = NULL; base_size = 0; Reset(); return; } // ********************************************************************************************** // inline AstArray<Ast *> *NewAstArray(unsigned size = 0) { return new (Alloc(sizeof(AstArray<Ast *>))) AstArray<Ast *>((StoragePool *) this, size); } inline AstListNode *NewListNode() { return new (Alloc(sizeof(AstListNode))) AstListNode(); } inline AstBlock *NewBlock() { return new (Alloc(sizeof(AstBlock))) AstBlock((StoragePool *) this); } inline AstPrimitiveType *NewPrimitiveType(Ast::Kind kind, LexStream::TokenIndex token) { return new (Alloc(sizeof(AstPrimitiveType))) AstPrimitiveType(kind, token); } inline AstArrayType *NewArrayType() { return new (Alloc(sizeof(AstArrayType))) AstArrayType((StoragePool *) this); } inline AstSimpleName *NewSimpleName(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstSimpleName))) AstSimpleName(token); } inline AstPackageDeclaration *NewPackageDeclaration() { return new (Alloc(sizeof(AstPackageDeclaration))) AstPackageDeclaration(); } inline AstImportDeclaration *NewImportDeclaration() { return new (Alloc(sizeof(AstImportDeclaration))) AstImportDeclaration(); } inline AstCompilationUnit *NewCompilationUnit() { return new (Alloc(sizeof(AstCompilationUnit))) AstCompilationUnit((StoragePool *) this); } inline AstModifier *NewModifier(Ast::Kind kind, LexStream::TokenIndex token) { return new (Alloc(sizeof(AstModifier))) AstModifier(kind, token); } inline AstEmptyDeclaration *NewEmptyDeclaration(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstEmptyDeclaration))) AstEmptyDeclaration(token); } inline AstClassBody *NewClassBody() { return new (Alloc(sizeof(AstClassBody))) AstClassBody((StoragePool *) this); } inline AstClassDeclaration *NewClassDeclaration() { return new (Alloc(sizeof(AstClassDeclaration))) AstClassDeclaration((StoragePool *) this); } inline AstArrayInitializer *NewArrayInitializer() { return new (Alloc(sizeof(AstArrayInitializer))) AstArrayInitializer((StoragePool *) this); } inline AstBrackets *NewBrackets(LexStream::TokenIndex left, LexStream::TokenIndex right) { return new (Alloc(sizeof(AstBrackets))) AstBrackets(left, right); } inline AstVariableDeclaratorId *NewVariableDeclaratorId() { return new (Alloc(sizeof(AstVariableDeclaratorId))) AstVariableDeclaratorId((StoragePool *) this); } inline AstVariableDeclarator *NewVariableDeclarator() { return new (Alloc(sizeof(AstVariableDeclarator))) AstVariableDeclarator(); } inline AstFieldDeclaration *NewFieldDeclaration() { return new (Alloc(sizeof(AstFieldDeclaration))) AstFieldDeclaration((StoragePool *) this); } inline AstFormalParameter *NewFormalParameter() { return new (Alloc(sizeof(AstFormalParameter))) AstFormalParameter((StoragePool *) this); } inline AstMethodDeclarator *NewMethodDeclarator() { return new (Alloc(sizeof(AstMethodDeclarator))) AstMethodDeclarator((StoragePool *) this); } inline AstMethodDeclaration *NewMethodDeclaration() { return new (Alloc(sizeof(AstMethodDeclaration))) AstMethodDeclaration((StoragePool *) this); } inline AstStaticInitializer *NewStaticInitializer() { return new (Alloc(sizeof(AstStaticInitializer))) AstStaticInitializer(); } inline AstThisCall *NewThisCall() { return new (Alloc(sizeof(AstThisCall))) AstThisCall((StoragePool *) this); } inline AstSuperCall *NewSuperCall() { return new (Alloc(sizeof(AstSuperCall))) AstSuperCall((StoragePool *) this); } inline AstConstructorBlock *NewConstructorBlock() { return new (Alloc(sizeof(AstConstructorBlock))) AstConstructorBlock((StoragePool *) this); } inline AstConstructorDeclaration *NewConstructorDeclaration() { return new (Alloc(sizeof(AstConstructorDeclaration))) AstConstructorDeclaration((StoragePool *) this); } inline AstInterfaceDeclaration *NewInterfaceDeclaration() { return new (Alloc(sizeof(AstInterfaceDeclaration))) AstInterfaceDeclaration((StoragePool *) this); } inline AstLocalVariableDeclarationStatement *NewLocalVariableDeclarationStatement() { return new (Alloc(sizeof(AstLocalVariableDeclarationStatement))) AstLocalVariableDeclarationStatement((StoragePool *) this); } inline AstIfStatement *NewIfStatement() { return new (Alloc(sizeof(AstIfStatement))) AstIfStatement(); } inline AstEmptyStatement *NewEmptyStatement(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstEmptyStatement))) AstEmptyStatement(token); } inline AstExpressionStatement *NewExpressionStatement() { return new (Alloc(sizeof(AstExpressionStatement))) AstExpressionStatement(); } inline AstCaseLabel *NewCaseLabel() { return new (Alloc(sizeof(AstCaseLabel))) AstCaseLabel(); } inline AstDefaultLabel *NewDefaultLabel() { return new (Alloc(sizeof(AstDefaultLabel))) AstDefaultLabel(); } inline AstSwitchBlockStatement *NewSwitchBlockStatement() { return new (Alloc(sizeof(AstSwitchBlockStatement))) AstSwitchBlockStatement((StoragePool *) this); } inline AstSwitchStatement *NewSwitchStatement() { return new (Alloc(sizeof(AstSwitchStatement))) AstSwitchStatement((StoragePool *) this); } inline AstWhileStatement *NewWhileStatement() { return new (Alloc(sizeof(AstWhileStatement))) AstWhileStatement(); } inline AstDoStatement *NewDoStatement() { return new (Alloc(sizeof(AstDoStatement))) AstDoStatement(); } inline AstForStatement *NewForStatement() { return new (Alloc(sizeof(AstForStatement))) AstForStatement((StoragePool *) this); } inline AstBreakStatement *NewBreakStatement() { return new (Alloc(sizeof(AstBreakStatement))) AstBreakStatement(); } inline AstContinueStatement *NewContinueStatement() { return new (Alloc(sizeof(AstContinueStatement))) AstContinueStatement(); } inline AstReturnStatement *NewReturnStatement() { return new (Alloc(sizeof(AstReturnStatement))) AstReturnStatement(); } inline AstThrowStatement *NewThrowStatement() { return new (Alloc(sizeof(AstThrowStatement))) AstThrowStatement(); } inline AstSynchronizedStatement *NewSynchronizedStatement() { return new (Alloc(sizeof(AstSynchronizedStatement))) AstSynchronizedStatement(); } inline AstCatchClause *NewCatchClause() { return new (Alloc(sizeof(AstCatchClause))) AstCatchClause(); } inline AstFinallyClause *NewFinallyClause() { return new (Alloc(sizeof(AstFinallyClause))) AstFinallyClause(); } inline AstTryStatement *NewTryStatement() { return new (Alloc(sizeof(AstTryStatement))) AstTryStatement((StoragePool *) this); } inline AstIntegerLiteral *NewIntegerLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstIntegerLiteral))) AstIntegerLiteral(token); } inline AstLongLiteral *NewLongLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstLongLiteral))) AstLongLiteral(token); } inline AstFloatingPointLiteral *NewFloatingPointLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstFloatingPointLiteral))) AstFloatingPointLiteral(token); } inline AstDoubleLiteral *NewDoubleLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstDoubleLiteral))) AstDoubleLiteral(token); } inline AstTrueLiteral *NewTrueLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstTrueLiteral))) AstTrueLiteral(token); } inline AstFalseLiteral *NewFalseLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstFalseLiteral))) AstFalseLiteral(token); } inline AstStringLiteral *NewStringLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstStringLiteral))) AstStringLiteral(token); } inline AstCharacterLiteral *NewCharacterLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstCharacterLiteral))) AstCharacterLiteral(token); } inline AstNullLiteral *NewNullLiteral(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstNullLiteral))) AstNullLiteral(token); } inline AstThisExpression *NewThisExpression(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstThisExpression))) AstThisExpression(token); } inline AstSuperExpression *NewSuperExpression(LexStream::TokenIndex token) { return new (Alloc(sizeof(AstSuperExpression))) AstSuperExpression(token); } inline AstParenthesizedExpression *NewParenthesizedExpression() { return new (Alloc(sizeof(AstParenthesizedExpression))) AstParenthesizedExpression(); } inline AstTypeExpression *NewTypeExpression(Ast *type) { return new (Alloc(sizeof(AstTypeExpression))) AstTypeExpression(type); } inline AstClassInstanceCreationExpression *NewClassInstanceCreationExpression() { return new (Alloc(sizeof(AstClassInstanceCreationExpression))) AstClassInstanceCreationExpression((StoragePool *) this); } inline AstDimExpr *NewDimExpr() { return new (Alloc(sizeof(AstDimExpr))) AstDimExpr(); } inline AstArrayCreationExpression *NewArrayCreationExpression() { return new (Alloc(sizeof(AstArrayCreationExpression))) AstArrayCreationExpression((StoragePool *) this); } inline AstFieldAccess *NewFieldAccess(AstFieldAccess::FieldAccessTag tag = AstFieldAccess::NONE) { return new (Alloc(sizeof(AstFieldAccess))) AstFieldAccess(tag); } inline AstMethodInvocation *NewMethodInvocation() { return new (Alloc(sizeof(AstMethodInvocation))) AstMethodInvocation((StoragePool *) this); } inline AstArrayAccess *NewArrayAccess() { return new (Alloc(sizeof(AstArrayAccess))) AstArrayAccess(); } inline AstPostUnaryExpression *NewPostUnaryExpression(AstPostUnaryExpression::PostUnaryExpressionTag tag) { return new (Alloc(sizeof(AstPostUnaryExpression))) AstPostUnaryExpression(tag); } inline AstPreUnaryExpression *NewPreUnaryExpression(AstPreUnaryExpression::PreUnaryExpressionTag tag) { return new (Alloc(sizeof(AstPreUnaryExpression))) AstPreUnaryExpression(tag); } inline AstCastExpression *NewCastExpression() { return new (Alloc(sizeof(AstCastExpression))) AstCastExpression((StoragePool *) this); } inline AstBinaryExpression *NewBinaryExpression(AstBinaryExpression::BinaryExpressionTag tag) { return new (Alloc(sizeof(AstBinaryExpression))) AstBinaryExpression(tag); } inline AstConditionalExpression *NewConditionalExpression() { return new (Alloc(sizeof(AstConditionalExpression))) AstConditionalExpression(); } inline AstAssignmentExpression *NewAssignmentExpression(AstAssignmentExpression::AssignmentExpressionTag tag, LexStream::TokenIndex token) { return new (Alloc(sizeof(AstAssignmentExpression))) AstAssignmentExpression(tag, token); } // ********************************************************************************************** // // // Note that CaseElement nodes are always generated. // Since they are not Ast nodes they do not need to // be marked. // inline CaseElement *GenCaseElement() { return new (Alloc(sizeof(CaseElement))) CaseElement(); } inline AstBlock *GenBlock() { AstBlock *p = NewBlock(); p -> generated = 1; return p; } inline AstPrimitiveType *GenPrimitiveType(Ast::Kind kind, LexStream::TokenIndex token) { AstPrimitiveType *p = NewPrimitiveType(kind, token); p -> generated = 1; return p; } inline AstArrayType *GenArrayType() { AstArrayType *p = NewArrayType(); p -> generated = 1; return p; } inline AstSimpleName *GenSimpleName(LexStream::TokenIndex token) { AstSimpleName *p = NewSimpleName(token); p -> generated = 1; return p; } inline AstPackageDeclaration *GenPackageDeclaration() { AstPackageDeclaration *p = NewPackageDeclaration(); p -> generated = 1; return p; } inline AstImportDeclaration *GenImportDeclaration() { AstImportDeclaration *p = NewImportDeclaration(); p -> generated = 1; return p; } inline AstCompilationUnit *GenCompilationUnit() { AstCompilationUnit *p = NewCompilationUnit(); p -> generated = 1; return p; } inline AstModifier *GenModifier(Ast::Kind kind, LexStream::TokenIndex token) { AstModifier *p = NewModifier(kind, token); p -> generated = 1; return p; } inline AstEmptyDeclaration *GenEmptyDeclaration(LexStream::TokenIndex token) { AstEmptyDeclaration *p = NewEmptyDeclaration(token); p -> generated = 1; return p; } inline AstClassBody *GenClassBody() { AstClassBody *p = NewClassBody(); p -> generated = 1; return p; } inline AstClassDeclaration *GenClassDeclaration() { AstClassDeclaration *p = NewClassDeclaration(); p -> generated = 1; return p; } inline AstArrayInitializer *GenArrayInitializer() { AstArrayInitializer *p = NewArrayInitializer(); p -> generated = 1; return p; } inline AstBrackets *GenBrackets(LexStream::TokenIndex left, LexStream::TokenIndex right) { AstBrackets *p = NewBrackets(left, right); p -> generated = 1; return p; } inline AstVariableDeclaratorId *GenVariableDeclaratorId() { AstVariableDeclaratorId *p = NewVariableDeclaratorId(); p -> generated = 1; return p; } inline AstVariableDeclarator *GenVariableDeclarator() { AstVariableDeclarator *p = NewVariableDeclarator(); p -> generated = 1; return p; } inline AstFieldDeclaration *GenFieldDeclaration() { AstFieldDeclaration *p = NewFieldDeclaration(); p -> generated = 1; return p; } inline AstFormalParameter *GenFormalParameter() { AstFormalParameter *p = NewFormalParameter(); p -> generated = 1; return p; } inline AstMethodDeclarator *GenMethodDeclarator() { AstMethodDeclarator *p = NewMethodDeclarator(); p -> generated = 1; return p; } inline AstMethodDeclaration *GenMethodDeclaration() { AstMethodDeclaration *p = NewMethodDeclaration(); p -> generated = 1; return p; } inline AstStaticInitializer *GenStaticInitializer() { AstStaticInitializer *p = NewStaticInitializer(); p -> generated = 1; return p; } inline AstThisCall *GenThisCall() { AstThisCall *p = NewThisCall(); p -> generated = 1; return p; } inline AstSuperCall *GenSuperCall() { AstSuperCall *p = NewSuperCall(); p -> generated = 1; return p; } inline AstConstructorBlock *GenConstructorBlock() { AstConstructorBlock *p = NewConstructorBlock(); p -> generated = 1; return p; } inline AstConstructorDeclaration *GenConstructorDeclaration() { AstConstructorDeclaration *p = NewConstructorDeclaration(); p -> generated = 1; return p; } inline AstInterfaceDeclaration *GenInterfaceDeclaration() { AstInterfaceDeclaration *p = NewInterfaceDeclaration(); p -> generated = 1; return p; } inline AstLocalVariableDeclarationStatement *GenLocalVariableDeclarationStatement() { AstLocalVariableDeclarationStatement *p = NewLocalVariableDeclarationStatement(); p -> generated = 1; return p; } inline AstIfStatement *GenIfStatement() { AstIfStatement *p = NewIfStatement(); p -> generated = 1; return p; } inline AstEmptyStatement *GenEmptyStatement(LexStream::TokenIndex token) { AstEmptyStatement *p = NewEmptyStatement(token); p -> generated = 1; return p; } inline AstExpressionStatement *GenExpressionStatement() { AstExpressionStatement *p = NewExpressionStatement(); p -> generated = 1; return p; } inline AstCaseLabel *GenCaseLabel() { AstCaseLabel *p = NewCaseLabel(); p -> generated = 1; return p; } inline AstDefaultLabel *GenDefaultLabel() { AstDefaultLabel *p = NewDefaultLabel(); p -> generated = 1; return p; } inline AstSwitchBlockStatement *GenSwitchBlockStatement() { AstSwitchBlockStatement *p = NewSwitchBlockStatement(); p -> generated = 1; return p; } inline AstSwitchStatement *GenSwitchStatement() { AstSwitchStatement *p = NewSwitchStatement(); p -> generated = 1; return p; } inline AstWhileStatement *GenWhileStatement() { AstWhileStatement *p = NewWhileStatement(); p -> generated = 1; return p; } inline AstDoStatement *GenDoStatement() { AstDoStatement *p = NewDoStatement(); p -> generated = 1; return p; } inline AstForStatement *GenForStatement() { AstForStatement *p = NewForStatement(); p -> generated = 1; return p; } inline AstBreakStatement *GenBreakStatement() { AstBreakStatement *p = NewBreakStatement(); p -> generated = 1; return p; } inline AstContinueStatement *GenContinueStatement() { AstContinueStatement *p = NewContinueStatement(); p -> generated = 1; return p; } inline AstReturnStatement *GenReturnStatement() { AstReturnStatement *p = NewReturnStatement(); p -> generated = 1; return p; } inline AstThrowStatement *GenThrowStatement() { AstThrowStatement *p = NewThrowStatement(); p -> generated = 1; return p; } inline AstSynchronizedStatement *GenSynchronizedStatement() { AstSynchronizedStatement *p = NewSynchronizedStatement(); p -> generated = 1; return p; } inline AstCatchClause *GenCatchClause() { AstCatchClause *p = NewCatchClause(); p -> generated = 1; return p; } inline AstFinallyClause *GenFinallyClause() { AstFinallyClause *p = NewFinallyClause(); p -> generated = 1; return p; } inline AstTryStatement *GenTryStatement() { AstTryStatement *p = NewTryStatement(); p -> generated = 1; return p; } inline AstIntegerLiteral *GenIntegerLiteral(LexStream::TokenIndex token) { AstIntegerLiteral *p = NewIntegerLiteral(token); p -> generated = 1; return p; } inline AstLongLiteral *GenLongLiteral(LexStream::TokenIndex token) { AstLongLiteral *p = NewLongLiteral(token); p -> generated = 1; return p; } inline AstFloatingPointLiteral *GenFloatingPointLiteral(LexStream::TokenIndex token) { AstFloatingPointLiteral *p = NewFloatingPointLiteral(token); p -> generated = 1; return p; } inline AstDoubleLiteral *GenDoubleLiteral(LexStream::TokenIndex token) { AstDoubleLiteral *p = NewDoubleLiteral(token); p -> generated = 1; return p; } inline AstTrueLiteral *GenTrueLiteral(LexStream::TokenIndex token) { AstTrueLiteral *p = NewTrueLiteral(token); p -> generated = 1; return p; } inline AstFalseLiteral *GenFalseLiteral(LexStream::TokenIndex token) { AstFalseLiteral *p = NewFalseLiteral(token); p -> generated = 1; return p; } inline AstStringLiteral *GenStringLiteral(LexStream::TokenIndex token) { AstStringLiteral *p = NewStringLiteral(token); p -> generated = 1; return p; } inline AstCharacterLiteral *GenCharacterLiteral(LexStream::TokenIndex token) { AstCharacterLiteral *p = NewCharacterLiteral(token); p -> generated = 1; return p; } inline AstNullLiteral *GenNullLiteral(LexStream::TokenIndex token) { AstNullLiteral *p = NewNullLiteral(token); p -> generated = 1; return p; } inline AstThisExpression *GenThisExpression(LexStream::TokenIndex token) { AstThisExpression *p = NewThisExpression(token); p -> generated = 1; return p; } inline AstSuperExpression *GenSuperExpression(LexStream::TokenIndex token) { AstSuperExpression *p = NewSuperExpression(token); p -> generated = 1; return p; } inline AstParenthesizedExpression *GenParenthesizedExpression() { AstParenthesizedExpression *p = NewParenthesizedExpression(); p -> generated = 1; return p; } inline AstTypeExpression *GenTypeExpression(Ast *type) { AstTypeExpression *p = NewTypeExpression(type); p -> generated = 1; return p; } inline AstClassInstanceCreationExpression *GenClassInstanceCreationExpression() { AstClassInstanceCreationExpression *p = NewClassInstanceCreationExpression(); p -> generated = 1; return p; } inline AstDimExpr *GenDimExpr() { AstDimExpr *p = NewDimExpr(); p -> generated = 1; return p; } inline AstArrayCreationExpression *GenArrayCreationExpression() { AstArrayCreationExpression *p = NewArrayCreationExpression(); p -> generated = 1; return p; } inline AstFieldAccess *GenFieldAccess(AstFieldAccess::FieldAccessTag tag = AstFieldAccess::NONE) { AstFieldAccess *p = NewFieldAccess(tag); p -> generated = 1; return p; } inline AstMethodInvocation *GenMethodInvocation() { AstMethodInvocation *p = NewMethodInvocation(); p -> generated = 1; return p; } inline AstArrayAccess *GenArrayAccess() { AstArrayAccess *p = NewArrayAccess(); p -> generated = 1; return p; } inline AstPostUnaryExpression *GenPostUnaryExpression(AstPostUnaryExpression::PostUnaryExpressionTag tag) { AstPostUnaryExpression *p = NewPostUnaryExpression(tag); p -> generated = 1; return p; } inline AstPreUnaryExpression *GenPreUnaryExpression(AstPreUnaryExpression::PreUnaryExpressionTag tag) { AstPreUnaryExpression *p = NewPreUnaryExpression(tag); p -> generated = 1; return p; } inline AstCastExpression *GenCastExpression() { AstCastExpression *p = NewCastExpression(); p -> generated = 1; return p; } inline AstBinaryExpression *GenBinaryExpression(AstBinaryExpression::BinaryExpressionTag tag) { AstBinaryExpression *p = NewBinaryExpression(tag); p -> generated = 1; return p; } inline AstConditionalExpression *GenConditionalExpression() { AstConditionalExpression *p = NewConditionalExpression(); p -> generated = 1; return p; } inline AstAssignmentExpression *GenAssignmentExpression(AstAssignmentExpression::AssignmentExpressionTag tag, LexStream::TokenIndex token) { AstAssignmentExpression *p = NewAssignmentExpression(tag, token); p -> generated = 1; return p; } // ********************************************************************************************** // // // Return the total size of temporary space allocated. // size_t SpaceAllocated(void) { return ((base_size * sizeof(Cell **)) + (size * sizeof(Cell))); } // // Return the total size of temporary space used. // size_t SpaceUsed(void) { return (((size >> log_blksize) * sizeof(Cell **)) + (top * sizeof(Cell))); } }; // // Allocate another block of storage for the ast array. // template <class T> void AstArray<T>::AllocateMoreSpace() { // // // The variable size always indicates the maximum number of // elements that has been allocated for the array. // Initially, it is set to 0 to indicate that the array is empty. // The pool of available elements is divided into segments of size // 2**log_blksize each. Each segment is pointed to by a slot in // the array base. // // By dividing size by the size of the segment we obtain the // index for the next segment in base. If base is full, it is // reallocated. // // int k = size >> log_blksize; /* which segment? */ // // If the base is overflowed, reallocate it and initialize the new elements to NULL. // if (k == base_size) { int old_base_size = base_size; T **old_base = base; base_size += base_increment; base = (T **) pool -> Alloc(sizeof(T *) * base_size); if (old_base != NULL) { memmove(base, old_base, old_base_size * sizeof(T *)); // STG: // delete [] old_base; } memset(&base[old_base_size], 0, (base_size - old_base_size) * sizeof(T *)); } // // We allocate a new segment and place its adjusted address in // base[k]. The adjustment allows us to index the segment directly, // instead of having to perform a subtraction for each reference. // See operator[] below. // base[k] = (T *) pool -> Alloc(sizeof(T) * Blksize()); base[k] -= size; // // Finally, we update size. // size += Blksize(); return; } inline void AstClassBody::AllocateInstanceVariables(int estimate) { if (! instance_variables) instance_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddInstanceVariable(AstFieldDeclaration *field_declaration) { if (! instance_variables) instance_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(); instance_variables -> Next() = field_declaration; } inline void AstClassBody::AllocateClassVariables(int estimate) { if (! class_variables) class_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddClassVariable(AstFieldDeclaration *field_declaration) { if (! class_variables) class_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(); class_variables -> Next() = field_declaration; } inline void AstClassBody::AllocateMethods(int estimate) { if (! methods) methods = (AstArray<AstMethodDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddMethod(AstMethodDeclaration *method_declaration) { if (! methods) methods = (AstArray<AstMethodDeclaration *> *) pool -> NewAstArray(); methods -> Next() = method_declaration; } inline void AstClassBody::AllocateBlocks(int estimate) { if (! blocks) blocks = (AstArray<AstBlock *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddBlock(AstBlock *block) { if (! blocks) blocks = (AstArray<AstBlock *> *) pool -> NewAstArray(); blocks -> Next() = block; } inline void AstClassBody::AllocateNestedInterfaces(int estimate) { if (! inner_interfaces) inner_interfaces = (AstArray<AstInterfaceDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddNestedInterface(AstInterfaceDeclaration *interface_declaration) { if (! inner_interfaces) inner_interfaces = (AstArray<AstInterfaceDeclaration *> *) pool -> NewAstArray(); inner_interfaces -> Next() = interface_declaration; } inline void AstClassBody::AllocateNestedClasses(int estimate) { if (! inner_classes) inner_classes = (AstArray<AstClassDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddNestedClass(AstClassDeclaration *class_declaration) { if (! inner_classes) inner_classes = (AstArray<AstClassDeclaration *> *) pool -> NewAstArray(); inner_classes -> Next() = class_declaration; } inline void AstClassBody::AllocateStaticInitializers(int estimate) { if (! static_initializers) static_initializers = (AstArray<AstStaticInitializer *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddStaticInitializer(AstStaticInitializer *static_initializer) { if (! static_initializers) static_initializers = (AstArray<AstStaticInitializer *> *) pool -> NewAstArray(); static_initializers -> Next() = static_initializer; } inline void AstClassBody::AllocateConstructors(int estimate) { if (! constructors) constructors = (AstArray<AstConstructorDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddConstructor(AstConstructorDeclaration *constructor_declaration) { if (! constructors) constructors = (AstArray<AstConstructorDeclaration *> *) pool -> NewAstArray(); constructors -> Next() = constructor_declaration; } inline void AstClassBody::AllocateEmptyDeclarations(int estimate) { if (! empty_declarations) empty_declarations = (AstArray<AstEmptyDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstClassBody::AddEmptyDeclaration(AstEmptyDeclaration *empty_declaration) { if (! empty_declarations) empty_declarations = (AstArray<AstEmptyDeclaration *> *) pool -> NewAstArray(); empty_declarations -> Next() = empty_declaration; } inline void AstInterfaceDeclaration::AllocateNestedInterfaces(int estimate) { if (! inner_interfaces) inner_interfaces = (AstArray<AstInterfaceDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddNestedInterface(AstInterfaceDeclaration *interface_declaration) { if (! inner_interfaces) inner_interfaces = (AstArray<AstInterfaceDeclaration *> *) pool -> NewAstArray(); inner_interfaces -> Next() = interface_declaration; } inline void AstInterfaceDeclaration::AllocateNestedClasses(int estimate) { if (! inner_classes) inner_classes = (AstArray<AstClassDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddNestedClass(AstClassDeclaration *class_declaration) { if (! inner_classes) inner_classes = (AstArray<AstClassDeclaration *> *) pool -> NewAstArray(); inner_classes -> Next() = class_declaration; } inline void AstInterfaceDeclaration::AllocateMethods(int estimate) { if (! methods) methods = (AstArray<AstMethodDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddMethod(AstMethodDeclaration *method_declaration) { if (! methods) methods = (AstArray<AstMethodDeclaration *> *) pool -> NewAstArray(); methods -> Next() = method_declaration; } inline void AstInterfaceDeclaration::AllocateClassVariables(int estimate) { if (! class_variables) class_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddClassVariable(AstFieldDeclaration *field_declaration) { if (! class_variables) class_variables = (AstArray<AstFieldDeclaration *> *) pool -> NewAstArray(); class_variables -> Next() = field_declaration; } inline void AstInterfaceDeclaration::AllocateEmptyDeclarations(int estimate) { if (! empty_declarations) empty_declarations = (AstArray<AstEmptyDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddEmptyDeclaration(AstEmptyDeclaration *empty_declaration) { if (! empty_declarations) empty_declarations = (AstArray<AstEmptyDeclaration *> *) pool -> NewAstArray(); empty_declarations -> Next() = empty_declaration; } inline void AstClassDeclaration::AllocateClassModifiers(int estimate) { if (! class_modifiers) class_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstClassDeclaration::AddClassModifier(AstModifier *class_modifier) { if (! class_modifiers) AllocateClassModifiers(4); // there are only 10 modifiers. class_modifiers -> Next() = class_modifier; } inline void AstFieldDeclaration::AllocateVariableModifiers(int estimate) { if (! variable_modifiers) variable_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstFieldDeclaration::AddVariableModifier(AstModifier *variable_modifier) { if (! variable_modifiers) AllocateVariableModifiers(4); // there are only 10 modifiers. variable_modifiers -> Next() = variable_modifier; } inline void AstFormalParameter::AllocateParameterModifiers(int estimate) { if (! parameter_modifiers) parameter_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstFormalParameter::AddParameterModifier(AstModifier *parameter_modifier) { if (! parameter_modifiers) AllocateParameterModifiers(4); // there are only 10 modifiers. parameter_modifiers -> Next() = parameter_modifier; } inline void AstMethodDeclaration::AllocateMethodModifiers(int estimate) { if (! method_modifiers) method_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstMethodDeclaration::AddMethodModifier(AstModifier *method_modifier) { if (! method_modifiers) AllocateMethodModifiers(4); // there are only 10 modifiers. method_modifiers -> Next() = method_modifier; } inline void AstConstructorDeclaration::AllocateConstructorModifiers(int estimate) { if (! constructor_modifiers) constructor_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstConstructorDeclaration::AddConstructorModifier(AstModifier *constructor_modifier) { if (! constructor_modifiers) AllocateConstructorModifiers(4); // there are only 10 modifiers. constructor_modifiers -> Next() = constructor_modifier; } inline void AstInterfaceDeclaration::AllocateInterfaceModifiers(int estimate) { if (! interface_modifiers) interface_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddInterfaceModifier(AstModifier *interface_modifier) { if (! interface_modifiers) AllocateInterfaceModifiers(4); // there are only 10 modifiers. interface_modifiers -> Next() = interface_modifier; } inline void AstLocalVariableDeclarationStatement::AllocateLocalModifiers(int estimate) { if (! local_modifiers) local_modifiers = (AstArray<AstModifier *> *) pool -> NewAstArray(estimate); } inline void AstLocalVariableDeclarationStatement::AddLocalModifier(AstModifier *local_modifier) { if (! local_modifiers) AllocateLocalModifiers(4); // there are only 10 modifiers. local_modifiers -> Next() = local_modifier; } inline void AstBlock::AllocateBlockStatements(int estimate) { if (! block_statements) block_statements = pool -> NewAstArray(estimate); } inline void AstBlock::AddStatement(Ast *statement) { if (! block_statements) AllocateBlockStatements(); block_statements -> Next() = statement; } inline void AstSwitchBlockStatement::AllocateBlockStatements(int estimate) { if (! block_statements) block_statements = (AstArray<AstStatement *> *) pool -> NewAstArray(estimate); } inline void AstSwitchBlockStatement::AddStatement(AstStatement *statement) { if (! block_statements) AllocateBlockStatements(); block_statements -> Next() = statement; } inline void AstSwitchBlockStatement::AllocateSwitchLabels(int estimate) { if (! switch_labels) switch_labels = pool -> NewAstArray(estimate); } inline void AstSwitchBlockStatement::AddSwitchLabel(Ast *case_or_default_label) { if (! switch_labels) AllocateSwitchLabels(); switch_labels -> Next() = case_or_default_label; } inline void AstConstructorBlock::AllocateLocalInitStatements(int estimate) { if (! local_init_statements) local_init_statements = (AstArray<AstStatement *> *) pool -> NewAstArray(estimate); } inline void AstConstructorBlock::AddLocalInitStatement(AstStatement *statement) { if (! local_init_statements) AllocateLocalInitStatements(); local_init_statements -> Next() = statement; } inline void AstVariableDeclaratorId::AllocateBrackets(int estimate) { if (! brackets) brackets = (AstArray<AstBrackets *> *) pool -> NewAstArray(estimate); } inline void AstVariableDeclaratorId::AddBrackets(AstBrackets *bracket) { if (! brackets) AllocateBrackets(); brackets -> Next() = bracket; } inline void AstArrayType::AllocateBrackets(int estimate) { if (! brackets) brackets = (AstArray<AstBrackets *> *) pool -> NewAstArray(estimate); } inline void AstArrayType::AddBrackets(AstBrackets *bracket) { if (! brackets) AllocateBrackets(); brackets -> Next() = bracket; } inline void AstMethodDeclarator::AllocateBrackets(int estimate) { if (! brackets) brackets = (AstArray<AstBrackets *> *) pool -> NewAstArray(estimate); } inline void AstMethodDeclarator::AddBrackets(AstBrackets *bracket) { if (! brackets) AllocateBrackets(); brackets -> Next() = bracket; } inline void AstArrayCreationExpression::AllocateBrackets(int estimate) { if (! brackets) brackets = (AstArray<AstBrackets *> *) pool -> NewAstArray(estimate); } inline void AstArrayCreationExpression::AddBrackets(AstBrackets *bracket) { if (! brackets) AllocateBrackets(); brackets -> Next() = bracket; } inline void AstCastExpression::AllocateBrackets(int estimate) { if (! brackets) brackets = (AstArray<AstBrackets *> *) pool -> NewAstArray(estimate); } inline void AstCastExpression::AddBrackets(AstBrackets *bracket) { if (! brackets) AllocateBrackets(); brackets -> Next() = bracket; } inline void AstArrayCreationExpression::AllocateDimExprs(int estimate) { if (! dim_exprs) dim_exprs = (AstArray<AstDimExpr *> *) pool -> NewAstArray(estimate); } inline void AstArrayCreationExpression::AddDimExpr(AstDimExpr *dim_expr) { if (! dim_exprs) AllocateDimExprs(); // will not be executed as we can assume dim_exprs has already beenallocated dim_exprs -> Next() = dim_expr; } inline void AstThisCall::AllocateArguments(int estimate) { if (! arguments) arguments = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstThisCall::AddArgument(AstExpression *argument) { if (! arguments) AllocateArguments(); // will not be executed as we can assume arguments has already beenallocated arguments -> Next() = argument; } inline void AstSuperCall::AllocateArguments(int estimate) { if (! arguments) arguments = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstSuperCall::AddArgument(AstExpression *argument) { if (! arguments) AllocateArguments(); // will not be executed as we can assume arguments has already beenallocated arguments -> Next() = argument; } inline void AstClassInstanceCreationExpression::AllocateArguments(int estimate) { if (! arguments) arguments = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstClassInstanceCreationExpression::AddArgument(AstExpression *argument) { if (! arguments) AllocateArguments(); // will not be executed as we can assume arguments has already beenallocated arguments -> Next() = argument; } inline void AstMethodInvocation::AllocateArguments(int estimate) { if (! arguments) arguments = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstMethodInvocation::AddArgument(AstExpression *argument) { if (! arguments) AllocateArguments(); // will not be executed as we can assume arguments has already beenallocated arguments -> Next() = argument; } inline void AstThisCall::AllocateLocalArguments(int estimate) { if (! local_arguments_opt) local_arguments_opt = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstThisCall::AddLocalArgument(AstExpression *argument) { if (! local_arguments_opt) AllocateLocalArguments(); local_arguments_opt -> Next() = argument; } inline void AstSuperCall::AllocateLocalArguments(int estimate) { if (! local_arguments_opt) local_arguments_opt = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstSuperCall::AddLocalArgument(AstExpression *argument) { if (! local_arguments_opt) AllocateLocalArguments(); local_arguments_opt -> Next() = argument; } inline void AstClassInstanceCreationExpression::AllocateLocalArguments(int estimate) { if (! local_arguments_opt) local_arguments_opt = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstClassInstanceCreationExpression::AddLocalArgument(AstExpression *argument) { if (! local_arguments_opt) AllocateLocalArguments(); local_arguments_opt -> Next() = argument; } inline void AstMethodDeclaration::AllocateThrows(int estimate) { if (! throws) throws = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstMethodDeclaration::AddThrow(AstExpression *exception) { if (! throws) AllocateThrows(); throws -> Next() = exception; } inline void AstConstructorDeclaration::AllocateThrows(int estimate) { if (! throws) throws = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstConstructorDeclaration::AddThrow(AstExpression *exception) { if (! throws) AllocateThrows(); throws -> Next() = exception; } inline void AstMethodDeclarator::AllocateFormalParameters(int estimate) { if (! formal_parameters) formal_parameters = (AstArray<AstFormalParameter *> *) pool -> NewAstArray(estimate); } inline void AstMethodDeclarator::AddFormalParameter(AstFormalParameter *formal_parameter) { if (! formal_parameters) AllocateFormalParameters(); formal_parameters -> Next() = formal_parameter; } inline void AstLocalVariableDeclarationStatement::AllocateVariableDeclarators(int estimate) { if (! variable_declarators) variable_declarators = (AstArray<AstVariableDeclarator *> *) pool -> NewAstArray(estimate); } inline void AstLocalVariableDeclarationStatement::AddVariableDeclarator(AstVariableDeclarator *variable_declarator) { if (! variable_declarators) AllocateVariableDeclarators(); variable_declarators -> Next() = variable_declarator; } inline void AstFieldDeclaration::AllocateVariableDeclarators(int estimate) { if (! variable_declarators) variable_declarators = (AstArray<AstVariableDeclarator *> *) pool -> NewAstArray(estimate); } inline void AstFieldDeclaration::AddVariableDeclarator(AstVariableDeclarator *variable_declarator) { if (! variable_declarators) AllocateVariableDeclarators(); variable_declarators -> Next() = variable_declarator; } inline void AstClassDeclaration::AllocateInterfaces(int estimate) { if (! interfaces) interfaces = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstClassDeclaration::AddInterface(AstExpression *interf) { if (! interfaces) AllocateInterfaces(); interfaces -> Next() = interf; } inline void AstInterfaceDeclaration::AllocateExtendsInterfaces(int estimate) { if (! extends_interfaces) extends_interfaces = (AstArray<AstExpression *> *) pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddExtendsInterface(AstExpression *interf) { if (! extends_interfaces) AllocateExtendsInterfaces(); extends_interfaces -> Next() = interf; } inline void AstInterfaceDeclaration::AllocateInterfaceMemberDeclarations(int estimate) { if (! interface_member_declarations) interface_member_declarations = pool -> NewAstArray(estimate); } inline void AstInterfaceDeclaration::AddInterfaceMemberDeclaration(Ast *member) { if (! interface_member_declarations) AllocateInterfaceMemberDeclarations(); interface_member_declarations -> Next() = member; } inline void AstClassBody::AllocateClassBodyDeclarations(int estimate) { if (! class_body_declarations) class_body_declarations = pool -> NewAstArray(estimate); } inline void AstClassBody::AddClassBodyDeclaration(Ast *member) { if (! class_body_declarations) AllocateClassBodyDeclarations(); class_body_declarations -> Next() = member; } inline void AstForStatement::AllocateForInitStatements(int estimate) { if (! for_init_statements) for_init_statements = (AstArray<AstStatement *> *) pool -> NewAstArray(estimate); } inline void AstForStatement::AddForInitStatement(AstStatement *statement) { if (! for_init_statements) AllocateForInitStatements(); for_init_statements -> Next() = statement; } inline void AstForStatement::AllocateForUpdateStatements(int estimate) { if (! for_update_statements) for_update_statements = (AstArray<AstExpressionStatement *> *) pool -> NewAstArray(estimate); } inline void AstForStatement::AddForUpdateStatement(AstExpressionStatement *statement) { if (! for_update_statements) AllocateForUpdateStatements(); for_update_statements -> Next() = statement; } inline void AstArrayInitializer::AllocateVariableInitializers(int estimate) { if (! variable_initializers) variable_initializers = pool -> NewAstArray(estimate); } inline void AstArrayInitializer::AddVariableInitializer(Ast *initializer) { if (! variable_initializers) AllocateVariableInitializers(); variable_initializers -> Next() = initializer; } inline void AstTryStatement::AllocateCatchClauses(int estimate) { if (! catch_clauses) catch_clauses = (AstArray<AstCatchClause *> *) pool -> NewAstArray(estimate); } inline void AstTryStatement::AddCatchClause(AstCatchClause *catch_clause) { if (! catch_clauses) AllocateCatchClauses(); catch_clauses -> Next() = catch_clause; } inline void AstCompilationUnit::AllocateImportDeclarations(int estimate) { if (! import_declarations) import_declarations = (AstArray<AstImportDeclaration *> *) pool -> NewAstArray(estimate); } inline void AstCompilationUnit::AddImportDeclaration(AstImportDeclaration *import_declaration) { if (! import_declarations) AllocateImportDeclarations(); import_declarations -> Next() = import_declaration; } inline void AstCompilationUnit::AllocateTypeDeclarations(int estimate) { if (! type_declarations) type_declarations = pool -> NewAstArray(estimate); } inline void AstCompilationUnit::AddTypeDeclaration(Ast *type_declaration) { if (! type_declarations) AllocateTypeDeclarations(); type_declarations -> Next() = type_declaration; } #endif