%{ /*** * Shane Beasley * EECS 473: Compiler Design * Machine Problem 4: Using Bison ***/ #include #include #include extern struct filepos_t { size_t line, column; } tokenPos; extern "C" { // defined by lex int yylex (void); inline void yyerror (const char *ptr) { cerr << "line " << tokenPos.line << ", col " << tokenPos.column << ": " << ptr << endl; } } %} %union { const char *c_str; } %token KEYWORD_CHAR KEYWORD_CLASS KEYWORD_DELETE KEYWORD_ELSE KEYWORD_FALSE %token KEYWORD_IF KEYWORD_INT KEYWORD_NEW KEYWORD_PRIVATE KEYWORD_PUBLIC %token KEYWORD_RETURN KEYWORD_TRUE KEYWORD_VOID KEYWORD_WHILE %token KEYWORD_CIN KEYWORD_COUT %token ARROW_OPERATOR %token GREATER_THAN_OR_EQUAL_TO_OPERATOR LESS_THAN_OR_EQUAL_TO_OPERATOR EQUAL_TO_OPERATOR NOT_EQUAL_TO_OPERATOR %token LOGICAL_AND_OPERATOR LOGICAL_OR_OPERATOR SHIFT_LEFT_OPERATOR SHIFT_RIGHT_OPERATOR %token INTEGER %token FLOAT %token CHARACTER %token IDENTIFIER %token STRING %type type %type num %type ident %% StartPrime : Start { } ; Start : StartItem Start | // empty ; StartItem : varDecl | classDef | functDef | prototype ; varDecl : type varList ';' { } ; varList : varList ',' varIdent { } | varIdent { } ; varIdent : ptrIdent brackets ; ptrIdent : '*' IDENTIFIER | IDENTIFIER { } ; brackets : '[' num ']' | // empty ; type : KEYWORD_INT | KEYWORD_CHAR | IDENTIFIER { $$ = $1; } ; classDef : KEYWORD_CLASS IDENTIFIER '{' classItems '}' ';' { } ; classItem : accessMode classMember | classMember ; classItems : classItem classItems | /* empty */ ; classMember : varDecl | functDef ; accessMode : KEYWORD_PUBLIC ':' { } | KEYWORD_PRIVATE ':' { } ; pfPrefix : type '*' IDENTIFIER '(' { } | type IDENTIFIER '(' { } | KEYWORD_VOID IDENTIFIER '(' { } ; pfFormal : pfPrefix formalParamList ')' ; prototype : pfFormal ';' { } | pfPrefix protoParamList ')' ';' { } ; functDef : pfFormal '{' body '}' { } ; fpItem : type '*' IDENTIFIER { } | type IDENTIFIER { } ; fpItems : fpItems ',' fpItem { } | fpItem { } ; formalParamList : fpItems | // empty ; protoItem : type '*' { } | type { } ; mixedItem : protoItem | fpItem ; protoItemsR : ',' mixedItem protoItemsR | // empty ; protoParamList : fpItems ',' protoItem protoItemsR { } | protoItem protoItemsR { } ; num : INTEGER { $$ = $1; } | FLOAT { $$ = $1; } ; statements : statement statements | // empty ; statement : lhsIdent '=' expr ';' { } | KEYWORD_IF '(' expr ')' statement KEYWORD_ELSE statement { } | KEYWORD_WHILE '(' expr ')' statement { } | '{' statements '}' { } | KEYWORD_RETURN expr ';' { } | fcall ';' { } | KEYWORD_COUT output ';' { } | KEYWORD_CIN input ';' { } ; output : SHIFT_LEFT_OPERATOR expr outputChain { } ; outputChain : SHIFT_LEFT_OPERATOR expr outputChain { } | // empty ; input : SHIFT_RIGHT_OPERATOR lhsIdent inputChain { } ; inputChain : SHIFT_RIGHT_OPERATOR lhsIdent inputChain { } | // empty ; exprBase : fcall { } | num { } | CHARACTER { } | STRING { } | '(' expr ')' { } | rhsIdent { } ; expr : exprBase | exprBase BOP expr { } | UOP expr { } ; callParamListFollow : ',' expr callParamListFollow | ; callParamList : expr callParamListFollow | // empty ; fcall : lhsIdent '(' callParamList ')' { } ; lhsBase : ident { } | ident '[' expr ']' { } ; ident : IDENTIFIER { } ; lhsIdent : lhsBase { } | lhsBase '.' lhsIdent { } | lhsBase ARROW_OPERATOR lhsIdent { } | '*' lhsIdent ; rhsIdent : lhsIdent | '&' lhsIdent ; BOP : '+' | '-' | '*' | '/' | '%' | '>' | GREATER_THAN_OR_EQUAL_TO_OPERATOR { } | '<' | LESS_THAN_OR_EQUAL_TO_OPERATOR { } | EQUAL_TO_OPERATOR { } | NOT_EQUAL_TO_OPERATOR { } | LOGICAL_AND_OPERATOR { } | LOGICAL_OR_OPERATOR { } ; UOP : '+' | '-' | '!' ; bodyPart : varDecl | statement | prototype ; body : bodyPart body | // empty ;