%{ /************************************************ Team: Jon Gregory, Gor Nishanov Project #2 Part 2 for RPI course 66-648 Compiler Design Theory java.y: to do: try finally, static initializer and interfaces */ #include #define YYERROR_VERBOSE 1 #define REPORT(cond,code) #include #include #include #include #include "tree.h" Environment env; int yyerror(char *s); int yylex(); %} %union { int modifier; int opval; Class * clazz; Field * field; Package * pkg; Type * type; Method * method; ExprList * exprs; StmtList * stmts; Expression * expr; Statement * stmt; IdentProxy id; } %token ident %type SimpleName oIdent %type QualifiedName %type Name %type ClassOrInterfaceType ClassType InterfaceType %type Type ReferenceType ArrayType %type MethodDeclarator ConstructorDeclarator %type MethodBody ConstructorBody %type VariableDeclaratorId VariableDeclarator FieldAccess %token _this_ _super_ %type NewClassInstance oArgList Expression ThisOrSuper %type VariableInitializer ArrayInitializer %type StatementExpression Assignment PreIncDec PostIncDec %type MethodInvocation %type ConstantExpression UnaryNotPM CastExpr %type ArgList VariableDeclarators %type oVariableInitializers VariableInitializers %type ExplicitConstructorInvocation %type Block oBlockStatements BlockStatement Statement %type LocalVariableDeclarationStatement %type LocalVariableDeclaration %type StatementNoShortIf %type StatementWithoutTrailingSubstatement %type LabeledStatementNoShortIf %type IfThenElseStatementNoShortIf %type WhileStatementNoShortIf %type ForStatementNoShortIf %type LabeledStatement %type IfThenStatement %type IfThenElseStatement %type WhileStatement %type ForStatement %type ExpressionStatement %type SwitchStatement %type DoStatement %type BreakStatement %type ContinueStatement %type ReturnStatement %type SynchronizedStatement %type ThrowStatement SwitchBlock %type TryStatement EmptyStatement SwitchLabel %type oForInit ForInit ; %type oForUpdate ForUpdate oForExpression %type StatementExpressionList %type BlockStatements %type SwitchLabels SwitchBlockStatementGroups SwitchBlockStatementGroup %type AssignExpression ArrayAccess Postfix AddExpr %type Primary NoNewArray ArrayCreation Unary MulExpr %type ShiftExpr RelExpr EqualExpr AndExpr XorExpr OrExpr %type AndAlso OrElse CondExpr LeftHandSide %type SaveElem /* small kludge */ %token Literal /* IntegerLiteral FloatingPointLiteral BooleanLiteral CharacterLiteral StringLiteral NullLiteral */ %token _new_ _instanceof_ _interface_ %token _if_ _else_ _switch_ _case_ _default_ _while_ %token _do_ _for_ _break_ _continue_ _return_ _throw_ %token _try_ _catch_ _finally_ %token _class_ _extends_ _implements_ _package_ _import_ _throws_ %token _andand_ _oror_ %token PrimitiveType /* bool int ... */ %token _void_ %token IncDec /* ++ -- */ %token MulOp /* * / % */ %token AddOp /* + - */ %token NegNot /* ! ~ */ %token ShiftOp /* << >> >>> */ %token RelOp /* < > <= >= */ %token EqualOp /* == != */ %token AssOp /* = *= /= %= += -= <<= >>= >>>= &= ^= |= */ %token _static_ /* special handling in StaticInitialization */ %token _synchronized_ /* used in sychronized statement */ /* all other modifiers are represented by the token Modifier1 */ %token Modifier1 /* public protected private abstract final native transient volatile */ %type oModifiers Modifiers Modifier %type ClassDeclaration InterfaceDeclaration %type TypeDeclaration TypeDeclarations %type oSuper /* Maybe it's good to allow method declaration in the form int a() {...}; Though, it is not in the syntax. Sun's java compiler eats this without a glitch */ %% Goal3: CompilationUnit; Modifier: _static_ {$$ = $1;} | _synchronized_ {$$ = $1;} | Modifier1 {$$ = $1;} ; oModifiers: {$$ = 0;} | Modifiers {$$ = $1;} ; Modifiers: Modifier {$$ = $1;} | Modifiers Modifier { REPORT( $1 & $2 , ER_REPEATED_MODIFIER); $$ = $1 | $2; } ; /****************** Names ***************************/ Name: SimpleName {$$ = new IdentifierExpression($1); } | QualifiedName {$$ = $1; }; SimpleName: ident ; QualifiedName: Name '.' ident { $$ = new FieldExpression($1,$3); }; /****************** Packages **************************/ CompilationUnit: PackageDeclaration oImportDeclarations oTypeDeclarations oImportDeclarations: ImportDeclarations {} | /* e */ {}; oTypeDeclarations: TypeDeclarations {} | /* e */ {}; ImportDeclarations : ImportDeclaration | ImportDeclarations ImportDeclaration ; TypeDeclaration: ClassDeclaration | InterfaceDeclaration | ';' {$$ = 0;}; TypeDeclarations : TypeDeclaration | TypeDeclarations TypeDeclaration ; PackageDeclaration: _package_ Name ';' {env.pkg = new Package($2); } | /* e */ {env.pkg = new Package(0); }; ImportDeclaration : SingleTypeImportDeclaration | TypeImportOnDemandDeclaration ; SingleTypeImportDeclaration: _import_ Name ';' {env.pkg->imports.add($2) }; TypeImportOnDemandDeclaration: _import_ Name '.' MulOp ';' { assert($4 == MUL); env.pkg->imports.add( new FieldExpression($2, Identifier::star) ); }; /******************* Classes ************************/ ClassDeclaration: oModifiers _class_ ident {env.addNewClass(new Class($3,$1));} oSuper oInterfaces ClassBody {}; oSuper: {env.clazz->super = Type::Object; } | _extends_ ClassType {env.clazz->super = $2;}; oInterfaces: /* e */ {} | _implements_ InterfaceTypeList {}; InterfaceTypeList: InterfaceType {env.clazz->interfaces.add($1); } | InterfaceTypeList ',' InterfaceType {env.clazz->interfaces.add($3); }; ClassBody: '{' oClassBodyDeclarations '}' ; oClassBodyDeclarations: /* e */ | ClassBodyDeclarations; ClassBodyDeclarations: ClassBodyDeclaration | ClassBodyDeclarations ClassBodyDeclaration ; ClassBodyDeclaration: ClassMemberDeclaration | StaticInitializer | ConstructorDeclaration ; ClassMemberDeclaration: FieldDeclaration | MethodDeclaration ; /* 19.8.2 */ FieldDeclaration: oModifiers Type VariableDeclarators ';' { env.clazz->fields.add( new DeclarationStatement($1,new TypeExpression($2), new ExpressionStatement($3->first))); }; /****************** Declaration *********************/ VariableDeclarators: VariableDeclarator { $$ = new ExprList($1); } | VariableDeclarators ',' VariableDeclarator {$$=$1; $$->add($3); } ; VariableDeclarator: VariableDeclaratorId { $$ = $1; } | VariableDeclaratorId AssOp VariableInitializer { assert($2 == ASSIGN); $1 = new BinaryAssignExpression(ASSIGN, $1, $3); }; VariableDeclaratorId: ident { $$ = new IdentifierExpression($1); } | VariableDeclaratorId '[' ']' { $$ = new ArrayAccessExpression($1,0); }; VariableInitializer: Expression {$$ = $1; } | ArrayInitializer {$$ = $1;}; /* 19.8.3 */ MethodDeclaration: MethodHeader MethodBody { env.method->body = $2; }; MethodHeader: oModifiers _void_ MethodDeclarator Throws {env.method->modifiers = $1; env.method->type = $2;} | oModifiers Type MethodDeclarator Throws {env.method->modifiers = $1; env.method->type = $2;} ; MethodDeclarator: ident '(' {env.addMethod( new Method($1) ); } oFormalParameterList ')' | MethodDeclarator '[' ']' {++env.method->dims;}; oFormalParameterList: /* e */ {} | FormalParameterList {}; FormalParameterList: FormalParameter {} | FormalParameterList ',' FormalParameter {}; FormalParameter: Type VariableDeclaratorId { env.method->params.add(new Parameter($2, $1)); }; Throws: /* e */ | _throws_ ClassTypeList ClassTypeList: ClassType {env.method->throwz.add($1); } | ClassTypeList ',' ClassType {env.method->throwz.add($3); }; MethodBody: Block {$$ = $1;} | ';' {$$ = env.empty_block;} ; /* 19.8.4 */ StaticInitializer: _static_ Block {env.clazz->inits.add($2); }; /* 19.8.5 Productions from 8.6: Constructor Declarations */ ConstructorDeclaration: oModifiers ConstructorDeclarator Throws ConstructorBody { env.method -> modifiers = $1; env.method -> type = Type::Void; env.method ->body = $4; }; ConstructorDeclarator: // Later check SimpleName = ClassName SimpleName '(' {env.method = new Method($1); } oFormalParameterList ')'; ConstructorBody: '{' ExplicitConstructorInvocation oBlockStatements '}' { $$ = new CompoundStatement( $2->glue($3) ); } | '{' oBlockStatements '}' { $$ = new CompoundStatement($2); } ; // !! def ctor ThisOrSuper: _this_ | _super_ ; ExplicitConstructorInvocation: ThisOrSuper '(' oArgList ')' ';' { $$ = new ExpressionStatement( new MethodExpression($1, Identifier::init, $3)); }; /* 19.9 Productions from p.9: Interfaces */ InterfaceDeclaration: oModifiers _interface_ ident { env.addNewClass(new Class($3,$1 | ACC_INTERFACE));} ExtendsInterfaces InterfaceBody ; ExtendsInterfaces: _extends_ InterfaceType {env.clazz->interfaces.add($2); } | ExtendsInterfaces ',' InterfaceType {env.clazz->interfaces.add($3); }; InterfaceBody: '{' oInterfaceMemberDeclarations '}' ; oInterfaceMemberDeclarations: /* e */ | InterfaceMemberDeclarations; InterfaceMemberDeclarations: InterfaceMemberDeclaration | InterfaceMemberDeclarations InterfaceMemberDeclaration ; InterfaceMemberDeclaration: ConstantDeclaration | AbstractMethodDeclaration ; ConstantDeclaration: FieldDeclaration; AbstractMethodDeclaration: MethodHeader ';' ; /* 19.10 Productions from 10: Arrays */ ArrayInitializer: '{' ',' '}' {$$ = new ArrayExpression(0); } | '{' oVariableInitializers '}' {$$ = new ArrayExpression($2->first);}; oComma: | ',' ; oVariableInitializers: {$$ = new ExprList(); } | VariableInitializers oComma {$$ = $1;}; VariableInitializers: VariableInitializer {$$ = new ExprList($1); } | VariableInitializers ',' VariableInitializer {$$=$1; $1->add($3); }; /****************** Statement ***********************/ ReferenceType: ClassOrInterfaceType | ArrayType; ClassOrInterfaceType: Name {$$ = Type::NewClass($1->toIdent()); }; ClassType: ClassOrInterfaceType; InterfaceType: ClassOrInterfaceType; ArrayType: PrimitiveType '[' ']' {$$ = Type::NewArray($1); } | Name '[' ']' { $$ = Type::NewArray(Type::NewClass($1->toIdent())); } | ArrayType '[' ']' {$$ = Type::NewArray($1); }; Type: PrimitiveType | ReferenceType ; Block: '{' oBlockStatements '}' {$$ = new CompoundStatement($2); }; oBlockStatements: {$$ = 0;} | BlockStatements {$$ = $1->first; }; BlockStatements: BlockStatement {$$ = new StmtList($1); } | BlockStatements BlockStatement {$$ = $1; $$->add($2); }; BlockStatement: LocalVariableDeclarationStatement | Statement ; LocalVariableDeclarationStatement: LocalVariableDeclaration ';' ; LocalVariableDeclaration: Type VariableDeclarators { $$ = new DeclarationStatement(0,new TypeExpression($1), new ExpressionStatement($2->first)); }; Statement: StatementWithoutTrailingSubstatement | LabeledStatement | IfThenStatement | IfThenElseStatement | WhileStatement | ForStatement ; StatementNoShortIf: StatementWithoutTrailingSubstatement | LabeledStatementNoShortIf | IfThenElseStatementNoShortIf | WhileStatementNoShortIf | ForStatementNoShortIf ; StatementWithoutTrailingSubstatement : Block | EmptyStatement | ExpressionStatement | SwitchStatement | DoStatement | BreakStatement | ContinueStatement | ReturnStatement | SynchronizedStatement | ThrowStatement | TryStatement ; EmptyStatement: ';' {$$ = new EmptyStatement(); }; LabeledStatement: ident ':' Statement {$$ = $3; $$->addLabel($1); }; LabeledStatementNoShortIf: ident ':' StatementNoShortIf {$$ = $3; $$->addLabel($1);}; ExpressionStatement: StatementExpression ';' {$$ = new ExpressionStatement($1); }; StatementExpression: Assignment | PreIncDec | PostIncDec | MethodInvocation | NewClassInstance ; IfThenStatement: _if_ '(' Expression ')' Statement {$$=new IfStatement($3,$5,0);}; IfThenElseStatement: _if_ '(' Expression ')' StatementNoShortIf _else_ Statement {$$=new IfStatement($3,$5,$7);}; IfThenElseStatementNoShortIf: _if_ '(' Expression ')' StatementNoShortIf _else_ StatementNoShortIf {$$=new IfStatement($3,$5,$7);}; SwitchStatement: _switch_ '(' Expression ')' SwitchBlock {$$ = new SwitchStatement($3,$5)}; SwitchBlock: '{' SwitchBlockStatementGroups oSwitchLabels '}' {$$=new CompoundStatement($2->first);} | '{' oSwitchLabels '}' {$$=new CompoundStatement(0);}; oSwitchLabels: /* e */ | SwitchLabels {}; SwitchBlockStatementGroups: SwitchBlockStatementGroup {$$ = $1;} | SwitchBlockStatementGroups SwitchBlockStatementGroup {$$=$1; $$->glueList($1); }; SwitchBlockStatementGroup: SwitchLabels BlockStatements {$$=$1; $$->glueList($1); }; SwitchLabels: SwitchLabel {$$ = new StmtList($1); } | SwitchLabels SwitchLabel {$$=$1; $$->add($2);}; SwitchLabel: _case_ ConstantExpression ':' {$$ = new CaseStatement($2); } | _default_ ':' {$$ = new CaseStatement(0); }; WhileStatement: _while_ '(' Expression ')' Statement {$$ = new WhileStatement($3,$5);}; WhileStatementNoShortIf: _while_ '(' Expression ')' StatementNoShortIf {$$ = new WhileStatement($3,$5);}; DoStatement: _do_ Statement _while_ '(' Expression ')' ';' {$$ = new DoStatement($2,$5);}; ForStatement: _for_ '(' oForInit ';' oForExpression ';' oForUpdate ')' Statement {$$ = new ForStatement($3,$5,$7,$9); }; ForStatementNoShortIf: _for_ '(' oForInit ';' oForExpression ';' oForUpdate ')' StatementNoShortIf {$$ = new ForStatement($3,$5,$7,$9); }; oForInit: {$$ = 0;} | ForInit ; oForUpdate: {$$ = 0;} | ForUpdate ; oForExpression: {$$ = 0;} | Expression ; ForInit: StatementExpressionList {$$ = new ExpressionStatement($1); } | LocalVariableDeclaration {$$ = $1;}; ForUpdate: StatementExpressionList ; StatementExpressionList: StatementExpression {$$ = $1; } | StatementExpressionList ',' StatementExpression {$$ = new CommaExpression($1, $3); }; oIdent: /* e */ {$$ = Identifier::nullstr} | ident {$$ = $1;}; BreakStatement: _break_ oIdent ';' {$$ = new BreakStatement($2); }; ContinueStatement: _continue_ oIdent ';' {$$ = new ContinueStatement($2); }; ReturnStatement: _return_ ';' {$$ = new ReturnStatement(0); } | _return_ Expression ';' {$$ = new ReturnStatement($2); }; ThrowStatement: _throw_ Expression ';' {$$ = new ThrowStatement($2); }; SynchronizedStatement: _synchronized_ '(' Expression ')' Block {$$ = new SynchronizedStatement($3, $5); }; TryStatement: _try_ Block Catches {$$ = $2;} // !! not implemented yet | _try_ Block oCatches Finally {$$ = $2; }; oCatches: /* e */ | Catches ; Catches: CatchClause | Catches CatchClause ; CatchClause: _catch_ '(' FormalParameter ')' Block ; Finally: _finally_ Block ; /************************* Expression ****************************/ Expression: AssignExpression; Primary: NoNewArray | ArrayCreation ; NoNewArray: Literal | _this_ | '(' Expression ')' {$$ = new ExprExpression($2); } | NewClassInstance | FieldAccess | MethodInvocation | ArrayAccess ; NewClassInstance: _new_ ClassType '(' oArgList ')' {$$ = new NewInstanceExpression($2, $4); }; oArgList: {$$ = 0;} | ArgList {$$ = $1->first; }; ArgList: Expression {$$ = new ExprList($1); } | ArgList ',' Expression {$$ = $1; $$->add($3); }; ArrayCreation: _new_ Name {env.arrayElem = $2;} DimExprs oDims | _new_ PrimitiveType {env.arrayElem = new TypeExpression($2);} DimExprs oDims; DimExprs: DimExpr | DimExprs DimExpr ; DimExpr: '[' Expression ']' { env.arrayElem = new ArrayGenerateExpression(env.arrayElem, $2); }; oDims: | Dims; Dims: '[' ']' {env.arrayElem = new ArrayGenerateExpression(env.arrayElem, 0);} |Dims '[' ']' {env.arrayElem = new ArrayGenerateExpression(env.arrayElem, 0);}; FieldAccess: Primary '.' ident {$$ = new FieldExpression($1,$3); } | _super_ '.' ident {$$ = new FieldExpression($1,$3); }; MethodInvocation: Primary '.' ident '(' oArgList ')' {$$ = new MethodExpression($1,$3,$5); } | Name '(' oArgList ')' {$$ = new MethodExpression($1,$3); } | _super_ '.' ident '(' oArgList ')' {$$ = new MethodExpression($1,$3,$5); } ; ArrayAccess: Name '[' Expression ']' {$$ = new ArrayAccessExpression($1,$3); } | NoNewArray '[' Expression ']' {$$ = new ArrayAccessExpression($1,$3); }; Postfix: Primary | Name | PostIncDec ; PostIncDec: Postfix IncDec { $$ = new PostIncDecExpression($2,$1); }; Unary: AddOp Unary {$$ = new NegPosExpression($1, $2); } | PreIncDec | UnaryNotPM ; PreIncDec: IncDec Unary {$$ = new PreIncDecExpression($1,$2); }; UnaryNotPM: Postfix | NegNot Unary {$$ = new UnaryExpression($1, $2->type, $2); } | CastExpr; SaveElem: {$$ = env.arrayElem; } CastExpr:'(' PrimitiveType {env.arrayElem = new TypeExpression($2);} oDims ')' SaveElem Unary {$$ = new CastExpression($6,$7); } | '(' Name '[' ']' {env.arrayElem = new ArrayGenerateExpression($2,0);} oDims ')' SaveElem UnaryNotPM {$$ = new CastExpression($8,$9); } | '(' Expression ')' UnaryNotPM {$$ = new CastExpression($2,$4); }; MulExpr: Unary | MulExpr MulOp Unary {$$ = new BinaryArithmeticExpression($2,$1,$3); }; AddExpr: MulExpr | AddExpr AddOp MulExpr {$$ = new BinaryArithmeticExpression($2,$1,$3); }; ShiftExpr: AddExpr | ShiftExpr ShiftOp AddExpr {$$ = new BinaryShiftExpression($2,$1,$3); }; RelExpr: ShiftExpr | RelExpr RelOp ShiftExpr {$$ = new BinaryCompareExpression($2,$1,$3); } | RelExpr _instanceof_ ReferenceType {$$ = new InstanceOfExpression($1, new TypeExpression($3) ); }; EqualExpr: RelExpr | EqualExpr EqualOp RelExpr {$$ = new BinaryEqualityExpression($2,$1,$3); }; AndExpr: EqualExpr | AndExpr '&' EqualExpr {$$ = new BinaryBitExpression(BITAND,$1,$3);}; XorExpr: AndExpr | XorExpr '^' AndExpr {$$ = new BinaryBitExpression(BITXOR,$1,$3);}; OrExpr: XorExpr | OrExpr '|' XorExpr {$$ = new BinaryBitExpression(BITOR,$1,$3);}; AndAlso: OrExpr | AndAlso _andand_ OrExpr {$$ = new BinaryLogicalExpression(AND,$1,$3);}; OrElse: AndAlso | OrElse _oror_ AndAlso {$$ = new BinaryLogicalExpression(OR,$1,$3);}; CondExpr: OrElse | OrElse '?' Expression ':' CondExpr {$$ = new ConditionalExpression($1,$3,$5); }; LeftHandSide: Name | FieldAccess | ArrayAccess; Assignment: LeftHandSide AssOp AssignExpression {$$ = new BinaryAssignExpression($2,$1,$3); }; AssignExpression: Assignment | CondExpr; ConstantExpression: Expression; // !! Check constness %% #include /* void describe() { int i,d; static char* a[] = {"Default %s\n","[%s]","%s "}; for(i = 1; i < sizeof(yytranslate)/sizeof(yytranslate[0]); ++i) { int yychar = YYTRANSLATE(i); int yyn = yypact[yystate] + yychar; if(yychar < 3) continue; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar) {d = 0;} else { yyn = yytable[yyn]; if(yyn == 0 || yyn == YYFLAG) continue; if( yyn < 0 ) d = 1; else d = 2; printf(a[d],yytname[yychar]); } } } */ #include "scanner.c" #ifdef YYBISON const char* TokenName(int c) { return yytname[YYTRANSLATE(c)]; } #else const char* TokenName(int c) { return "Use Bison. Token Name unaccessible in Yacc";} #endif int main(int argc, char ** argv) { cout << "Main Begin" << endl; #ifndef YYBISON printf("Please use bison (GNU's version of yacc)\n"); printf("Please use bison (GNU's version of yacc)\n"); #else extern int yydebug; #endif yydebug = argc == 2; #ifdef YYBISON if (argc == 3) { int c; int curno = 0; printf("1:"); while(c = yylex()) { if (curno != lineno) {printf("\n%d:",lineno); curno = lineno;} printf(" %s", TokenName(c)); } printf("\n"); return 0; } #endif cout << "Before yyparse() " << endl; if(yyparse() == 0) printf("No Errors\n"); cout << "----------- " << QuickNew::Avail() << endl; cout << env.pkg; QuickNew::finalize(); cout << "After finalize" << endl; } int yyerror(char *s) { printf("Line %d: Unexpected token %s\n",lineno, TokenName(yychar)); printf(s); /* printf("Possible alternative(s) is(are):"); describe(); */ printf("\n"); exit(1); return 0; }