From 581f61a8ddf535175b03749b215ade43f3fa28c5 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Wed, 4 Sep 2024 19:10:47 +0200 Subject: Support multiple eqns per table --- src/lexer.l | 1 + src/main.c | 145 ++++++++++++++++++++++++++++++++++++++++---------------- src/parser.y | 60 +++++++++++++---------- src/pinocchio.h | 7 ++- src/wrapper.c | 27 +++++++++++ src/wrapper.h | 11 +++++ 6 files changed, 184 insertions(+), 67 deletions(-) create mode 100644 src/wrapper.c create mode 100644 src/wrapper.h (limited to 'src') diff --git a/src/lexer.l b/src/lexer.l index 832db79..befd30a 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -25,6 +25,7 @@ extern const char *current_file; \<=>|⇔ { return EQUIV; } \( { return OPAR; } \) { return CPAR; } +\| { return '|'; } \n { return EOL; } [a-zA-Z] { diff --git a/src/main.c b/src/main.c index 197f63a..d90bb96 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,13 +10,16 @@ #include #include #include -#include #include #include "lexer.h" #include "parser.h" +#include "wrapper.h" -#define MAXVARS (26 * 2) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MAXVARS (26 * 2) + +#define lengthof(x) ((sizeof(x) / sizeof(*(x)))) #ifndef __has_builtin # define __has_builtin(x) (0) @@ -41,8 +45,8 @@ static tbl_style_t tflag = TS_UNSET; const char *current_file; -static void astprocess_cli(ast_t); -static void astprocess_latex(ast_t); +static void astprocess_cli(asts_t); +static void astprocess_latex(asts_t); static bool eqnsolve(eqn_t *, uint64_t, uint64_t); static int eqnprint(eqn_t *); static void eqnfree(eqn_t *); @@ -77,11 +81,11 @@ main(int argc, char **argv) while ((opt = getopt_long(argc, argv, "b:t:", longopts, NULL)) != -1) { switch (opt) { case 'b': - if (strcmp(optarg, "alpha") == 0) + if (streq(optarg, "alpha")) bflag = BS_ALPHA; - else if (strcmp(optarg, "binary") == 0) + else if (streq(optarg, "binary")) bflag = BS_BINARY; - else if (strcmp(optarg, "symbols") == 0) + else if (streq(optarg, "symbols")) bflag = BS_SYMBOLS; else { warnx("invalid bool style -- '%s'", optarg); @@ -89,11 +93,11 @@ main(int argc, char **argv) } break; case 't': - if (strcmp(optarg, "ascii") == 0) + if (streq(optarg, "ascii")) tflag = TS_ASCII; - else if (strcmp(optarg, "latex") == 0) + else if (streq(optarg, "latex")) tflag = TS_LATEX; - else if (strcmp(optarg, "utf8") == 0) + else if (streq(optarg, "utf8")) tflag = TS_UTF8; else { warnx("invalid table style -- '%s'", optarg); @@ -109,7 +113,7 @@ usage: } if (tflag == TS_UNSET) { - tflag = strcmp(nl_langinfo(CODESET), "UTF-8") == 0 + tflag = streq(nl_langinfo(CODESET), "UTF-8") ? TS_UTF8 : TS_ASCII; } @@ -124,7 +128,7 @@ usage: rv = EXIT_FAILURE; } } else for (int i = 0; i < argc; i++) { - if (strcmp(argv[i], "-") == 0) + if (streq(argv[i], "-")) yyin = stdin; else if ((yyin = fopen(argv[i], "r")) == NULL) { warn("fopen: %s", argv[i]); @@ -141,13 +145,16 @@ usage: } void -astprocess(ast_t a) +astprocess(asts_t as) { - (tflag == TS_LATEX ? astprocess_latex : astprocess_cli)(a); + (tflag == TS_LATEX ? astprocess_latex : astprocess_cli)(as); + for (size_t i = 0; i < as.len; i++) + eqnfree(as.buf[i].eqn); + free(as.buf); } void -astprocess_cli(ast_t a) +astprocess_cli(asts_t as) { enum { TBLVBAR, @@ -174,39 +181,68 @@ astprocess_cli(ast_t a) const char **tblsyms = tflag == TS_UTF8 ? tblsyms_utf8 : tblsyms_ascii; + uint64_t varmsk = as.buf[0].vars; + for (size_t i = 1; i < as.len; i++) + varmsk |= as.buf[i].vars; + int varcnt = popcnt(varmsk); + for (int i = 0; i < MAXVARS; i++) { - if ((a.vars & UINT64_C(1)< 0;) printf("%s ", boolsyms[bflag][(bool)(msk & UINT64_C(1)< 0) + putchar(' '); + putchar('c'); } - fputs("|c|}\n\t\t", stdout); + + for (size_t i = 0; i < as.len; i++) + fputs("|c", stdout); + fputs("|}\n\t\t", stdout); for (int i = 0; i < MAXVARS; i++) { - if ((a.vars & UINT64_C(1)< 0;) printf("%s & ", boolsyms[bflag][(bool)(msk & UINT64_C(1)<ch) ? e->ch-'a'+26 : e->ch-'A'; for (int j = 0; j < bitnr; j++) i += (bool)(vars & UINT64_C(1)< IDENT -%type line exp +%type expr +%type line exprs %left OR %left AND @@ -46,34 +48,51 @@ extern const char *current_file; input: %empty | input line { - if ($2.eqn != NULL) + if ($2.len > 0) astprocess($2); } ; line: - EOL { $$.eqn = NULL; } - | exp eol { $$ = $1; } + EOL { $$.len = 0; } + | exprs eol { $$ = $1; } ; -eol: EOL | YYEOF; +exprs: + expr { + $$.len = 1; + $$.cap = 8; + $$.buf = xmalloc(sizeof(*$$.buf) * $$.cap); + $$.buf[0] = $1; + } + | exprs '|' expr { + $$ = $1; + if ($$.len == $$.cap) { + $$.cap *= 2; + $$.buf = xrealloc($$.buf, sizeof(*$$.buf) * $$.cap); + } + $$.buf[$$.len++] = $3; + } + ; -exp: +expr: IDENT { $$.eqn = xmalloc(sizeof(eqn_t)); $$.eqn->type = IDENT; $$.eqn->ch = $1; $$.vars = 1 << (islower($1) ? $1-'a'+26 : $1-'A'); } - | NOT exp { $$ = mkunop(NOT, $2); } - | OPAR exp CPAR { $$ = mkunop(OPAR, $2); } - | exp AND exp { $$ = mkbinop(AND, $1, $3); } - | exp OR exp { $$ = mkbinop(OR, $1, $3); } - | exp XOR exp { $$ = mkbinop(XOR, $1, $3); } - | exp IMPL exp { $$ = mkbinop(IMPL, $1, $3); } - | exp EQUIV exp { $$ = mkbinop(EQUIV, $1, $3); } + | NOT expr { $$ = mkunop(NOT, $2); } + | OPAR expr CPAR { $$ = mkunop(OPAR, $2); } + | expr AND expr { $$ = mkbinop(AND, $1, $3); } + | expr OR expr { $$ = mkbinop(OR, $1, $3); } + | expr XOR expr { $$ = mkbinop(XOR, $1, $3); } + | expr IMPL expr { $$ = mkbinop(IMPL, $1, $3); } + | expr EQUIV expr { $$ = mkbinop(EQUIV, $1, $3); } ; +eol: EOL | YYEOF; + %% ast_t @@ -101,15 +120,6 @@ mkbinop(int op, ast_t lhs, ast_t rhs) return a; } -void * -xmalloc(size_t n) -{ - void *p = malloc(n); - if (p == NULL) - err(1, "malloc"); - return p; -} - void yyerror(const char *s) { diff --git a/src/pinocchio.h b/src/pinocchio.h index fb74f3c..1a25672 100644 --- a/src/pinocchio.h +++ b/src/pinocchio.h @@ -19,7 +19,12 @@ typedef struct { uint64_t vars; } ast_t; -void astprocess(ast_t); +typedef struct { + size_t len, cap; + ast_t *buf; +} asts_t; + +void astprocess(asts_t); void user_error(const char *, ...) #if __GNUC__ __attribute__((format(printf, 1, 2))) diff --git a/src/wrapper.c b/src/wrapper.c new file mode 100644 index 0000000..16c6300 --- /dev/null +++ b/src/wrapper.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +void * +xmalloc(size_t n) +{ + void *p = malloc(n); + if (p == NULL) + err(1, "malloc"); + return p; +} + +void * +xrealloc(void *p, size_t n) +{ + if ((p = realloc(p, n)) == NULL) + err(1, "realloc"); + return p; +} + +bool +streq(const char *x, const char *y) +{ + return strcmp(x, y) == 0; +} diff --git a/src/wrapper.h b/src/wrapper.h new file mode 100644 index 0000000..a57f71e --- /dev/null +++ b/src/wrapper.h @@ -0,0 +1,11 @@ +#ifndef PINOCCHIO_WRAPPER_H +#define PINOCCHIO_WRAPPER_H + +#include +#include + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +bool streq(const char *, const char *); + +#endif /* !PINOCCHIO_WRAPPER_H */ -- cgit v1.2.3