diff options
Diffstat (limited to 'examples/c/reccalc/scan.l')
-rw-r--r-- | examples/c/reccalc/scan.l | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/examples/c/reccalc/scan.l b/examples/c/reccalc/scan.l new file mode 100644 index 00000000..7cf0ceef --- /dev/null +++ b/examples/c/reccalc/scan.l @@ -0,0 +1,85 @@ +/* Prologue (directives). -*- C++ -*- */ + +/* Disable Flex features we don't need, to avoid warnings. */ +%option nodefault noinput nounput noyywrap + +%option reentrant + +%{ +#include <assert.h> +#include <limits.h> /* INT_MIN */ +#include <stdlib.h> /* strtol */ + +#include "parse.h" +%} + +%x SC_STRING + +%% +%{ + int nesting = 0; + char *str = NULL; + int size = 0; + int capacity = 0; +#define STR_APPEND() \ + do { \ + if (capacity < size + yyleng + 1) \ + { \ + do \ + capacity = capacity ? 2 * capacity : 128; \ + while (capacity < size + yyleng + 1); \ + str = realloc (str, capacity); \ + } \ + strncpy (str + size, yytext, yyleng); \ + size += yyleng; \ + assert (size < capacity); \ + } while (0) +%} + + // Rules. + +"+" return TOK_PLUS; +"-" return TOK_MINUS; +"*" return TOK_STAR; +"/" return TOK_SLASH; + +"(" nesting += 1; BEGIN SC_STRING; + + /* Scan an integer. */ +[0-9]+ { + errno = 0; + long n = strtol (yytext, NULL, 10); + if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE)) + yyerror (yyscanner, res, "integer is out of range"); + yylval->TOK_NUM = (int) n; + return TOK_NUM; +} + + /* Ignore white spaces. */ +[ \t]+ continue; + +"\n" return TOK_EOL; + +. yyerror (yyscanner, res, "syntax error, invalid character: %c", yytext[0]); + +<SC_STRING> +{ + "("+ nesting += yyleng; STR_APPEND (); + ")" { + if (!--nesting) + { + BEGIN INITIAL; + if (str) + str[size] = 0; + yylval->TOK_STR = str; + return TOK_STR; + } + else + STR_APPEND (); + } + [^()]+ STR_APPEND (); +} + +<<EOF>> return TOK_EOF; +%% +/* Epilogue (C code). */ |