diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-09-04 12:25:04 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-09-04 12:25:04 +0200 |
commit | a65336ea79935dfbf3006e775dd16a15f5ef1bd8 (patch) | |
tree | 2b346b317079ce797efd825da98bfc8c0e45fc84 | |
parent | 0d5f7878b54042a11efc34d75761b87e43d20792 (diff) |
Support LaTeX output
-rw-r--r-- | src/main.c | 85 | ||||
-rw-r--r-- | src/parser.y | 6 | ||||
-rw-r--r-- | src/pinocchio.h | 3 |
3 files changed, 81 insertions, 13 deletions
@@ -1,6 +1,8 @@ #include <ctype.h> #include <err.h> +#include <getopt.h> #include <langinfo.h> +#include <libgen.h> #include <locale.h> #include <stdarg.h> #include <stdbool.h> @@ -22,6 +24,7 @@ static int rv; static bool interactive, utf8; +bool lflag; const char *current_file; static bool eqnsolve(eqn_t *, uint64_t, uint64_t); @@ -44,28 +47,48 @@ popcnt(uint64_t n) int main(int argc, char **argv) { + argv[0] = basename(argv[0]); setlocale(LC_ALL, ""); utf8 = strcmp(nl_langinfo(CODESET), "UTF-8") == 0; interactive = isatty(STDIN_FILENO); - if (argc == 1) { + int opt; + static struct option longopts[] = { + {"latex", no_argument, 0, 'l'}, + {0}, + }; + + while ((opt = getopt_long(argc, argv, "l", longopts, NULL)) != -1) { + switch (opt) { + case 'l': + lflag = true; + break; + default: + fprintf(stderr, "Usage: %s [-l] [file ...]\n", argv[0]); + exit(EXIT_FAILURE); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) { current_file = "-"; for (;;) { - int ret = yyparse(); - if (ret == 0) + if (yyparse() == 0) break; rv = EXIT_FAILURE; } - } else for (int i = 1; i < argc; i++) { + } else for (int i = 0; i < argc; i++) { if (strcmp(argv[i], "-") == 0) yyin = stdin; else if ((yyin = fopen(argv[i], "r")) == NULL) { - warn("fopen: %s", argv[1]); + warn("fopen: %s", argv[i]); rv = EXIT_FAILURE; continue; } - current_file = argv[1]; + current_file = argv[i]; yyparse(); fclose(yyin); } @@ -74,11 +97,8 @@ main(int argc, char **argv) } void -astprocess(ast_t a) +astprocess_cli(ast_t a) { - if (a.eqn == NULL) - return; - enum { TBLVBAR, TBLHBAR, @@ -127,6 +147,38 @@ astprocess(ast_t a) eqnfree(a.eqn); } +void +astprocess_latex(ast_t a) +{ + fputs("\\begin{displaymath}\n\t\\begin{array}{|", stdout); + int varcnt = popcnt(a.vars); + for (int i = 0; i < varcnt; i++) { + if (i == 0) + putchar('c'); + else + fputs(" c", stdout); + } + fputs("|c|}\n\t\t", stdout); + + for (int i = 0; i < MAXVARS; i++) { + if ((a.vars & UINT64_C(1)<<i) != 0) + printf("%c & ", i < 26 ? i + 'A' : i + 'a' - 26); + } + + (void)eqnprint(a.eqn); + puts("\\\\\n\t\t\\hline"); + + for (uint64_t msk = 0; msk < (UINT64_C(1) << varcnt); msk++) { + fputs("\t\t", stdout); + for (int i = varcnt; i --> 0;) + printf("%d & ", (bool)(msk & UINT64_C(1)<<i)); + printf("%d\\\\\n", eqnsolve(a.eqn, a.vars, msk)); + } + + puts("\t\\end{array}\n\\end{displaymath}"); + + eqnfree(a.eqn); +} bool eqnsolve(eqn_t *e, uint64_t vars, uint64_t msk) @@ -185,8 +237,19 @@ eqnprint(eqn_t *a) [IMPL - NOT] = {"=>", 2}, [EQUIV - NOT] = {"<=>", 3}, }; + static const sym_t symbols_latex[] = { + [NOT - NOT] = {"\\lnot ", -1}, + [OR - NOT] = {"\\lor", -1}, + [AND - NOT] = {"\\land", -1}, + [XOR - NOT] = {"\\oplus", -1}, + [IMPL - NOT] = {"\\implies", -1}, + [EQUIV - NOT] = {"\\iff", -1}, + }; - const sym_t *symtab = utf8 ? symbols_utf8 : symbols_ascii; + const sym_t *symtab + = lflag ? symbols_latex + : utf8 ? symbols_utf8 + : symbols_ascii; switch (a->type) { case IDENT: diff --git a/src/parser.y b/src/parser.y index 5a4c409..d7e8168 100644 --- a/src/parser.y +++ b/src/parser.y @@ -11,6 +11,7 @@ static ast_t astmerge(int, ast_t, ast_t); static void *xmalloc(size_t); static void yyerror(const char *); +extern bool lflag; extern const char *current_file; %} @@ -44,7 +45,10 @@ extern const char *current_file; input : %empty - | input line { astprocess($2); } + | input line { + if ($2.eqn != NULL) + (lflag ? astprocess_latex : astprocess_cli)($2); + } ; line diff --git a/src/pinocchio.h b/src/pinocchio.h index fb74f3c..51e4dd5 100644 --- a/src/pinocchio.h +++ b/src/pinocchio.h @@ -19,7 +19,8 @@ typedef struct { uint64_t vars; } ast_t; -void astprocess(ast_t); +void astprocess_cli(ast_t); +void astprocess_latex(ast_t); void user_error(const char *, ...) #if __GNUC__ __attribute__((format(printf, 1, 2))) |