diff options
author | Jakob Kaivo <jkk@ung.org> | 2022-04-17 15:55:30 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2022-04-17 15:55:30 -0400 |
commit | 59ddf28516c22963f0e4f04d793f28f7d00db401 (patch) | |
tree | aa92fdf538779071eebd2bdc26a3e2f595a6dc8a | |
parent | de4091fec9cd5716445ae40f95789188e018d476 (diff) |
use custom yylex() to directly parse command line arguments
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | expr.h | 9 | ||||
-rw-r--r-- | expr.l | 74 | ||||
-rw-r--r-- | expr.y | 116 |
4 files changed, 113 insertions, 93 deletions
@@ -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 @@ -1,9 +0,0 @@ -typedef struct { - int type; - union { - int i; - char *s; - } u; -} expr_yystype; - -#define YYSTYPE expr_yystype @@ -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(); -} @@ -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(); +} |