/* lexer.l */ /* * The incl state is used for picking up the name of an include file */ %x incl %x comment %x str %{ #include #include #include #include "types.h" #include "y.tab.h" #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int lineno_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; #define MAX_STR_CONST 1024 char string_buf[MAX_STR_CONST]; char *string_buf_ptr; %} %option yylineno %% %include BEGIN(incl); "/*" BEGIN(comment); { [^*]* /* eat anything that's not a '*' */ "*"+[^*/]* /* eat up '*'s not followed by '/'s */ "*"+"/" BEGIN(INITIAL); } \" string_buf_ptr = string_buf; BEGIN(str); { \" { BEGIN(INITIAL); *string_buf_ptr = '\0'; yylval.Tstring = strdup(string_buf); return STRING; } \n { fprintf(stderr, "Unterminated string at line %d\n", yylineno); exit(1); } \\[0-7]{1,3} { /* octal escape sequence */ int result; (void) sscanf(yytext + 1, "%o", &result); if (result > 0xff) { fprintf(stderr, "octal escape out of bounds at line %d\n", yylineno); exit(1); } } \\[0-9]+ { /* bad escape sequence */ fprintf(stderr, "bad escape sequence at line %d\n", yylineno); exit(1); } \\n *string_buf_ptr++ = '\n'; \\t *string_buf_ptr++ = '\t'; \\r *string_buf_ptr++ = '\r'; \\b *string_buf_ptr++ = '\b'; \\f *string_buf_ptr++ = '\f'; \\(.|\n) *string_buf_ptr++ = yytext[1]; [^\\\n\"]+ { char *yptr = yytext; while (*yptr) *string_buf_ptr++ = *yptr++; } } function return TOKFUNCTION; fndefint return TOKFNDEFINT; fndefext return TOKFNDEFEXT; constant return TOKCONSTANT; while return TOKWHILE; if return TOKIF; else return TOKELSE; switch return TOKSWITCH; case return TOKCASE; default return TOKDEFAULT; break return TOKBREAK; return return TOKRETURN; == return TOKEQ; != return TOKNE; \<= return TOKLE; \>= return TOKGE; && return TOKAND; \|\| return TOKOR; [0-9]+ yylval.Tinteger = atoi(yytext); return NUMBER; -[0-9]+ yylval.Tinteger = atoi(yytext); return NUMBER; /* Cater for the possibility that things might be signed or unsigned. This is horrible and ugly, but might just work. */ 0x[0-9a-fA-F]+ yylval.Tinteger = strtoul(yytext+2, (char **)NULL, 16); return NUMBER; -0x[0-9a-fA-F]+ yylval.Tinteger = strtol(yytext+2, (char **)NULL, 16); return NUMBER; [0-9]+\.[0-9]+ yylval.Treal = atof(yytext); return REAL; -[0-9]+\.[0-9]+ yylval.Treal = atof(yytext); return REAL; [_a-zA-Z0-9]+ yylval.Tstring = strdup(yytext); return IDENTIFIER; %[_a-zA-Z0-9]+ yylval.Tstring = strdup(yytext); return IDENTIFIER; $[_a-zA-Z0-9]+ yylval.Tstring = strdup(yytext); return IDENTIFIER; [ \t\n]+ /* eat whitespace */ . return (int) yytext[0]; [ \t]* /* eat the whitespace */ [^ \t\n]+ { /* got the include filename */ if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { fprintf(stderr, "Includes nested too deeply"); exit(1); } include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; lineno_stack[include_stack_ptr++] = yylineno; yyin = fopen(yytext, "r"); yylineno = 1; if (!yyin) err(1, "%s", yytext); yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); BEGIN(INITIAL); } <> { if (--include_stack_ptr < 0) { yyterminate(); } else { yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer( include_stack[include_stack_ptr]); yylineno = lineno_stack[include_stack_ptr]; } } %%