summaryrefslogtreecommitdiff
path: root/examples/c/reccalc/scan.l
diff options
context:
space:
mode:
Diffstat (limited to 'examples/c/reccalc/scan.l')
-rw-r--r--examples/c/reccalc/scan.l85
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). */