diff --git a/Makefile b/Makefile index 768f5bc..f315391 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ else CF += -g endif -projects := bin/test-text bin/test-kjv bin/test-journal +projects := bin/test-text bin/test-kjv bin/test-journal bin/interpret #docs := $(patsubst test/test_%.c, doc/%.md, $(wildcard test/test_*.c)) default: $(projects) @@ -38,29 +38,29 @@ default: $(projects) bin/test-text: build/test_text.o build/text.o bin/test-kjv: build/test_kjv.o build/text.o build/kjv.o bin/test-journal: build/test_journal.o build/text.o build/journal.o -# and h +bin/interpret: build/interpret.o build/scan.o build/journal.o build/kjv.o build/text.o bin/%: - # linking test $@ + @echo "\033[1;36mlinking $@\033[0m" @mkdir -p bin $(CC) $(OF) -o $@ $^ -build/%.o: src/%.c - # compile src $@ +build/%.o: src/%.c src/%.h + @echo "\033[0;36mcompile src $@\033[0m" @mkdir -p build $(CC) $(CF) -c -o $@ $< build/%.o: test/%.c - # compile test $@ + @echo "\033[0;36mcompile test $@\033[0m" @mkdir -p build $(CC) $(CF) -c -o $@ $< -build/%.o: build/%.c - # compile generated $@ +build/%.o: build/%.c src/%.h + @echo "\033[0;36mcompile generated $@\033[0m" $(CC) $(CF) -c -o $@ $< build/%.c: src/%.re.c - # https://re2c.org/ generate $@ + @echo "\033[0;34mhttps://re2c.org/ generate $@\033[0m" @mkdir -p build re2c -W --tags --conditions -o $@ $< @@ -68,7 +68,7 @@ build/%.c: src/%.re.c # # https://github.com/neil-edelman/cdoc documentation # -cdoc -o $@ $< -.SECONDARY: build/kjv.c build/journal.c +.SECONDARY: build/kjv.c build/journal.c build/scan.c .PHONY: clean release test test: $(projects) diff --git a/src/lex.h b/src/scan.h similarity index 79% rename from src/lex.h rename to src/scan.h index e21b74c..06ebde9 100644 --- a/src/lex.h +++ b/src/scan.h @@ -1,4 +1,4 @@ -#include +#include "journal.h" int lex_looks_like_year(const char *, int *); int lex_looks_like_month(const char *); @@ -46,7 +46,16 @@ int lex_looks_like_day(const char *); X(KJV_TEXT, &word_vt), \ X(KJV_NEXT, 0) +int scan(union date32 date, const char *const buffer); +#if 0 + +struct scan { + const char *marker, *from, *cursor, *limit, *label, *buffer; + int condition; + size_t line; + int is_ws_expected; +}; struct lex { size_t line; @@ -59,5 +68,7 @@ struct lex { static const char *const lex_symbols[] = { FOR_SYMBOL(STR1) }; #undef X -void lex_reset(const char *const buffer); -int lex_next(struct lex *); +struct scan scan(const char *); +int scan_next(struct scan *const s, struct lex *const x); + +#endif diff --git a/src/lex.re.c b/src/scan.re.c similarity index 63% rename from src/lex.re.c rename to src/scan.re.c index 2ed0a3f..56a6e35 100644 --- a/src/lex.re.c +++ b/src/scan.re.c @@ -10,7 +10,7 @@ @std C89/90 */ -#include "../src/lex.h" +#include "../src/scan.h" #include #include #include @@ -20,64 +20,42 @@ /* This defines `enum condition`. */ /*!types:re2c*/ -/* In this case, expect - would be a stack of `size = 5` `EXPECT_KEYWORD`. This mirrors arguments in - `LEX_SYMBOL` and should also be an `edict_*` in and - . */ -#define EXPECT_HEAD X(keyword, KEYWORD) X(date, DATE) X(natural, NATURAL) \ - X(restrict_text, RESTRICT_TEXT) -#define EXPECT_CONS Y(end_text, END_TEXT) -#define EXPECT EXPECT_HEAD EXPECT_CONS +int scan(union date32 date, const char *const buffer) { + const char *YYCURSOR = buffer; + /*!re2c /**/ + re2c:define:YYCTYPE = char; + re2c:yyfill:enable = 0; + */ +} -/** Scan reads one file as a time and extracts semantic information. Valid to - access only while underlying pointers do not change. This is a singleton, not - concurrent: convenient and bad. */ -static struct scan { - /* `re2c` variables; these point directly into `buffer`. */ - const char *marker, /**ctx_marker,*/ *from, *cursor; - /* Weird `c2re` stuff: these fields have to come after when >5? */ - const char *label, *buffer; - enum condition condition; - size_t line; - int is_ws_expected, is_source; -#define X(n, N) EXPECT_ ## N, -#define Y(n, N) EXPECT_ ## N - struct { unsigned size; enum { EXPECT } expect[16]; } edict; -#undef X -#undef Y -} scan; -/** Resets the buffer to some `buffer`. */ -void lex_reset(const char *const buffer) { - scan.marker = /*scan.ctx_marker =*/ scan.from = scan.cursor = scan.label - = scan.buffer = buffer; + + + + + + +#if 0 + +struct scan scan(const char *const buffer) { + struct scan scan; + scan.marker = scan.from = scan.cursor = scan.label = scan.buffer = buffer; scan.condition = yycline; scan.line = 1; + return scan; } -/** I don't think `re2c` supports branching on variable conditions. - It does now? */ -static void expect_pop(void) { - if(!scan.edict.size) { scan.condition = yycedict_end; return; } - switch(scan.edict.expect[--scan.edict.size]) { -#define X(n, N) case EXPECT_ ## N : scan.condition = yycedict_ ## n; break; -#define Y(n, N) case EXPECT_ ## N : scan.condition = yycedict_ ## n; break; - EXPECT -#undef X -#undef Y - } -} - -int lex_next(struct lex *const x) { +int scan_next(struct scan *const s, struct lex *const x) { /*!re2c /**/ re2c:flags:tags = 1; - re2c:define:YYCURSOR = scan.cursor; - re2c:define:YYMARKER = scan.marker; - /*re2c:define:YYCTXMARKER = scan.ctx_marker;*/ + re2c:define:YYCTYPE = char; + re2c:yyfill:enable = 0; + re2c:define:YYCURSOR = s->cursor; + re2c:define:YYMARKER = s->marker; re2c:define:YYCONDTYPE = 'condition'; - re2c:define:YYGETCONDITION = 'scan.condition'; + re2c:define:YYGETCONDITION = 's->condition'; re2c:define:YYGETCONDITION:naked = 1; - re2c:define:YYSETCONDITION = 'scan.condition = @@;'; + re2c:define:YYSETCONDITION = 's->condition = @@;'; re2c:define:YYSETCONDITION:naked = 1; sentinel = "\x00"; newline = "\n"; @@ -91,28 +69,28 @@ int lex_next(struct lex *const x) { */ const char *s0, *s1; /*!stags:re2c format = 'const char *@@;\n'; */ - assert(x); - if(!scan.buffer) return 0; - x->line = scan.line; + assert(s && x); + if(!s->buffer) return 0; + x->line = s->line; x->s0 = x->s1 = 0; scan: /*!re2c /**/ <*> unix_control { return x->symbol = ILLEGAL, 0; } <*> * { return x->symbol = SYNTAX, 0; } <*> sentinel /* New line always delimits. */ - { return x->symbol = scan.condition == yycline ? END : ILLEGAL, 0; } - newline => line { x->line = ++scan.line; goto scan; } + { return x->symbol = s->condition == yycline ? END : ILLEGAL, 0; } + newline => line { x->line = ++s->line; goto scan; } /* Symbols that go at the beginning of a line. */ - newline { x->line = ++scan.line; goto scan; } + newline { x->line = ++s->line; goto scan; } "[" :=> edict "--" :=> source "->" :=> location - * :=> text "!" => text { return x->symbol = COMPLETE, 1; } "^" => text { return x->symbol = CANCELLED, 1; } "#" => text { return x->symbol = HEADING, 1; } + * :=> text - newline => line { x->line = ++scan.line; goto scan; } + newline => line { x->line = ++s->line; goto scan; } ws+ { goto scan; } @s0 glyph+ @s1 { x->s0 = s0, x->s1 = s1; return x->symbol = TEXT, 1; } @@ -144,7 +122,7 @@ scan: { x->s0 = s0, x->s1 = s1; return x->symbol = KJV_TEXT, 1; } /* Multiple verses can be present, but they end in ''. Not strictly enforced. */ - newline / (newline | "``") { x->line = ++scan.line; goto scan; } + newline / (newline | "``") { x->line = ++s->line; goto scan; } newline { return x->symbol = SYNTAX, 0; } @s0 keyword @s1 => expect_line @@ -180,50 +158,50 @@ scan: /* How did it get into my journal? */ "source" - { if(scan.is_ws_expected || scan.edict.size) + { if(s->is_ws_expected || s->edict.size) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 1, scan.is_source = 1; - scan.edict.size = 2; - scan.edict.expect[1] = EXPECT_KEYWORD; - scan.edict.expect[0] = EXPECT_END_TEXT; + s->is_ws_expected = 1, s->is_source = 1; + s->edict.size = 2; + s->edict.expect[1] = EXPECT_KEYWORD; + s->edict.expect[0] = EXPECT_END_TEXT; return x->symbol = SOURCE, 1; } "default" - { if(scan.is_ws_expected || !scan.is_source) + { if(s->is_ws_expected || !s->is_source) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 1, scan.is_source = 0; + s->is_ws_expected = 1, s->is_source = 0; return x->symbol = DEFAULT, 1; } /* Editorializing; looking back. */ "ed" - { if(scan.is_ws_expected || scan.edict.size) + { if(s->is_ws_expected || s->edict.size) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 1; /* no idea, just copy; probably should do sth */ - scan.edict.size = 1; - scan.edict.expect[0] = EXPECT_END_TEXT; /* Pithy comment. */ + s->is_ws_expected = 1; /* no idea, just copy; probably should do sth */ + s->edict.size = 1; + s->edict.expect[0] = EXPECT_END_TEXT; /* Pithy comment. */ return x->symbol = EDITORIALIZING, 1; } /* Score. */ "significant" - { if(scan.is_ws_expected || scan.edict.size) + { if(s->is_ws_expected || s->edict.size) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 1; - scan.edict.size = 3; - scan.edict.expect[2] = EXPECT_NATURAL; /* Ordinal. */ - scan.edict.expect[1] = EXPECT_RESTRICT_TEXT; /* Name. */ - scan.edict.expect[0] = EXPECT_DATE; /* Birthday. */ + s->is_ws_expected = 1; + s->edict.size = 3; + s->edict.expect[2] = EXPECT_NATURAL; /* Ordinal. */ + s->edict.expect[1] = EXPECT_RESTRICT_TEXT; /* Name. */ + s->edict.expect[0] = EXPECT_DATE; /* Birthday. */ return x->symbol = SIGNIFICANT, 1; } @s0 natural @s1 - { if(scan.is_ws_expected || scan.edict.size) + { if(s->is_ws_expected || s->edict.size) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 1; + s->is_ws_expected = 1; x->s0 = s0, x->s1 = s1; return x->symbol = SIGNIFICANT_RECALL, 1; } /* General [edict: whatever]. */ - ws+ { scan.is_ws_expected = 0; goto scan; } + ws+ { s->is_ws_expected = 0; goto scan; } ":" - { if(!scan.edict.size) return x->symbol = SYNTAX, 0; - scan.is_ws_expected = 0, scan.is_source = 0; + { if(!s->edict.size) return x->symbol = SYNTAX, 0; + s->is_ws_expected = 0, s->is_source = 0; expect_pop(); goto scan; } ws* @s0 keyword @s1 ws* ";"? { x->s0 = s0, x->s1 = s1; expect_pop(); @@ -243,6 +221,8 @@ scan: { x->s0 = s0, x->s1 = s1; expect_pop(); return x->symbol = ARG_END_TEXT, 1; } "]" => expect_line - { if(scan.edict.size) return 0; goto scan; } + { if(s->edict.size) return 0; goto scan; } */ } + +#endif diff --git a/test/interpret.c b/test/interpret.c new file mode 100644 index 0000000..b2de962 --- /dev/null +++ b/test/interpret.c @@ -0,0 +1,8 @@ +#include +#include +#include +#include + +int main(void) { + return EXIT_SUCCESS; +}