summaryrefslogtreecommitdiff
path: root/lex-pattern.l
diff options
context:
space:
mode:
Diffstat (limited to 'lex-pattern.l')
-rw-r--r--lex-pattern.l58
1 files changed, 58 insertions, 0 deletions
diff --git a/lex-pattern.l b/lex-pattern.l
new file mode 100644
index 0000000..d091c74
--- /dev/null
+++ b/lex-pattern.l
@@ -0,0 +1,58 @@
+%{
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "ast.h"
+#include "parse-pattern.h"
+
+static int intlit(long *out, const char *in)
+{
+ errno = 0;
+ *out = strtol(in, NULL, 10);
+ return errno == ERANGE ? T_BADLIT : T_INTEGER;
+}
+
+static int strlit(char **out, const char *in, size_t inlen)
+{
+ in += 1;
+ inlen -= 2;
+
+ size_t len = 0;
+ for (const char *c = in; c < in + inlen; c++, len++) {
+ if (*c == '\"') c++;
+ }
+
+ char *str;
+ if (!(*out = str = malloc(len + 1))) return T_NOMEM;
+
+ for (const char *c = in; c < in + inlen; *str++ = *c++) {
+ if (*c == '\"') c++;
+ }
+ *str = 0;
+
+ return T_STRING;
+}
+
+%}
+
+%option outfile="lex-pattern.c" header-file="lex-pattern.h"
+%option noyywrap never-interactive
+
+%%
+
+\( { return T_LPAREN; }
+\) { return T_RPAREN; }
+, { return T_COMMA; }
+\. { return T_PERIOD; }
+A { return T_ALPHABETIC; }
+N { return T_NUMERIC; }
+U { return T_UPPERCASE; }
+L { return T_LOWERCASE; }
+C { return T_CONTROL; }
+P { return T_PUNCTUATION; }
+E { return T_EVERYTHING; }
+[0-9]+ { return intlit(&yylval.lval, yytext); }
+\"(\"\"|[^"])*\" { return strlit(&yylval.sval, yytext, yyleng); }
+
+%%