summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--expr.h9
-rw-r--r--expr.l74
-rw-r--r--expr.y116
4 files changed, 113 insertions, 93 deletions
diff --git a/Makefile b/Makefile
index 33e958f..3ebd801 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,5 @@
-expr: expr.c y.tab.c y.tab.h
- $(CC) -g -o $@ expr.c y.tab.c -ll -ly
-
-expr.c: expr.l
- lex -t expr.l > expr.c
+expr: y.tab.c y.tab.h
+ $(CC) -g -o $@ y.tab.c -ly
y.tab.c y.tab.h: expr.y
yacc -d expr.y
diff --git a/expr.h b/expr.h
deleted file mode 100644
index 4b4a874..0000000
--- a/expr.h
+++ /dev/null
@@ -1,9 +0,0 @@
-typedef struct {
- int type;
- union {
- int i;
- char *s;
- } u;
-} expr_yystype;
-
-#define YYSTYPE expr_yystype
diff --git a/expr.l b/expr.l
deleted file mode 100644
index 57b3de2..0000000
--- a/expr.l
+++ /dev/null
@@ -1,74 +0,0 @@
-%{
-#define _XOPEN_SOURCE 700
-#include <locale.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "expr.h"
-
-#include "y.tab.h"
-
-extern int yyparse(void);
-
-%}
-
-DIGIT [0-9]
-
-%%
-
-"|" return '|';
-"&" return '&';
-"=" return '=';
-">" return '>';
-">=" return GE;
-"<" return '<';
-"<=" return LE;
-"!=" return NE;
-"+" return '+';
-"-" return '-';
-"*" return '*';
-"/" return '/';
-"%" return '%';
-"(" return '(';
-")" return ')';
-":" return ':';
-{DIGIT}+ { yylval.u.i = atoi(yytext); return yylval.type = INTEGER; }
--{DIGIT}+ { yylval.u.i = atoi(yytext); return yylval.type = INTEGER; }
-.+ { yylval.u.s = strdup(yytext); return yylval.type = STRING; }
-\n ;
-
-%%
-
-int main(int argc, char *argv[])
-{
- setlocale(LC_ALL, "");
-
- int c;
- while ((c = getopt(argc, argv, "")) != -1) {
- switch (c) {
- default:
- return -1;
- }
- }
-
- if (optind >= argc) {
- fprintf(stderr, "expr: missing operands\n");
- return 1;
- }
-
- size_t n = 1;
- for (int i = optind; i < argc; i++) {
- n += strlen(argv[i]) + 1;
- }
-
- FILE *mem = fmemopen(NULL, n, "w+");
- for (int i = optind; i < argc; i++) {
- fprintf(mem, "%s\n", argv[i]);
- }
- rewind(mem);
-
- yyin = mem;
-
- return yyparse();
-}
diff --git a/expr.y b/expr.y
index b2f2061..f409c5c 100644
--- a/expr.y
+++ b/expr.y
@@ -1,16 +1,27 @@
%{
+#define _XOPEN_SOURCE 700
+#include <locale.h>
+#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+typedef struct {
+ int type;
+ union {
+ intmax_t i;
+ char *s;
+ } u;
+} expr_yystype;
+
+#define YYSTYPE expr_yystype
-#include "expr.h"
#include "y.tab.h"
-extern int yylex(void);
+static int yylex(void);
extern int yyerror(const char *s);
-static void breakpoint(void) { }
-
static void expr_only_integers(YYSTYPE *y1, YYSTYPE *y2)
{
if (y1->type == STRING) {
@@ -140,3 +151,98 @@ expr : STRING {
printf("or\n");
}
;
+
+%%
+
+
+/*
+
+"|" return '|';
+"&" return '&';
+"=" return '=';
+">" return '>';
+">=" return GE;
+"<" return '<';
+"<=" return LE;
+"!=" return NE;
+"+" return '+';
+"-" return '-';
+"*" return '*';
+"/" return '/';
+"%" return '%';
+"(" return '(';
+")" return ')';
+":" return ':';
+{DIGIT}+ { yylval.u.i = atoi(yytext); return yylval.type = INTEGER; }
+-{DIGIT}+ { yylval.u.i = atoi(yytext); return yylval.type = INTEGER; }
+.+ { yylval.u.s = strdup(yytext); return yylval.type = STRING; }
+\n ;
+
+*/
+
+static char **expr_args;
+
+static int yylex(void)
+{
+ if (expr_args[optind] == NULL) {
+ return YYEOF;
+ }
+
+ char *s = expr_args[optind];
+
+ if (strlen(s) == 1) {
+ char c = s[0];
+ if (strchr("|&=+-*/%():", c)) {
+ optind++;
+ return c;
+ }
+ }
+
+ if (strlen(s) == 2) {
+ if (!strcmp(s, ">=")) {
+ optind++;
+ return GE;
+ }
+ if (!strcmp(s, "<=")) {
+ optind++;
+ return LE;
+ }
+ if (!strcmp(s, "!=")) {
+ optind++;
+ return NE;
+ }
+ }
+
+ char *end = NULL;
+ yylval.type = INTEGER;
+ yylval.u.i = strtoimax(s, &end, 10);
+ if (end && *end != '\0') {
+ yylval.type = STRING;
+ yylval.u.s = s;
+ }
+
+ optind++;
+ return yylval.type;
+}
+
+int main(int argc, char *argv[])
+{
+ setlocale(LC_ALL, "");
+
+ int c;
+ while ((c = getopt(argc, argv, "")) != -1) {
+ switch (c) {
+ default:
+ return -1;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "expr: missing operands\n");
+ return 1;
+ }
+
+ expr_args = argv;
+
+ return yyparse();
+}