/* Titanium Parser $Id: parser.yy 1.87.1.5.1.7.1.1.1.1.1.1 Wed, 03 Aug 2005 11:44:00 -0700 kamil $ */ /* With the exceptions noted below, the .val fields of terminal */ /* symbols are irrelevant and may be set to NULL by the lexer. */ /* KEYWORDS */ %token ABSTRACT %token ASSERT %token BOOLEAN BREAK BROADCAST BYTE %token CASE CATCH CHAR CLASS CONTINUE %token DEFAULT DO DOUBLE %token ELSE EXTENDS %token FINAL FINALLY FLOAT FOR %token FOREACH /* Titanium */ %token IF IMPLEMENTS IMPORT INSTANCEOF INT INTERFACE %token IMMUTABLE INLINE /* Titanium */ %token LOCAL /* Titanium */ %token LONG %token NATIVE NEW NULL_VAL %token OPERATOR OVERLAP /* Titanium */ %token _PACKAGE PRIVATE PROTECTED PUBLIC %token POLYSHARED NONSHARED /* Titanium */ %token PARTITION /* Titanium */ %token RETURN %token SHORT STATIC SUPER SWITCH SYNCHRONIZED STRICTFP %token SINGLE SGLOBAL /* Titanium */ %token TEMPLATE /* Titanium */ %token THIS THROW THROWS TRANSIENT TRY %token VOID VOLATILE %token WHILE /* KEYWORDS RESERVED (ILLEGAL AS IDENTIFIERS) BUT NOT USED */ /* %token CONST GOTO */ /* IDENTIFIERS AND LITERALS */ %token TRUE_LITERAL FALSE_LITERAL %token IDENTIFIER %token INT_LITERAL LONG_LITERAL %token FLOAT_LITERAL DOUBLE_LITERAL %token CHARACTER_LITERAL %token STRING_LITERAL /* SEPARATORS */ %token '(' ')' '{' '}' '[' ']' ',' '.' ';' '@' /* OPERATORS */ %token '=' '>' '<' '!' '~' '?' ':' %token '+' '-' '*' '/' '&' '|' '^' '%' %token CAND /* &&: conditional and */ %token COR /* ||: conditional or */ %token EQ /* == */ %token NE /* != */ %token LE /* <= */ %token GE /* >= */ %token LSHIFTL /* << */ %token ASHIFTR /* >> */ %token LSHIFTR /* >>> */ %token PLUS_ASG /* += */ %token MINUS_ASG /* -= */ %token MULT_ASG /* *= */ %token DIV_ASG /* /= */ %token REM_ASG /* %= */ %token LSHIFTL_ASG /* <<= */ %token ASHIFTR_ASG /* >>= */ %token LSHIFTR_ASG /* >>>= */ %token AND_ASG /* &= */ %token XOR_ASG /* ^= */ %token OR_ASG /* |= */ %token PLUSPLUS /* ++ */ %token MINUSMINUS /* -- */ %token GUARDS /* => */ /* Titanium */ /* PRECEDENCES */ /* LOWEST */ /* ']' resolves s/r conflict between op[]= and op[] = ... (we shift because the latter is illegal as operators cannot be field names) CLASS resolves s/r conflict on PrimitiveType.CLASS - always shift the '.' because it's otherwise always illegal after a Primitive type */ %left CLASS %right ELSE %left ']' %left '=' PLUS_ASG MINUS_ASG MULT_ASG DIV_ASG REM_ASG LSHIFTL_ASG LSHIFTR_ASG ASHIFTR_ASG AND_ASG OR_ASG XOR_ASG %right '?' ':' %left COR %left CAND %left '|' %left '^' %left '&' %left EQ NE %left '<' '>' LE GE INSTANCEOF %left LSHIFTL LSHIFTR ASHIFTR %left '+' '-' %left '*' '/' '%' %nonassoc PLUSPLUS MINUSMINUS /* HIGHEST */ /* Artificial precedence rules: /* The rule for '.' resolves conflicts with QualifiedNames, */ /* FieldAccesses, and MethodAccesses. The result is that */ /* FieldAccesses and MethodAccesses that look syntactically like */ /* QualifiedNames are parsed as QualifiedNames (see the production for */ /* Name from QualifiedName). The ambiguity must be resolved with */ /* static semantic information at a later stage. */ /* The rule for ')' resolves conflicts between Casts and ComplexPrimaries. */ %right '.' ')' /* Artificial precedence rule to resolve conflicts with */ /* InterfaceModifiers and ClassModifiers */ %right ABSTRACT FINAL PUBLIC /* Artificial precedence rule to favour interpreting [ (id)id ] in ArrayName as [ Expression ] rather than [ Expression IDENTIFIER ] */ %left IDENTIFIER %{ #include #include #include "AST.h" #include "errors.h" #include "parse.h" #include "tokens.h" #include "code-util.h" #include "pseudocode.h" #include "lex-string.h" #define YYDEBUG 1 #ifdef HAVE_ALLOCA # define YYSTACK_USE_ALLOCA 1 # if HAVE_ALLOCA_H # include # else extern "C" void *alloca(size_t size); # endif // HAVE_ALLOCA_H #if defined(__GNUC__) && !defined(alloca) #define alloca __builtin_alloca #endif #endif // HAVE_ALLOCA static void yyerror(const char* msg); static TreeNode *newOperator(char *op, SourcePosn p); /* Routines to check the validity of modifier flags. Each routine */ /* takes a logical `or' of flag values and a source position to which */ /* to refer error messages. */ static void checkFieldModifiers (Common::Modifiers flags, SourcePosn posn); static void checkConstantFieldModifiers (Common::Modifiers flags, SourcePosn posn); static void checkMethodModifiers (Common::Modifiers flags, SourcePosn posn); static void checkConstructorModifiers (Common::Modifiers flags, SourcePosn posn); static void checkMethodSignatureModifiers (Common::Modifiers flags, SourcePosn posn); static void checkInterfaceModifiers(Common::Modifiers flags, SourcePosn posn); static void checkNestedTypeModifiers(Common::Modifiers flags, SourcePosn posn); static void checkLocalTypeModifiers(Common::Modifiers flags, SourcePosn posn); static const string *isTitaniumTypeName(TypeNode *t); static TypeNode *buildTemplateInstanceType(TreeNode *tn, llist *args); static TreeNode *buildTemplateQualifiedName(TypeNode *tmpl, TreeNode *name); static TreeNode *addSynchronized(Common::Modifiers modifiers, TreeNode *body); %} %union { SimpTerminalInfo SimpTerminal; /* Terminal symbols with only position. */ TerminalInfo Terminal; /* Terminal symbols with ASCII string data. */ StrTerminalInfo StrTerminal; /* Terminal symbols with Unicode string data. */ CharTerminalInfo CharTerminal; /* Terminal symbols with Unicode char data. */ long Int; /* Simple integer values */ bool Bool; CompileUnitNode* CompileUnit; TreeNode* Tree; TypeNode* Type; CatchNode* Catch; llist* TreeList; llist* TypeList; llist* CatchList; Common::Modifiers Modifiers; llist* DeclaratorList; TryNode *Try; TypeDeclNode *TypeDecl; } %type CompilationUnit %type Dims DimsOpt %type ArrayName FullArrayName %type Literal PrimaryExpression NotJustName ComplexPrimary %type QualifiedAllocationStart %type ArrayAccess IndexExpression MethodCall AllocationExpression %type PostfixExpression PostIncrement PostDecrement UnaryExpression %type PreIncrement PreDecrement RestrictedUnaryExpression %type CastExpression ExpressionOpt Expression Expression1 Assignment %type ConstantExpression DimExpr StatementExpression %type VariableInitializer ArrayInitializer Element RegionOpt %type NoNamePostfixExpression NoNameUnaryExpression %type OtherPostfixExpression %type NoNameRestrictedUnaryExpression NoNameExpression1 %type OtherUnaryExpression %type BinaryExpression1 %type OtherRestrictedPostfixExpression %type ArgumentListOpt ArgumentList %type DimExprs ElementInitializers %type FieldAccessStart %type FieldAccess %type QualifiedBaseType BaseType %type TypeName %type Type Void %type NoNameType %type OtherType %type PrimitiveType %type SuperOpt ArraySpecifier %type ArraySpecifiers %type TemplateIntro %type TemplateDeclaration %type TemplateInstance TemplateQualifierStart %type TemplateQualifiedName %type TemplateFormalList %type TemplateFormal %type TemplateActual TemplateActual1 TemplateActual2 TemplateActual3 %type TemplateActualList TemplateActualList1 TemplateActualList2 TemplateActualList3 %type TypeNameList InterfacesOpt ThrowsOpt Throws %type ExtendsInterfacesOpt ExtendsInterfaces %type Block Statement %type EmptyStatement LabeledStatement AssertStatement %type SelectionStatement IterationStatement JumpStatement %type GuardingStatement MethodBody Finally %type ConstructorCallStatement ExplicitThisConstructorCallStatement %type ExplicitSuperConstructorCallStatement ExpressionStatement %type LocalClassDeclarationStatement %type BlockStatementsOpt BlockStatements BlockStatement SwitchBlock %type LocalVariableDeclarationStatement %type SwitchBlockStatementsOpt %type ForInit ForUpdateOpt %type StatementExpressionsOpt %type StatementExpressions %type ClassModifiersOpt ClassModifiers ClassModifier %type FieldModifiersOpt FieldModifiers FieldModifier %type QualifiersOpt Qualifier %type ClassDeclaration %type InterfaceDeclaration %type BasicTypeDeclaration %type TypeDeclaration %type ImportStatement TypeImportStatement %type TypeImportOnDemandStatement TypeDefStatement %type Parameter %type MethodDeclaration StaticInitializer InstanceInitializer ConstructorDeclaration NestedTypeDeclaration NestedClassDeclaration NestedInterfaceDeclaration %type MethodSignatureDeclaration %type ClassBody FieldDeclarationsOpt FieldDeclarations %type FieldDeclaration FieldVariableDeclaration %type ConstantFieldDeclaration %type TypeDeclarationsOpt %type ParameterListOpt ParameterList InterfaceBody %type ImportStatementsOpt %type InterfaceMemberDeclaration InterfaceMemberDeclarationsOpt %type SwitchLabel %type SwitchLabels %type SimpleName MethodName OperatorName LabelOpt %type PackageDeclarationOpt Name QualifiedNameStart QualifiedName QualifiedSuperStart %type Catch %type Catches %type TryBlock %type VariableDeclarator VariableDeclarators /* Titanium */ %type PartitionStatement ForEachStatement %type PointLiteral DomainLiteral BroadcastExpression %type ForEachClauses PartitionClauses %type DomainPairs DomainTriples OverlapsOpt %type DomainPair DomainTriple OverlapDecl %type OptionalInline OptionalFinal %start Start %glr-parser %expect 2 %% /* The following production passes the translated program to the later */ /* stages of the compiler for processing. */ Start : CompilationUnit { compileAST ($1); } ; /* 1.7 LITERALS */ Literal : INT_LITERAL { $$ = new PrimitiveLitNode (intLiteral(*$1.val), $1.posn); } | LONG_LITERAL { $$ = new PrimitiveLitNode (longLiteral(*$1.val), $1.posn); } | FLOAT_LITERAL { $$ = new PrimitiveLitNode (floatLiteral(*$1.val), $1.posn); } | DOUBLE_LITERAL { $$ = new PrimitiveLitNode (doubleLiteral(*$1.val), $1.posn); } | TRUE_LITERAL { $$ = new PrimitiveLitNode (Literal(true), $1.posn); } | FALSE_LITERAL { $$ = new PrimitiveLitNode (Literal(false), $1.posn); } | CHARACTER_LITERAL { $$ = new PrimitiveLitNode (Literal($1.val), $1.posn); } | STRING_LITERAL { $$ = new StringLitNode (*$1.val, $1.posn); } ; /* 2. TYPES AND VALUES */ Type : ArrayName %prec ')' { $$ = $1->asType(); } | OtherType ; NoNameType : OtherType ; OtherType : PrimitiveType QualifiersOpt { $$ = $1; $1->modifiers($2); } | PrimitiveType QualifiersOpt ArraySpecifiers { $1->modifiers($2); $$ = arraySpecifiers2Type($3, $1); } | TemplateInstance QualifiersOpt { $$ = $1; $1->modifiers($2); } | TemplateInstance QualifiersOpt ArraySpecifiers { $1->modifiers($2); $$ = arraySpecifiers2Type($3, $1); } ; QualifiedBaseType : BaseType QualifiersOpt { $$ = $1; $$->modifiers($2); } ; BaseType : PrimitiveType | TypeName | TemplateInstance ; TypeName : Name %prec ')' { $$ = new TypeNameNode ($1); } | TemplateQualifiedName { $$ = new TypeNameNode ($1); } ; TemplateQualifierStart : TemplateInstance '.' { $$ = $1; } ; TemplateQualifiedName : TemplateQualifierStart Name { $$ = buildTemplateQualifiedName($1, $2); } ; ArraySpecifiers : ArraySpecifier { $$ = cons($1); } | ArraySpecifier ArraySpecifiers { $$ = cons($1, $2); } ; ArraySpecifier : '[' ']' QualifiersOpt { $$ = new EmptyArrayNode($3, $1.posn); } | '[' IndexExpression ']' QualifiersOpt { $$ = new ExpressionArrayNode($2, $4); } | '[' Expression IDENTIFIER ']' QualifiersOpt { if (*$3.val != "d") { Error($3.posn) << "Unexpected identifier '" << *$3.val << "'" << endl; $$ = new ExpressionArrayNode($2, $5); } else $$ = new TitaniumArrayNode($2, $5); } ; QualifiersOpt : /* empty */ { $$ = (Common::Modifiers)0; } | QualifiersOpt Qualifier { $$ = (Common::Modifiers) ($1 | $2); if (($1 & $2) != 0) Error (lexerPosition()) << "repeated modifier" << endl; } ; Qualifier : SINGLE { $$ = TreeNode::Single; } | LOCAL { $$ = TreeNode::Local; } | NONSHARED { $$ = TreeNode::NonsharedQ; } | POLYSHARED { $$ = TreeNode::PolysharedQ; } ; PrimitiveType : BOOLEAN { $$ = new BoolTypeNode ($1.posn); } | CHAR { $$ = new CharTypeNode ($1.posn); } | BYTE { $$ = new ByteTypeNode ($1.posn); } | SHORT { $$ = new ShortTypeNode ($1.posn); } | INT { $$ = new IntTypeNode ($1.posn); } | FLOAT { $$ = new FloatTypeNode ($1.posn); } | LONG { $$ = new LongTypeNode ($1.posn); } | DOUBLE { $$ = new DoubleTypeNode ($1.posn); } ; /* 5. PROGRAM STRUCTURE */ /* Section 5.4 */ CompilationUnit : PackageDeclarationOpt ImportStatementsOpt TypeDeclarationsOpt { llist *types = $3; SourcePosn pos = lexerPosition(); pos.posn = 0; $$ = new CompileUnitNode (NULL, $1, $2, new TreeListNode (types), NULL, pos); } ; PackageDeclarationOpt : _PACKAGE Name ';' { $$ = $2; } | /* empty */ { $$ = TreeNode::omitted; } ; ImportStatementsOpt : /* empty */ { $$ = NULL; } | ImportStatementsOpt ImportStatement { $$ = extend ($1, cons($2)); } ; /* Note: This definition appears to be missing from the 10/30/95 draft. */ TypeDeclarationsOpt : /* empty */ { $$ = NULL; } | TypeDeclaration TypeDeclarationsOpt { if ($1->absent()) $$ = $2; else $$ = cons (static_cast($1), $2); } | ';' TypeDeclarationsOpt { $$ = $2; } ; TypeDeclaration : BasicTypeDeclaration { $$ = $1; } | TemplateDeclaration { $$ = $1; } ; BasicTypeDeclaration : ClassDeclaration { $$ = $1; } | InterfaceDeclaration { $$ = $1; } ; /* Section 5.7 */ ImportStatement : TypeImportStatement | TypeImportOnDemandStatement | TypeDefStatement ; TypeImportStatement : IMPORT Name ';' { $$ = new ImportNode ($2); } ; /* Note: I have combined PackageImportStatement and TypeImportStatement */ /* to avoid syntactic ambiguity. Also, the draft of 10/30/95 appears */ /* to be missing a final ";" in the definition of */ /* PackageImportStatement. */ TypeImportOnDemandStatement : IMPORT Name '.' '*' ';' { $$ = new ImportOnDemandNode ($2); } ; TypeDefStatement : IMPORT Name '=' Name ';' { Error (lexerPosition()) << "typedefs unimplemented, use macro instead" << endl; $$ = new ImportNode($2); } ; /* 6. CLASS AND INTERFACE TYPE DECLARATIONS */ /* Section 6.1 */ ClassDeclaration : ClassModifiersOpt CLASS SimpleName SuperOpt InterfacesOpt ClassBody { $$ = new ClassDeclNode ($1, $3, $4, $5, $6, NULL, TreeNode::omitted, (NameNode *) $3, false, TreeNode::omitted, NULL, 0, $2.posn); } ; /* Section 6.1.1 */ ClassModifiersOpt : ClassModifiers | /* empty */ { $$ = (Common::Modifiers) 0; } ; ClassModifiers : ClassModifier | ClassModifiers ClassModifier { $$ = (Common::Modifiers) ($1 | $2); if (($1 & $2) != 0) Error (lexerPosition()) << "repeated modifier" << endl; } ; ClassModifier : ABSTRACT { $$ = TreeNode::Abstract; } | FINAL { $$ = TreeNode::Final; } | PUBLIC { $$ = TreeNode::Public; } | IMMUTABLE { $$ = TreeNode::Immutable; } | STRICTFP { Warning (lexerPosition(),"strictfp") << "strictfp modifier is currently ignored." << endl; $$ = TreeNode::Strictfp; } ; /* Section 6.1.2 */ SuperOpt : EXTENDS Type { $$ = $2; } | /* empty */ { $$ = TreeNode::omitted; } ; /* Section 6.1.3 */ InterfacesOpt : IMPLEMENTS TypeNameList { $$ = $2; } | /* empty */ { $$ = NULL; } ; /* Section 6.1.4 */ ClassBody : '{' FieldDeclarationsOpt '}' { $$ = cons (TreeNode::omitted, cons (TreeNode::omitted, cons(TreeNode::omitted, $2))); } ; FieldDeclarationsOpt : FieldDeclarations | /* empty */ { $$ = NULL; } ; FieldDeclarations : FieldDeclaration | FieldDeclarations FieldDeclaration { $$ = extend ($1, $2); } ; /* Section 6.2 */ FieldDeclaration : FieldVariableDeclaration | MethodDeclaration { $$ = cons ($1); } | ConstructorDeclaration { $$ = cons ($1); } | StaticInitializer { $$ = cons ($1); } | InstanceInitializer { $$ = cons ($1); } | NestedTypeDeclaration { $$ = cons ($1); } | ';' { $$ = NULL; } ; /* Section 8.5 (J2SE) */ NestedTypeDeclaration : NestedClassDeclaration { $$ = $1; } | NestedInterfaceDeclaration { $$ = $1; } ; NestedClassDeclaration : FieldModifiersOpt CLASS SimpleName SuperOpt InterfacesOpt ClassBody { checkNestedTypeModifiers($1, $2.posn); $$ = static_cast(new ClassDeclNode ($1, $3, $4, $5, $6, NULL, TreeNode::omitted, (NameNode *) $3, false, TreeNode::omitted, NULL, 0, $2.posn)); } ; NestedInterfaceDeclaration : FieldModifiersOpt INTERFACE SimpleName ExtendsInterfacesOpt InterfaceBody { checkNestedTypeModifiers($1, $2.posn); $$ = static_cast(new InterfaceDeclNode ($1, $3, $4, $5, NULL, (NameNode *) $3, false, $2.posn)); } ; /* Section 6.3 */ FieldVariableDeclaration : FieldModifiersOpt Type VariableDeclarators ';' { checkFieldModifiers ($1, $2->position()); $$ = NULL; foreach (decl, llist, *$3) { $$ = cons (static_cast(new FieldDeclNode(makeArrayType($2, (*decl).dims), (*decl).name, $1, (*decl).initExpr)), $$); } free_all ($3); } ; /* Section 6.3.1, 6.4.1, 6.5.1 */ /* Note: The nonterminals ConstructorModifier, MethodModifier, and */ /* VariableModifer are consolidated here into FieldModifier to */ /* resolve the LALR(1) conflicts. Must be distinguished in later */ /* sections of the compiler. */ FieldModifiersOpt : FieldModifiers | /* empty */ { $$ = (Common::Modifiers) 0; } ; FieldModifiers : FieldModifier | FieldModifiers FieldModifier { $$ = (Common::Modifiers) ($1 | $2); if (($1 & $2) != 0) Error (lexerPosition()) << "repeated modifier" << endl; } ; FieldModifier : /* Applicable to methods, constructors, and variables (6.[345].1) */ PUBLIC { $$ = TreeNode::Public; } | PROTECTED { $$ = TreeNode::Protected; } | PRIVATE { $$ = TreeNode::Private; } /* Applicable to methods and variables (6.[34].1) */ | STATIC { $$ = TreeNode::Static; } | FINAL { $$ = TreeNode::Final; } | SINGLE /* Titanium - obsolete */ { $$ = TreeNode::Sglobal; } | SGLOBAL /* Titanium */ { $$ = TreeNode::Sglobal; } /* Applicable to methods (6.4.1) */ | ABSTRACT { $$ = TreeNode::Abstract; } | NATIVE { $$ = TreeNode::Native; } | SYNCHRONIZED { $$ = TreeNode::Synchronized; } /* Applicable to variables (6.3.1) */ | TRANSIENT { $$ = TreeNode::Transient; } | STRICTFP { Warning (lexerPosition(),"strictfp") << "strictfp modifier is currently ignored." << endl; $$ = TreeNode::Strictfp; } | VOLATILE { $$ = TreeNode::Volatile; } | LOCAL { $$ = TreeNode::Local; } | NONSHARED { $$ = TreeNode::NonsharedQ; } | POLYSHARED { $$ = TreeNode::PolysharedQ; } | INLINE { $$ = TreeNode::Inline; } /* Applicable to nested classes */ | IMMUTABLE { $$ = TreeNode::Immutable; } ; /* Section 6.3.2 */ /* This is built up backwards */ VariableDeclarators : VariableDeclarator | VariableDeclarators ',' VariableDeclarator { $$ = $3; $3->tail() = $1; } ; VariableDeclarator : SimpleName DimsOpt { $$ = cons(DeclaratorTuple($2, $1, TreeNode::omitted)); } | SimpleName DimsOpt '=' VariableInitializer { $$ = cons(DeclaratorTuple($2, $1, $4)); } ; /* Section 6.3.3 */ VariableInitializer : Expression | ArrayInitializer ; /* Section 6.4 */ MethodDeclaration : FieldModifiersOpt Type MethodName '(' ParameterListOpt ')' DimsOpt ThrowsOpt OverlapsOpt MethodBody { checkMethodModifiers($1, $3->position()); TreeNode *body = addSynchronized($1, $10); $$ = new MethodDeclNode($1, $5, makeArrayType($2, $7), makeArrayType($2, $7), $3, $8, $9, body); } | FieldModifiersOpt Void MethodName '(' ParameterListOpt ')' DimsOpt ThrowsOpt OverlapsOpt MethodBody { checkMethodModifiers($1, $3->position()); TreeNode *body = addSynchronized($1, $10); $$ = new MethodDeclNode($1, $5, makeArrayType($2, $7), makeArrayType($2, $7), $3, $8, $9, body); if ($7) Error($3->position()) << "cannot return array of void" << endl; } ; MethodName : SimpleName | OperatorName ; Void : VOID { $$ = new VoidTypeNode ($1.posn); } ; OverlapsOpt : /* empty */ { $$ = NULL; } | OverlapDecl OverlapsOpt { $$ = cons($1, $2); } ; OverlapDecl : OVERLAP '(' SimpleName ',' SimpleName ')' { $$ = new OverlapNode($3, $5, $1.posn); } ; /* Note: "Inlined" ResultType to avoid LALR(1) conflict. */ /* Section 6.4.3 */ ParameterListOpt : ParameterList | /* empty */ { $$ = NULL; } ; ParameterList : Parameter { $$ = cons ($1); } | Parameter ',' ParameterList { $$ = cons ($1, $3); } ; Parameter : OptionalFinal Type SimpleName DimsOpt { $$ = new ParameterNode ($1, makeArrayType ($2, $4), $3); } ; OptionalFinal : FINAL { $$ = true; } | /* empty */ { $$ = false; } ; /* Section 6.4.4 */ ThrowsOpt : Throws | /* empty */ { $$ = NULL; } ; Throws : THROWS TypeNameList { $$ = $2; } ; TypeNameList : Type { $$ = cons ($1); } | Type ',' TypeNameList { $$ = cons ($1, $3); } ; /* Section 6.4.5 */ MethodBody : Block | ';' { $$ = TreeNode::omitted; } ; /* Section 6.5 */ ConstructorDeclaration : FieldModifiersOpt SimpleName '(' ParameterListOpt ')' ThrowsOpt '{' ConstructorCallStatement BlockStatementsOpt '}' { checkConstructorModifiers ($1, $2->position()); $$ = new ConstructorDeclNode ($1, $4, $2, $6, $8, new BlockNode ($9, NULL, $10.posn), TreeNode::omitted); } | FieldModifiersOpt SimpleName '(' ParameterListOpt ')' ThrowsOpt '{' BlockStatementsOpt '}' { checkConstructorModifiers ($1, $2->position ()); $$ = new ConstructorDeclNode ($1, $4, $2, $6, new SuperConstructorCallNode (Common::CompilerGenerated, TreeNode::omitted, NULL, NULL, $2->position()), new BlockNode ($8, NULL, $9.posn), TreeNode::omitted); } ; /* Note: We use FieldModifiersOpt to avoid a LALR(1) conflict. */ /* Section 6.5.4 */ ConstructorCallStatement : ExplicitThisConstructorCallStatement | ExplicitSuperConstructorCallStatement ; ExplicitThisConstructorCallStatement : THIS '(' ArgumentListOpt ')' ';' { $$ = new ThisConstructorCallNode ($3, NULL, false, $1.posn); } ; ExplicitSuperConstructorCallStatement : SUPER '(' ArgumentListOpt ')' ';' { $$ = new SuperConstructorCallNode (Common::None, TreeNode::omitted, $3, NULL, $1.posn); } | QualifiedSuperStart '(' ArgumentListOpt ')' ';' { $$ = new SuperConstructorCallNode (Common::None, new ObjectNode($1, $1->position()), $3, NULL, $2.posn); } | FieldAccessStart SUPER '(' ArgumentListOpt ')' ';' { $$ = new SuperConstructorCallNode (Common::None, $1, $4, NULL, $2.posn); } ; /* Section 6.7.2 */ StaticInitializer : STATIC Block { $$ = new StaticInitNode ($2); } ; InstanceInitializer : Block { $$ = new InstanceInitNode ($1); } ; /* Section 6.8 */ InterfaceDeclaration : ClassModifiersOpt INTERFACE SimpleName ExtendsInterfacesOpt InterfaceBody { checkInterfaceModifiers($1, $2.posn); $$ = new InterfaceDeclNode ($1, $3, $4, $5, NULL, (NameNode *) $3, false); } ; /* Section 6.8.2 */ ExtendsInterfacesOpt : ExtendsInterfaces | /* empty */ { $$ = NULL; } ; ExtendsInterfaces : EXTENDS TypeNameList { $$ = $2; } ; /* Section 6.8.3 */ InterfaceBody : '{' InterfaceMemberDeclarationsOpt '}' { $$ = cons(TreeNode::omitted, cons(TreeNode::omitted, $2)); } ; InterfaceMemberDeclarationsOpt : /* empty */ { $$ = NULL; } | InterfaceMemberDeclaration InterfaceMemberDeclarationsOpt { $$ = extend ($1, $2); } ; InterfaceMemberDeclaration : ConstantFieldDeclaration | MethodSignatureDeclaration { $$ = cons ($1); } | NestedTypeDeclaration { $$ = cons ($1); } | ';' { $$ = NULL; } ; ConstantFieldDeclaration : FieldModifiersOpt Type VariableDeclarators ';' { checkConstantFieldModifiers ($1, $2->position()); $$ = NULL; foreach (decl, llist, *$3) { $$ = cons (static_cast(new FieldDeclNode (makeArrayType ($2, (*decl).dims), (*decl).name, $1, (*decl).initExpr)), $$); } free_all ($3); } ; MethodSignatureDeclaration : FieldModifiersOpt Type MethodName '(' ParameterListOpt ')' DimsOpt ThrowsOpt ';' { checkMethodSignatureModifiers ($1, $2->position()); $$ = new MethodSignatureNode ($1, $5, makeArrayType ($2, $7), makeArrayType ($2, $7), $3, $8); } | FieldModifiersOpt Void MethodName '(' ParameterListOpt ')' DimsOpt ThrowsOpt ';' { checkMethodSignatureModifiers ($1, $2->position()); $$ = new MethodSignatureNode ($1, $5, makeArrayType ($2, $7), makeArrayType ($2, $7), $3, $8); } ; /* Titanium extension: templates */ TemplateIntro : TEMPLATE | '@' ; TemplateDeclaration : TemplateIntro '<' TemplateFormalList '>' BasicTypeDeclaration { $$ = new TemplateDeclNode( $5, $3, 0 ); } ; TemplateFormalList : TemplateFormal { $$ = cons( $1 ); } | TemplateFormal ',' TemplateFormalList { $$ = cons( $1, $3 ); } ; TemplateFormal : CLASS SimpleName { $$ = new TemplateTypeParamNode( $2 ); } | Type SimpleName { $$ = new TemplateConstParamNode( $1, $2 ); } ; TemplateInstance : Name '<' TemplateActualList1 { $$ = buildTemplateInstanceType($1, $3); } /* Deprecated old syntax */ | TemplateIntro Name '<' TemplateActualList1 { $$ = buildTemplateInstanceType($2, $4); } ; TemplateActualList : TemplateActual { $$ = cons( $1 ); } | TemplateActualList ',' TemplateActual { $$ = extend( $1, cons($3) ); } ; TemplateActualList1 : TemplateActual1 { $$ = cons( $1 ); } | TemplateActualList ',' TemplateActual1 { $$ = extend( $1, cons($3) ); } ; TemplateActual1 : TemplateActual '>' { $$ = $1; } | Name '<' TemplateActualList2 { $$ = buildTemplateInstanceType($1, $3); } /* Deprecated old syntax */ | TemplateIntro Name '<' TemplateActualList2 { $$ = buildTemplateInstanceType($2, $4); } ; TemplateActualList2 : TemplateActual2 { $$ = cons( $1 ); } | TemplateActualList ',' TemplateActual2 { $$ = extend( $1, cons($3) ); } ; TemplateActual2 : TemplateActual ASHIFTR { $$ = $1; } | Name '<' TemplateActualList3 { $$ = buildTemplateInstanceType($1, $3); } /* Deprecated old syntax */ | TemplateIntro Name '<' TemplateActualList3 { $$ = buildTemplateInstanceType($2, $4); } ; TemplateActualList3 : TemplateActual3 { $$ = cons( $1 ); } | TemplateActualList ',' TemplateActual3 { $$ = extend( $1, cons($3) ); } ; TemplateActual3 : TemplateActual LSHIFTR { $$ = $1; } ; TemplateActual : NoNameType { $$ = $1; } | NoNameExpression1 { $$ = $1; } | ArrayName { $$ = $1; } ; /* ARRAYS */ /* Section 7.3 */ ArrayInitializer : '{' ElementInitializers '}' { $$ = new ArrayInitNode (dreverse ($2), $1.posn); } | '{' ElementInitializers ',' '}' { $$ = new ArrayInitNode (dreverse ($2), $1.posn); } | '{' '}' { $$ = new ArrayInitNode (NULL, $1.posn); } ; /* Note: I'm going to assume that they didn't intend to allow "{,}". Indeed. (checked with respect to Sun's javac) */ ElementInitializers : Element { $$ = cons ($1); } | ElementInitializers ',' Element { $$ = cons ($3, $1); } ; Element : Expression | ArrayInitializer ; /* BLOCKS AND STATEMENTS */ /* Section 8.1 */ Block : '{' BlockStatementsOpt '}' { $$ = new BlockNode ($2, NULL, $3.posn); } ; BlockStatementsOpt : BlockStatements | /* empty */ { $$ = NULL; } ; BlockStatements : BlockStatement { $$ = $1; } | BlockStatements BlockStatement { $$ = extend ($1, $2); } ; BlockStatement : LocalVariableDeclarationStatement { $$ = $1; } | Statement { $$ = cons ($1); } | LocalClassDeclarationStatement { $$ = cons ($1); } ; /* Section 14.3 (J2SE) */ LocalClassDeclarationStatement : ClassModifiersOpt CLASS SimpleName SuperOpt InterfacesOpt ClassBody { checkLocalTypeModifiers($1, $2.posn); $$ = new ClassDeclNode ($1, $3, $4, $5, $6, NULL, TreeNode::omitted, (NameNode *) $3, false, TreeNode::omitted, NULL, 0, $2.posn); } ; /* Section 8.2 */ /* Not LALR(1) if we use OptionalFinal */ LocalVariableDeclarationStatement : FINAL Type VariableDeclarators ';' { $$ = makeVarDeclNodes(true, $2, $3); } | Type VariableDeclarators ';' { $$ = makeVarDeclNodes(false, $1, $2); } ; /* Section 8.3 */ Statement : EmptyStatement | AssertStatement | LabeledStatement | ExpressionStatement | SelectionStatement | IterationStatement | JumpStatement | GuardingStatement | Block | PartitionStatement /* Titanium */ ; /* Section 8.4 */ EmptyStatement : ';' { $$ = new EmptyStmtNode ($1.posn); } ; AssertStatement : ASSERT Expression ';' { /* Java spec says a missing Expr2 produces an empty message, but that sucks - so add a default message that's actually useful */ string msg = string(" at ") + $1.posn.asString() + ": " + pseudocode($2); $$ = new AssertNode ( $2, new StringLitNode ( string16( convertString((char*)msg.c_str(), msg.length(), $1.posn) ), $1.posn) ); } | ASSERT Expression ':' Expression ';' { $$ = new AssertNode ( $2, $4 ); } ; /* Section 8.5 */ LabeledStatement : SimpleName ':' Statement { $$ = new LabeledStmtNode ($1, $3); } ; /* Section 8.6 */ ExpressionStatement : StatementExpression ';' { $$ = new ExpressionStmtNode( $1 ); } ; StatementExpression : Assignment { $$ = $1; } | PreIncrement { $$ = $1; } | PreDecrement { $$ = $1; } | PostIncrement { $$ = $1; } | PostDecrement { $$ = $1; } | MethodCall { $$ = $1; } | AllocationExpression { $$ = $1; } ; /* Section 8.7 */ SelectionStatement : IF '(' Expression ')' Statement %prec ELSE { $$ = new IfStmtNode ($3, $5, TreeNode::omitted); } | IF '(' Expression ')' Statement ELSE Statement { $$ = new IfStmtNode ($3, $5, $7); } | SWITCH '(' Expression ')' SwitchBlock { $$ = new SwitchNode ($3, $5, $1.posn); } ; SwitchBlock : '{' SwitchBlockStatementsOpt '}' { $$ = $2; } ; SwitchBlockStatementsOpt : /* empty */ { $$ = NULL; } | SwitchLabels BlockStatements SwitchBlockStatementsOpt { $$ = cons (static_cast(new SwitchBranchNode ($1, $2)), $3); } | SwitchLabels { $$ = cons (static_cast(new SwitchBranchNode ($1, cons (static_cast(new EmptyStmtNode ()))))); } ; SwitchLabels : SwitchLabel { $$ = cons ($1); } | SwitchLabel SwitchLabels { $$ = cons ($1, $2); } ; SwitchLabel : CASE ConstantExpression ':' { $$ = new CaseNode ($2, $1.posn); } | DEFAULT ':' { $$ = new CaseNode (TreeNode::omitted, $1.posn); } ; /* Section 8.8 */ IterationStatement : WHILE '(' Expression ')' Statement { $$ = new WhileNode ($3, $5); } | DO Statement WHILE '(' Expression ')' ';' { $$ = new DoNode ($2, $5); } | FOR '(' ForInit ExpressionOpt ';' ForUpdateOpt ')' Statement { $$ = new ForNode ($3, $4, $6, $8); } | ForEachStatement /* Titanium */ ; ForInit : StatementExpressionsOpt ';' { $$ = $1; } | LocalVariableDeclarationStatement { $$ = $1; } ; ForUpdateOpt : StatementExpressions | /* empty */ { $$ = NULL; } ; StatementExpressionsOpt : StatementExpressions | /* empty */ { $$ = NULL; } ; StatementExpressions : StatementExpression { $$ = cons (static_cast(new ExpressionStmtNode($1))); } | StatementExpression ',' StatementExpressions { $$ = cons (static_cast(new ExpressionStmtNode($1)), $3); } ; /* Titanium */ ForEachStatement : FOREACH '(' ForEachClauses ')' OptionalInline Statement { $$ = new ForEachStmtNode ($3, $6, $5, $1.posn); } ; OptionalInline : INLINE { $$ = true; } | /* empty */ { $$ = false; } ; ForEachClauses : SimpleName SpecialIn Expression { $$ = cons(static_cast(new ForEachPairNode($1, $3, TreeNode::omitted, $1->position()))); } | TemplateInstance SimpleName SpecialIn Expression { TreeNode *pttype = $1; if (!((TypeNode*)pttype)->isPointType()) { Error(pttype->position()) << "optional point type declaration in a foreach must be Point" << endl; pttype = TreeNode::omitted; } $$ = cons(static_cast(new ForEachPairNode($2, $4, pttype, $1->position()))); } /* DOB: what is this? this mysterious and undocumented syntax appears to be non-functional at code generation time, so I'm removing it in tc 2.473 | SimpleName SpecialIn Expression ',' ForEachClauses { $$ = cons(static_cast(new ForEachPairNode($1, $3)), $5); } */ ; SpecialIn : IDENTIFIER { if (*$1.val == "within") Warning(lexerPosition(),"deprecated-foreach-within") << "deprecated use of 'within' in foreach - expected 'in'" << endl; else if (*$1.val != "in") Error(lexerPosition()) << "bad keyword in foreach - expected 'in'" << endl; } ; /* Section 8.9 */ JumpStatement : BREAK LabelOpt ';' { $$ = new BreakNode ($2, NULL, NULL, $1.posn); } | CONTINUE LabelOpt ';' { $$ = new ContinueNode ($2, NULL, NULL, $1.posn); } | RETURN ExpressionOpt ';' { $$ = new ReturnNode ($2, NULL, $1.posn); } | THROW Expression ';' { $$ = new ThrowNode ($2, $1.posn); } ; LabelOpt : SimpleName | /* empty */ { $$ = TreeNode::omitted; } ; /* Section 8.10 */ GuardingStatement : SYNCHRONIZED '(' Expression ')' Statement { $$ = new SynchronizedNode ($3, $5); } | TryBlock Finally { $$ = new TryStmtNode ($1, NULL, $2); } | TryBlock Catches { $$ = new TryStmtNode ($1, $2, TreeNode::omitted); } | TryBlock Catches Finally { $$ = new TryStmtNode ($1, $2, $3); } ; TryBlock : TRY Block { $$ = new TryNode ($2); } ; Catches : Catch { $$ = cons ($1); } | Catch Catches { $$ = cons ($1, $2); } ; Catch : CATCH '(' Parameter ')' Block { $$ = new CatchNode ($3, $5, $1.posn); } ; Finally : FINALLY Block { $$ = new FinallyNode( $2 ); } ; /* Titanium */ PartitionStatement : PARTITION '{' PartitionClauses '}' { $$ = new PartitionStmtNode(TreeNode::omitted, $3, $1.posn); } | PARTITION SimpleName '{' PartitionClauses '}' { $$ = new PartitionStmtNode($2, $4, $1.posn); } ; PartitionClauses: /* empty */ { $$ = NULL; } | Expression GUARDS Statement PartitionClauses { $$ = cons(static_cast(new PartitionClauseNode($1, $3)), $4); } ; /* EXPRESSIONS */ /* Section 9.4 */ PrimaryExpression : ArrayName %prec ')' { $$ = $1->asExpr(); } | NotJustName ; NotJustName : AllocationExpression | ComplexPrimary ; ComplexPrimary : Literal | NULL_VAL { $$ = new NullPntrNode ($1.posn); } | THIS { $$ = new ThisNode (TreeNode::omitted, NULL, Common::None, $1.posn); } | QualifiedNameStart THIS { $$ = new ThisNode (new TypeNameNode($1), NULL, Common::None, $2.posn); } | TemplateQualifiedName '.' THIS { $$ = new ThisNode (new TypeNameNode($1), NULL, Common::None, $3.posn); } | TemplateInstance '.' THIS { $$ = new ThisNode ($1, NULL, Common::None, $3.posn); } | '(' Expression ')' { $$ = $2; } | '(' ArrayName ')' { $$ = $2->asExpr(); } | ArrayAccess | FieldAccess { $$ = $1; } | MethodCall | PrimitiveType '.' CLASS /* shift/reduce conflict that should always be shift */ { string s = "java.lang."; switch ($1->signature()[0]) { case 'Z': s += "Boolean"; break; case 'C': s += "Character"; break; case 'B': s += "Byte"; break; case 'S': s += "Short"; break; case 'I': s += "Integer"; break; case 'J': s += "Long"; break; case 'F': s += "Float"; break; case 'D': s += "Double"; break; default: abort(); } $$ = new TypeFieldAccessNode ( new TypeNameNode(buildName(s.c_str(), $2.posn)), buildName("TYPE", $2.posn), $2.posn); } | VOID '.' CLASS { $$ = new TypeFieldAccessNode ( new TypeNameNode(buildName("java.lang.Void", $2.posn)), buildName("TYPE", $2.posn), $2.posn); } ; /* Note: The third production above is redundant, but helps resolve a LALR(1) */ /* lookahead conflict arising in cases like "(T) + x" (Do we reduce Name */ /* T to ClassOrInterfaceType on seeing the ")"?). See also CastExpression */ /* in section 9.10. */ ArrayName : Name QualifiersOpt { $$ = new ArrayNameNode($1, $2, NULL); } | TemplateQualifiedName QualifiersOpt { $$ = new ArrayNameNode($1, $2, NULL); } | FullArrayName ; FullArrayName : Name QualifiersOpt ArraySpecifiers { $$ = new ArrayNameNode($1, $2, $3); } | TemplateQualifiedName QualifiersOpt ArraySpecifiers { $$ = new ArrayNameNode($1, $2, $3); } ; Name : SimpleName | QualifiedName ; SimpleName : IDENTIFIER { $$ = new NameNode (TreeNode::omitted, $1.val, NULL, $1.posn); } ; /* To prevent LALR(1) ambiguity (used by qualified allocations) */ QualifiedNameStart : Name '.' { $$ = $1; } ; QualifiedName : QualifiedNameStart IDENTIFIER { $$ = new NameNode ($1, $2.val, NULL, $2.posn); } /* class literals handled as a static field access */ | QualifiedNameStart CLASS { $$ = new NameNode ($1, intern("class"), NULL, $2.posn); } | QualifiedNameStart OperatorName { $$ = new NameNode ($1, $2->ident(), NULL, $2->position()); } ; OperatorName : OPERATOR '!' { $$ = newOperator("!", $2.posn); } | OPERATOR '~' { $$ = newOperator("~", $2.posn); } | OPERATOR '<' { $$ = newOperator("<", $2.posn); } | OPERATOR '>' { $$ = newOperator(">", $2.posn); } | OPERATOR LE { $$ = newOperator("<=", $2.posn); } | OPERATOR GE { $$ = newOperator(">=", $2.posn); } | OPERATOR EQ { $$ = newOperator("==", $2.posn); } | OPERATOR NE { $$ = newOperator("!=", $2.posn); } | OPERATOR '+' { $$ = newOperator("+", $2.posn); } | OPERATOR '-' { $$ = newOperator("-", $2.posn); } | OPERATOR '*' { $$ = newOperator("*", $2.posn); } | OPERATOR '/' { $$ = newOperator("/", $2.posn); } | OPERATOR '&' { $$ = newOperator("&", $2.posn); } | OPERATOR '|' { $$ = newOperator("|", $2.posn); } | OPERATOR '^' { $$ = newOperator("^", $2.posn); } | OPERATOR '%' { $$ = newOperator("%", $2.posn); } | OPERATOR LSHIFTL { $$ = newOperator("<<", $2.posn); } | OPERATOR ASHIFTR { $$ = newOperator(">>", $2.posn); } | OPERATOR LSHIFTR { $$ = newOperator(">>>", $2.posn); } | OPERATOR PLUS_ASG { $$ = newOperator("+=", $2.posn); } | OPERATOR MINUS_ASG { $$ = newOperator("-=", $2.posn); } | OPERATOR MULT_ASG { $$ = newOperator("*=", $2.posn); } | OPERATOR DIV_ASG { $$ = newOperator("/=", $2.posn); } | OPERATOR REM_ASG { $$ = newOperator("%=", $2.posn); } | OPERATOR LSHIFTL_ASG { $$ = newOperator("<<=", $2.posn); } | OPERATOR ASHIFTR_ASG { $$ = newOperator(">>=", $2.posn); } | OPERATOR LSHIFTR_ASG { $$ = newOperator(">>>=", $2.posn); } | OPERATOR AND_ASG { $$ = newOperator("&=", $2.posn); } | OPERATOR XOR_ASG { $$ = newOperator("^=", $2.posn); } | OPERATOR OR_ASG { $$ = newOperator("|=", $2.posn); } | OPERATOR '[' ']' { $$ = newOperator("[]", $2.posn); } | OPERATOR '[' ']' '=' { $$ = newOperator("[]=", $2.posn); } ; /* Section 9.5 */ ArrayAccess : ComplexPrimary '[' IndexExpression ']' { $$ = new ArrayAccessNode ($1, $3); } ; IndexExpression : /* titanium - implicit point creation */ ArgumentList { $$ = new PointNode($1); } ; /* Section 9.6 */ /* In order to keep grammar LALR(1) (needed by field accesses and qualified * allocations. */ FieldAccessStart : NotJustName '.' { $$ = $1; } ; QualifiedSuperStart : QualifiedNameStart SUPER { $$ = $1; } | TemplateQualifiedName '.' SUPER { $$ = $1; } ; FieldAccess : /* The following never matches Name '.' IDENTIFIER */ FieldAccessStart MethodName { $$ = new ObjectFieldAccessNode ($1, $2); } | SUPER '.' MethodName { $$ = new SuperFieldAccessNode (TreeNode::omitted, NULL, Common::None, $3); } | QualifiedSuperStart '.' MethodName { $$ = new SuperFieldAccessNode (new TypeNameNode($1), NULL, Common::None, $3); } | TemplateInstance '.' SUPER '.' MethodName { $$ = new SuperFieldAccessNode ($1, NULL, Common::None, $5); } | FullArrayName '.' MethodName { $$ = new ObjectFieldAccessNode ($1->asExpr(), $3); } /* class literals handled as a static field access */ | TemplateQualifierStart CLASS { $$ = new TypeFieldAccessNode ($1, buildName("class", $2.posn)); } | OperatorName { $$ = new ThisFieldAccessNode (NULL, Common::None, $1); } ; /* Section 9.7 */ MethodCall : FieldAccess '(' ArgumentListOpt ')' { $$ = new MethodCallNode ($1, $3); } | ArrayName '(' ArgumentListOpt ')' { $$ = new MethodCallNode ($1->asExpr(), $3); } ; ArgumentListOpt : ArgumentList | /* empty */ { $$ = NULL; } ; ArgumentList : Expression { $$ = cons ($1); } | Expression ',' ArgumentList { $$ = cons ($1, $3); } ; /* Section 9.8 */ QualifiedAllocationStart : FieldAccessStart NEW { $$ = $1; } | QualifiedNameStart NEW { $$ = new ObjectNode($1, $1->position()); } | TemplateQualifiedName '.' NEW { $$ = new ObjectNode($1, $1->position()); } ; AllocationExpression : NEW RegionOpt QualifiedBaseType DimExprs { $$ = new AllocateArrayNode ($2, $3, $4, TreeNode::omitted); } | NEW RegionOpt QualifiedBaseType DimExprs ArrayInitializer /* Semantics makes sure no size is specified here. */ { $$ = new AllocateArrayNode ($2, $3, $4, $5); } | NEW RegionOpt QualifiedBaseType '(' ArgumentListOpt ')' { $$ = new AllocateNode ($2, $3, $5, NULL, TreeNode::omitted, TreeNode::omitted); } | NEW RegionOpt QualifiedBaseType '(' ArgumentListOpt ')' ClassBody { llist* body = $7; $$ = new AllocateNode ($2, $3, $5, NULL, TreeNode::omitted, new TreeListNode(body, $3->position())); } | QualifiedAllocationStart RegionOpt QualifiedBaseType '(' ArgumentListOpt ')' { $$ = new AllocateNode ($2, $3, $5, NULL, $1, TreeNode::omitted); } | QualifiedAllocationStart RegionOpt QualifiedBaseType '(' ArgumentListOpt ')' ClassBody { llist* body = $7; $$ = new AllocateNode ($2, $3, $5, NULL, $1, new TreeListNode(body, $3->position())); } ; RegionOpt : '(' Expression ')' { $$ = $2; } | /* empty */ { $$ = TreeNode::omitted; } ; DimExprs : DimExpr { $$ = cons ($1); } | DimExpr DimExprs { $$ = cons ($1, $2); } ; DimExpr : ArraySpecifier { $$ = $1; } | DomainLiteral QualifiersOpt { $$ = new AllocateArrayDimensionNode($1, $2); } ; DimsOpt : Dims | /* empty */ { $$ = 0; } ; Dims : '[' ']' { $$ = 1; } | '[' ']' LOCAL { $$ = 1; } | Dims '[' ']' { $$ = $1 + 1; } | Dims '[' ']' LOCAL { $$ = $1 + 1; } ; /* Section 9.9 */ PostfixExpression : PrimaryExpression | OtherPostfixExpression ; NoNamePostfixExpression : NotJustName | OtherPostfixExpression ; OtherPostfixExpression : PostIncrement | PostDecrement ; PostIncrement : PostfixExpression PLUSPLUS { $$ = new PostIncrNode ($1); } ; PostDecrement : PostfixExpression MINUSMINUS { $$ = new PostDecrNode ($1); } ; /* Section 9.10 */ UnaryExpression : RestrictedUnaryExpression | OtherUnaryExpression ; NoNameUnaryExpression : NoNameRestrictedUnaryExpression | OtherUnaryExpression ; OtherUnaryExpression : PreIncrement | PreDecrement | '+' UnaryExpression { $$ = new UnaryPlusNode ($2, $1.posn); } | '-' UnaryExpression { $$ = new UnaryMinusNode ($2, $1.posn); } | PointLiteral /* Titanium */ | DomainLiteral /* Titanium */ | BroadcastExpression ; PreIncrement : PLUSPLUS UnaryExpression { $$ = new PreIncrNode ($2); } ; PreDecrement : MINUSMINUS UnaryExpression { $$ = new PreDecrNode ($2); } ; RestrictedUnaryExpression : PostfixExpression | OtherRestrictedPostfixExpression ; NoNameRestrictedUnaryExpression : NoNamePostfixExpression | OtherRestrictedPostfixExpression ; OtherRestrictedPostfixExpression : '~' UnaryExpression { $$ = new ComplementNode ($2); } | '!' UnaryExpression { $$ = new NotNode ($2); } | CastExpression ; CastExpression : '(' Type ')' UnaryExpression { $$ = new CastNode ($4, $2); } | '(' ArrayName ')' RestrictedUnaryExpression { $$ = new CastNode ($4, $2->asType()); } ; /* Note: The last production is redundant, but helps resolve a LALR(1) */ /* lookahead conflict arising in cases like "(T) + x" (Do we reduce Name */ /* T to ClassOrInterfaceType on seeing the ")"?). See also ComplexPrimary */ /* in section 9.4. */ /* Titanium */ PointLiteral : '[' ArgumentList ']' { $$ = new PointNode($2); } ; DomainLiteral : '[' DomainPairs ']' { $$ = new DomainNode($2); } | '[' DomainTriples ']' { $$ = new DomainNode($2); } ; DomainPairs : DomainPair { $$ = cons($1); } | DomainPair ',' DomainPairs { $$ = cons($1, $3); } ; DomainPair : Expression ':' Expression { llist* children = cons($1, cons($3)); $$ = new TreeListNode(children); } ; DomainTriples : DomainTriple { $$ = cons($1); } | DomainTriple ',' DomainTriples { $$ = cons($1, $3); } ; DomainTriple : Expression ':' Expression ':' Expression { llist* children = cons($1, cons($3, cons($5))); $$ = new TreeListNode(children); } ; /* Sections 9.11 to 9.19 */ ExpressionOpt : Expression | /* empty */ { $$ = TreeNode::omitted; } ; Expression : Expression1 | Expression '<' Expression { $$ = new LTNode ($1, $3); } | Expression '>' Expression { $$ = new GTNode ($1, $3); } | Expression LE Expression { $$ = new LENode ($1, $3); } | Expression GE Expression { $$ = new GENode ($1, $3); } | Expression INSTANCEOF Type { $$ = new InstanceOfNode ($1, $3); } | Expression EQ Expression { $$ = new EQNode ($1, $3); } | Expression NE Expression { $$ = new NENode ($1, $3); } | Expression '&' Expression { $$ = new BitAndNode ($1, $3); } | Expression '|' Expression { $$ = new BitOrNode ($1, $3); } | Expression '^' Expression { $$ = new BitXorNode ($1, $3); } | Expression CAND Expression { $$ = new CandNode ($1, $3); } | Expression COR Expression { $$ = new CorNode ($1, $3); } | Expression '?' Expression ':' Expression { $$ = new IfExprNode ($1, $3, $5); } | Expression LSHIFTL Expression { $$ = new LeftShiftLogNode ($1, $3); } | Expression LSHIFTR Expression { $$ = new RightShiftLogNode ($1, $3); } | Expression ASHIFTR Expression { $$ = new RightShiftArithNode ($1, $3); } | Assignment ; Expression1 : UnaryExpression | BinaryExpression1 ; NoNameExpression1 : NoNameUnaryExpression | BinaryExpression1 ; BinaryExpression1 : Expression1 '*' Expression1 { $$ = new MultNode ($1, $3); } | Expression1 '/' Expression1 { $$ = new DivNode ($1, $3); } | Expression1 '%' Expression1 { $$ = new RemNode ($1, $3); } | Expression1 '+' Expression1 { $$ = new PlusNode ($1, $3); } | Expression1 '-' Expression1 { $$ = new MinusNode ($1, $3); } ; /* Section 9.20 */ Assignment : UnaryExpression '=' Expression { $$ = new AssignNode ($1, $3); } | UnaryExpression MULT_ASG Expression { $$ = new MultAssignNode ($1, $3); } | UnaryExpression DIV_ASG Expression { $$ = new DivAssignNode ($1, $3); } | UnaryExpression REM_ASG Expression { $$ = new RemAssignNode ($1, $3); } | UnaryExpression PLUS_ASG Expression { $$ = new PlusAssignNode ($1, $3); } | UnaryExpression MINUS_ASG Expression { $$ = new MinusAssignNode ($1, $3); } | UnaryExpression LSHIFTL_ASG Expression { $$ = new LeftShiftLogAssignNode ($1, $3); } | UnaryExpression LSHIFTR_ASG Expression { $$ = new RightShiftLogAssignNode ($1, $3); } | UnaryExpression ASHIFTR_ASG Expression { $$ = new RightShiftArithAssignNode ($1, $3); } | UnaryExpression AND_ASG Expression { $$ = new BitAndAssignNode ($1, $3); } | UnaryExpression XOR_ASG Expression { $$ = new BitXorAssignNode ($1, $3); } | UnaryExpression OR_ASG Expression { $$ = new BitOrAssignNode ($1, $3); } ; /* Section 9.22 */ ConstantExpression : Expression ; BroadcastExpression : BROADCAST Expression SpecialFrom UnaryExpression { $$ = new BroadcastNode ($2, $4); } ; SpecialFrom : IDENTIFIER { if (*$1.val != "from") Error(lexerPosition()) << "bad keyword in broadcast - expected 'from'" << endl; } ; /* MISCELLANEOUS */ /* Collected error productions */ ImportStatement : IMPORT error ';' { $$ = TreeNode::omitted; } ; PackageDeclarationOpt : _PACKAGE error ';' { $$ = TreeNode::omitted; } ; NestedTypeDeclaration : error ClassBody { $$ = TreeNode::omitted; } ; ClassBody : '{' error '}' { $$ = cons ( TreeNode::omitted ); } ; Block : '{' error '}' { $$ = TreeNode::omitted; } ; Statement : error ';' { $$ = new EmptyStmtNode; } | error Block { $$ = $2; } ; FieldDeclaration : error ';' { $$ = NULL; } ; TypeDeclaration : error ClassBody { $$ = TreeNode::omitted; } ; %% static void yyerror(const char* msg) { Error(yylval.SimpTerminal.posn) << msg << endl; } static TreeNode *newOperator(char *op, SourcePosn p) { return new NameNode(TreeNode::omitted, intern(op), NULL, p); } /* Check that only the modifiers in ... are in FLAGS, reporting an */ /* error at POSN if not. */ static void checkModifiers(SourcePosn posn, Common::Modifiers flags, ...) { unsigned long flag; va_list ap; va_start (ap, flags); while (true) { flag = va_arg (ap, unsigned long); if (flag == 0) break; flags = (Common::Modifiers)((unsigned long)flags & ~flag); } va_end (ap); if ((unsigned long) flags != 0) Error(posn) << "illegal modifiers: " << stringifyModifiers(flags) << endl; } static void checkFieldModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Protected, TreeNode::Private, TreeNode::Static, TreeNode::Final, TreeNode::Transient, TreeNode::Volatile, (Common::Modifiers) 0); } static void checkConstantFieldModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Static, TreeNode::Final, (Common::Modifiers) 0); } static void checkMethodModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Protected, TreeNode::Private, TreeNode::Static, TreeNode::Final, TreeNode::Abstract, TreeNode::Native, TreeNode::Sglobal, TreeNode::Local, TreeNode::NonsharedQ, TreeNode::PolysharedQ, TreeNode::Synchronized, TreeNode::Inline, TreeNode::Strictfp, (Common::Modifiers) 0); } static void checkConstructorModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Protected, TreeNode::Private, TreeNode::NonsharedQ, TreeNode::PolysharedQ, TreeNode::Sglobal, TreeNode::Inline, (Common::Modifiers) 0); } static void checkMethodSignatureModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Abstract, TreeNode::Sglobal, TreeNode::Local, TreeNode::NonsharedQ, TreeNode::PolysharedQ, (Common::Modifiers) 0); } static void checkInterfaceModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Abstract, TreeNode::Strictfp, (Common::Modifiers) 0); } static void checkNestedTypeModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Public, TreeNode::Protected, TreeNode::Private, TreeNode::Static, TreeNode::Final, TreeNode::Abstract, TreeNode::Immutable, TreeNode::Strictfp, (Common::Modifiers) 0); } static void checkLocalTypeModifiers(Common::Modifiers flags, SourcePosn posn) { checkModifiers(posn, flags, TreeNode::Final, TreeNode::Abstract, TreeNode::Strictfp, (Common::Modifiers) 0); } static const string *isTitaniumTypeName(TypeNode *t) { if (isTypeNameNode(t) && isNameNode(t->name()) && t->name()->qualifier()->absent()) { const string *id = t->name()->ident(); if (*id == "Point" || *id == "RectDomain" || *id == "Domain") return id; } return NULL; } static TypeNode *buildTemplateInstanceType(TreeNode *tn, llist *args) { TypeNode *t = new TypeNameNode(tn); const string *tname = isTitaniumTypeName(t); if (tname) { TreeNode *arg = TreeNode::omitted; if (args->size() != 1) { Error(t->position()) << *tname << " requires exactly one argument" << endl; } else if (args->front()->isTypeNode()) { Error(t->position()) << "Bad argument to " << *tname << endl; } else arg = args->front(); if (isArrayNameNode(arg)) arg = arg->asExpr(); if (*tname == "Point") return new PointTypeNode(arg, t->position()); else if (*tname == "RectDomain") return new RectDomainTypeNode(arg, t->position()); else { assert(*tname == "Domain"); return new DomainTypeNode(arg, t->position()); } } else /* not a Titanium type - a regular template */ return new TemplateInstanceTypeNode( t, args, 0 ); } static TreeNode *buildTemplateQualifiedName(TypeNode *tmpl, TreeNode *name) { if (name->qualifier()->absent()) return new NameNode(new TemplateNameNode(TreeNode::omitted, tmpl, tmpl->position()), name->ident(), NULL, name->position()); else return new NameNode(buildTemplateQualifiedName(tmpl, name->qualifier()), name->ident(), NULL, name->position()); } static TreeNode *addSynchronized(Common::Modifiers modifiers, TreeNode *body) { if ((modifiers & TreeNode::Synchronized) != 0 && !body->absent()) { TreeNode *syncObject; if ((modifiers & TreeNode::Static) != 0) { syncObject = TreeNode::omitted; } else { syncObject = new ThisNode(TreeNode::omitted, NULL, Common::None, body->position()); } body = new SynchronizedNode(syncObject, body); } return body; }