From a75385f71a14c07ae3a2e3e395dfcf7047a5fb48 Mon Sep 17 00:00:00 2001 From: Neil Date: Mon, 14 Feb 2022 22:02:32 -0800 Subject: [PATCH] More complex; read args in commands. --- src/interpret.c | 6 ++-- src/lex.h | 3 +- src/lex.re_c.c | 89 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/interpret.c b/src/interpret.c index d1ea689..c7d6f15 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -135,10 +135,12 @@ int main(int argc, char **argv) { while(lex_next(&lex)) { printf("%lu: %s", (unsigned long)lex.line, lex_symbols[lex.symbol]); - if(lex.symbol == TEXT) { + if(lex.symbol == TEXT || lex.symbol == ARG_KEYWORD + || lex.symbol == ARG_DATE + || lex.symbol == ARG_FREEFORM) { if(lex.s0 + INT_MAX < lex.s1) { errno = EILSEQ; goto catch; } - printf(" %.*s", (int)(lex.s1 - lex.s0), lex.s0); + printf(" <<%.*s>>", (int)(lex.s1 - lex.s0), lex.s0); } printf(".\n"); } diff --git a/src/lex.h b/src/lex.h index 4c1d01f..ab82088 100644 --- a/src/lex.h +++ b/src/lex.h @@ -6,7 +6,8 @@ int lex_looks_like_day(const char *); #define LEX_SYMBOL X(END), X(ERROR), X(TEXT), X(BANG), X(BRACKET), X(WHITE), \ X(MAP), \ - /* Commands */ X(SIGNIFICANT), X(DEFAULT), X(SOURCE) + /* Commands */ X(SOURCE), X(DEFAULT), X(SIGNIFICANT), X(SCORE), \ + /* Arguments */ X(ARG_KEYWORD), X(ARG_DATE), X(ARG_NATURAL), X(ARG_FREEFORM) #define X(n) n struct lex { diff --git a/src/lex.re_c.c b/src/lex.re_c.c index 6b863cb..f7d882f 100644 --- a/src/lex.re_c.c +++ b/src/lex.re_c.c @@ -66,6 +66,8 @@ int lex_looks_like_day(const char *const a) { /* This defines `enum condition`. */ /*!types:re2c*/ +#define EXPECT X(KEYWORD), X(DATE), X(FREEFORM) + /** scanner reads a file and extracts semantic information. Valid to access only while underlying pointers do not change. */ static struct scan { @@ -75,7 +77,12 @@ static struct scan { const char *label, *buffer; enum condition condition; size_t line; - int is_ws_expected; + int is_ws_expected, is_source; +#define X(n) EXPECT_ ## n + /* "[something: expect; there; to; be; args]", in this case, `size = 5` and + expect would be 5 `EXPECT_KEYWORD`. */ + struct { unsigned size; enum { EXPECT } expect[20]; } command; +#undef X } scan; /* Terrible, gah. */ void lex_reset(const char *const buffer) { @@ -108,8 +115,19 @@ glyphs = glyph+; natural = [1-9][0-9]*; decimal = "-"? ([1-9][0-9]* | [0])? "." [0-9]+ | [1-9][0-9]* | [0]; id = [a-zA-Z_][a-zA-Z_\-0-9]{0,63}; +date = "-"? natural "-" [0-1][0-9] "-" [0-1][0-9]; */ +static void expect_pop(void) { + printf(""); + if(!scan.command.size) { printf("nostack\n"); scan.condition = yyccommand_end; return; } + switch(scan.command.expect[--scan.command.size]) { + case EXPECT_KEYWORD: printf("keyword\n");scan.condition = yyccommand_keyword; break; + case EXPECT_DATE: printf("date\n");scan.condition = yyccommand_date; break; + case EXPECT_FREEFORM: printf("freeform\n");scan.condition = yyccommand_freeform; break; + } +} + int lex_next(struct lex *const x) { const char *s0, *s1; const size_t prev_line = scan.line; @@ -123,7 +141,8 @@ int lex_next(struct lex *const x) { scan: /*!re2c end { printf("end\n");return x->symbol = END, 0; } - end { return x->symbol = ERROR, 0; } + end + { return x->symbol = ERROR, 0; } newline { x->line = ++scan.line; @@ -147,20 +166,58 @@ scan: } * { printf("image(broken)\n");return 0; } - ws+ { scan.is_ws_expected = 0; goto scan; } - @s0 natural @s1 - { if(scan.is_ws_expected) return x->symbol = ERROR, 0; - return x->symbol = SIGNIFICANT, scan.is_ws_expected = 1, - x->s0 = s0, x->s1 = s1, 1; } + // source "source" - { if(scan.is_ws_expected) return x->symbol = ERROR, 0; - return scan.is_ws_expected = 1, x->symbol = SOURCE, 1; } + { if(scan.is_ws_expected || scan.command.size) + return x->symbol = ERROR, 0; + scan.is_ws_expected = 1, scan.is_source = 1; + scan.command.size = 2; + scan.command.expect[1] = EXPECT_KEYWORD; + scan.command.expect[0] = EXPECT_FREEFORM; + return x->symbol = SOURCE, 1; } "default" - { if(scan.is_ws_expected) return x->symbol = ERROR, 0; - return scan.is_ws_expected = 1, x->symbol = DEFAULT, 1; } - ":" => command_args { scan.is_ws_expected = 0; goto scan; } - [^\n\r\]\x00]+ { printf("Command args fixme\n"); goto scan; } - "]" :=> text - * { return x->symbol = ERROR, 0; } - */ + { if(scan.is_ws_expected || !scan.is_source) + return x->symbol = ERROR, 0; + scan.is_ws_expected = 1, scan.is_source = 0; + return x->symbol = DEFAULT, 1; } + + // score + "significant" + { if(scan.is_ws_expected || scan.command.size) + return x->symbol = ERROR, 0; + scan.is_ws_expected = 1; + scan.command.size = 2; + scan.command.expect[1] = EXPECT_FREEFORM; + scan.command.expect[0] = EXPECT_DATE; + return x->symbol = SIGNIFICANT, 1; } + @s0 natural @s1 + { if(scan.is_ws_expected || scan.command.size) + return x->symbol = ERROR, 0; + scan.is_ws_expected = 1; + x->s0 = s0, x->s1 = s1; + return x->symbol = SCORE, 1; } + + // general command stuff + ws+ { scan.is_ws_expected = 0; goto scan; } + ":" + { if(!scan.command.size) return x->symbol = ERROR, 0; + scan.is_ws_expected = 0, scan.is_source = 0; + expect_pop(); goto scan; } + ws* @s0 id @s1 ws* ";"? / "]"? + { x->s0 = s0, x->s1 = s1; expect_pop(); + return x->symbol = ARG_KEYWORD, 1; } + ws* @s0 date @s1 ws* ";"? / "]"? + { x->s0 = s0, x->s1 = s1; expect_pop(); + return x->symbol = ARG_DATE, 1; } + ws* @s0 [^\t\n\r\v\f;[\]\x00]* @s1 ws* ";"? / "]"? + { x->s0 = s0, x->s1 = s1; expect_pop(); + return x->symbol = ARG_FREEFORM, 1; } + "]" => text + { printf("]\n"); if(scan.command.size) { printf("huh?\n"); return 0; } + goto scan; + } + * + { return x->symbol = ERROR, 0; } + */ + assert(0); }