/* scanner.l */ %{ #include #include #include #include "project.h" #include "grammar.h" /* Current line */ static struct { int number; /* Line number */ int col; /* Line column */ char* text; /* Text of current line */ int size; /* Maximum length of `text' */ } line; FILE* yyin; %} COMMENT \#.* BIN_CONST 0b[0-1]+ OCT_CONST 0[0-7]* DEC_CONST [1-9][0-9]* HEX_CONST 0x[0-9a-fA-F]* CHAR_CONST '[^'\\]'|'\\[abefnrtv'\\]'|'\\[0-3]?[0-7]{1,2}'|'\\x[0-9a-fA-F]{1,2}' WS [ \v\t\f\r]+ ID [_a-zA-Z.][_a-zA-Z0-9.]* %% {COMMENT} { /* Eat juicy comments (yum!) */ } {BIN_CONST} { line.col += yyleng; yylval.val = strtoul(yytext + 2, NULL, 2); return INT; } {OCT_CONST} { line.col += yyleng; yylval.val = strtoul(yytext, NULL, 8); return INT; } {DEC_CONST} { line.col += yyleng; yylval.val = strtoul(yytext, NULL, 10); return INT; } {HEX_CONST} { line.col += yyleng; yylval.val = strtoul(yytext, NULL, 16); return INT; } {CHAR_CONST} { line.col += yyleng; if (yyleng == 3) { yylval.val = yytext[1]; } else if (yyleng == 4) { switch (yytext[2]) { case 'a': yylval.val = 7; break; case 'b': yylval.val = 8; break; case 'e': yylval.val = 27; break; case 'f': yylval.val = 12; break; case 'n': yylval.val = 10; break; case 'r': yylval.val = 13; break; case 't': yylval.val = 9; break; case 'v': yylval.val = 11; break; case '\'':yylval.val = 39; break; case '\\':yylval.val = 92; break; default: yylval.val = yytext[2] - '0'; } } else { line.col += yyleng; yytext[yyleng - 1] = 0; yylval.val = strtoul(yytext + 3, NULL, 16); } return INT; } {ID} { line.col += yyleng; yylval.str = strdup(yytext); /* Memory leak */ return ID; } \|\| {line.col += yyleng; return IOR;} && {line.col += yyleng; return AND;} == {line.col += yyleng; return EQV;} != {line.col += yyleng; return NEQ;} \<= {line.col += yyleng; return LEQ;} \>= {line.col += yyleng; return GEQ;} \<\< {line.col += yyleng; return SHL;} \>\> {line.col += yyleng; return SHR;} {WS} { /* Skip over spaces */ line.col += yyleng; } \n.* { /* Track newlines */ line.number++; if (yyleng > line.size) { /* Grow buffer */ if (line.text) free(line.text); line.text = strdup(yytext + 1); line.size = yyleng; } else { /* Copy line into existing buffer */ strcpy(line.text, yytext + 1); } line.col = 1; /* Re-process line, skipping the newline character */ yyless(1); } . { /* Leftovers */ line.col++; return yytext[0]; } %% int yywrap() { return 1; } /* Basic error handler. */ void yyerror(char* s) { char caret[] = "^"; fprintf(stderr, "%s: line %d, col %d\n", s, line.number, line.col); fprintf(stderr, "%s\n%*s\n", line.text, line.col, caret); } /* Reinitializes the scanner to begin a new file. */ void scanner_init(void) { int count; line.number = 1; count = getline(&line.text, &line.size, yyin); if (count == -1) { perror("getline"); exit(EXIT_FAILURE); } fseek(yyin, -count, SEEK_CUR); } /* EOF */