%{ /*** * Shane Beasley * EECS 473: Compiler Design * Machine Problem 4: Using Bison ***/ #include "decls.h" #include "parser.h" #include #include filepos_t currentPos = { 1, 1 }, tokenPos = currentPos; string globalBuffer; set tokenPool; inline void startToken (void) { tokenPos = currentPos; } inline void advancePos (void) { currentPos.column += yyleng; } void normalToken (void) { startToken(); advancePos(); yylval.c_str = tokenPool.insert(yytext).first->c_str(); } %} /*** * identifer - a sequence of alphabetic, numeric and underscore * characters, not starting with a numeric character. ***/ IDBEGIN _|[[:alpha:]] IDTERM _|[[:alnum:]] IDENTIFIER {IDBEGIN}{IDTERM}* /*** * character - a single character delimited by matching single quotes * ('). Special characters can be represented by multiple characters * (that are still delimited by matching single quotes) using escape * notation: ***/ ESCAPE_CHAR \'|\"|"?"|\\|f|n|r|t|[[:digit:]]+ ESCAPE_ATOM \\{ESCAPE_CHAR} CHAR_ATOM {ESCAPE_ATOM}|[^\\] CHARACTER \'{CHAR_ATOM}\' // integer - a sequence of digits. INTEGER [[:digit:]]+ /*** * float - two sequences of digits separated by a decimal point (.). * Either sequnce of digits (but not both) may be empty. ***/ FLOAT1 [[:digit:]]+"."[[:digit:]]* FLOAT2 "."[[:digit:]]+ FLOAT {FLOAT1}|{FLOAT2} /*** * The program is to ignore and blanks, tabs, newlines, formfeeds and * comments found in the program. ***/ CPP_COMMENT "//"[^\n]* %% // keyword - an identifer with one of the following values. "char" { normalToken(); return KEYWORD_CHAR; } "class" { normalToken(); return KEYWORD_CLASS; } "delete" { normalToken(); return KEYWORD_DELETE; } "else" { normalToken(); return KEYWORD_ELSE; } "false" { normalToken(); return KEYWORD_FALSE; } "if" { normalToken(); return KEYWORD_IF; } "int" { normalToken(); return KEYWORD_INT; } "new" { normalToken(); return KEYWORD_NEW; } "private" { normalToken(); return KEYWORD_PRIVATE; } "public" { normalToken(); return KEYWORD_PUBLIC; } "return" { normalToken(); return KEYWORD_RETURN; } "true" { normalToken(); return KEYWORD_TRUE; } "void" { normalToken(); return KEYWORD_VOID; } "while" { normalToken(); return KEYWORD_WHILE; } "cin" { normalToken(); return KEYWORD_CIN; } "cout" { normalToken(); return KEYWORD_COUT; } "->" { normalToken(); return ARROW_OPERATOR; } ">=" { normalToken(); return GREATER_THAN_OR_EQUAL_TO_OPERATOR; } "<=" { normalToken(); return LESS_THAN_OR_EQUAL_TO_OPERATOR; } "==" { normalToken(); return EQUAL_TO_OPERATOR; } "!=" { normalToken(); return NOT_EQUAL_TO_OPERATOR; } "&&" { normalToken(); return LOGICAL_AND_OPERATOR; } "||" { normalToken(); return LOGICAL_OR_OPERATOR; } "<<" { normalToken(); return SHIFT_LEFT_OPERATOR; } ">>" { normalToken(); return SHIFT_RIGHT_OPERATOR; } {CHARACTER} { normalToken(); return CHARACTER; } {IDENTIFIER} { normalToken(); return IDENTIFIER; } {INTEGER} { normalToken(); return INTEGER; } {FLOAT} { normalToken(); return FLOAT; } {CPP_COMMENT} { advancePos(); } \n { currentPos.column = 1; currentPos.line++; } [[:space:]] { advancePos(); } "/*" { // ignoring C-style /* ... */ comments int last = 0, cur; startToken(); for (currentPos.column++, cur = yyinput(); last != '*' || cur != '/'; currentPos.column++, cur = yyinput()) { if (cur == EOF) { cout << "Unterminated C comment on line " << tokenPos.line << ", column " << tokenPos.column << endl; return 0; } else if (cur == '\n') { currentPos.column = 1; currentPos.line++; } last = cur; } } "\"" { // reading string constant int c; globalBuffer = '"'; startToken(); for (currentPos.column++, c = yyinput(); c != '"'; currentPos.column++, c = yyinput()) { if (c == EOF) { cerr << "Unterminated string constant on line " << tokenPos.line << ", column " << tokenPos.column << endl; return 0; } globalBuffer += c; if (c == '\n') { currentPos.column = 1; currentPos.line++; } } globalBuffer += c; return STRING; } . { normalToken(); return *yytext; } %%