cons, allows automation of pop; <!condition>
This commit is contained in:
parent
fb814b7223
commit
3dd4557438
@ -6,9 +6,10 @@ int lex_looks_like_day(const char *);
|
||||
|
||||
#define LEX_SYMBOL \
|
||||
/* Results. */ X(END), X(SYNTAX), X(ILLEGAL), X(NOT_FOUND), \
|
||||
/* Text */ X(PARAGRAPH), X(TEXT), \
|
||||
/* Directive. */ X(SOURCE), X(DEFAULT), X(SIGNIFICANT), X(SCORE), X(MAP), \
|
||||
/* Arguments. */ X(ARG_KEYWORD), X(ARG_DATE), X(ARG_NATURAL), X(ARG_FREEFORM)
|
||||
/* Text. */ X(PARAGRAPH), X(TEXT), \
|
||||
/* Edicts. */ X(SOURCE), X(DEFAULT), X(SIGNIFICANT), X(SCORE), X(MAP), \
|
||||
/* Arguments. */ X(ARG_KEYWORD), X(ARG_DATE), X(ARG_NATURAL), \
|
||||
X(ARG_FREEFORM)
|
||||
|
||||
#define X(n) n
|
||||
struct lex {
|
||||
|
@ -20,7 +20,7 @@ re2c:define:YYCTYPE = char;
|
||||
int lex_looks_like_year(const char *const a, int *const year) {
|
||||
const char *YYCURSOR = a, *YYMARKER = a, *s0;
|
||||
/*!stags:re2c format = 'const char *@@;\n'; */
|
||||
(void)yyt1;
|
||||
(void)yyt2, (void)yyt3;
|
||||
assert(a && year);
|
||||
/*!re2c
|
||||
@s0 ("-"? [1-9][0-9]* | "0") "\x00" {
|
||||
@ -41,6 +41,7 @@ int lex_looks_like_year(const char *const a, int *const year) {
|
||||
int lex_looks_like_month(const char *const a) {
|
||||
const char *YYCURSOR = a, *YYMARKER = a, *s0;
|
||||
/*!stags:re2c format = 'const char *@@;\n'; */
|
||||
(void)yyt1, (void)yyt2, (void)yyt3;
|
||||
assert(a);
|
||||
/*!re2c
|
||||
@s0 [0-1][0-9] "\x00" {
|
||||
@ -54,6 +55,7 @@ int lex_looks_like_month(const char *const a) {
|
||||
int lex_looks_like_day(const char *const a) {
|
||||
const char *YYCURSOR = a, *YYMARKER = a, *s0;
|
||||
/*!stags:re2c format = 'const char *@@;\n'; */
|
||||
(void)yyt1, (void)yyt2, (void)yyt3;
|
||||
assert(a);
|
||||
/*!re2c
|
||||
@s0 [0-3][0-9] ".txt\x00" {
|
||||
@ -67,7 +69,12 @@ int lex_looks_like_day(const char *const a) {
|
||||
/* This defines `enum condition`. */
|
||||
/*!types:re2c*/
|
||||
|
||||
#define EXPECT X(KEYWORD), X(DATE), X(FREEFORM)
|
||||
/* "[edict: expect; there; to; be; args]", 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 <fn:lex_next> and <fn:expect_pop>. */
|
||||
#define EXPECT_HEAD X(keyword, KEYWORD) X(date, DATE)
|
||||
#define EXPECT_CONS Y(freeform, FREEFORM)
|
||||
#define EXPECT EXPECT_HEAD EXPECT_CONS
|
||||
|
||||
/** scanner reads a file and extracts semantic information. Valid to access
|
||||
only while underlying pointers do not change. */
|
||||
@ -79,29 +86,31 @@ static struct scan {
|
||||
enum condition condition;
|
||||
size_t line;
|
||||
int is_ws_expected, is_source;
|
||||
#define X(n) EXPECT_ ## n
|
||||
/* "[something: expect; there; to; be; args]", in this case, expect would
|
||||
be a stack of `size = 5` `EXPECT_KEYWORD`. */
|
||||
#define X(n, N) EXPECT_ ## N,
|
||||
#define Y(n, N) EXPECT_ ## N
|
||||
struct { unsigned size; enum { EXPECT } expect[16]; } edict;
|
||||
#undef X
|
||||
} scan; /* Terrible, gah. */
|
||||
#undef Y
|
||||
} scan; /* Not suited for concurrency. Simple. */
|
||||
|
||||
/** 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;
|
||||
scan.condition = 0;
|
||||
scan.condition = yycline;
|
||||
scan.line = 1;
|
||||
}
|
||||
|
||||
/** I don't think `re2c` supports branching on variable conditions.
|
||||
It does now? */
|
||||
static void expect_pop(void) {
|
||||
printf("<expect_pop>");
|
||||
if(!scan.edict.size) { printf("allfinished\n"); scan.condition = yycedict_end; return; }
|
||||
if(!scan.edict.size) { scan.condition = yycedict_end; return; }
|
||||
switch(scan.edict.expect[--scan.edict.size]) {
|
||||
case EXPECT_KEYWORD: printf("keyword\n");scan.condition = yycedict_keyword; break;
|
||||
case EXPECT_DATE: printf("date\n");scan.condition = yycedict_date; break;
|
||||
case EXPECT_FREEFORM: printf("freeform\n");scan.condition = yycedict_freeform; break;
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,14 +127,10 @@ int lex_next(struct lex *const x) {
|
||||
re2c:define:YYSETCONDITION:naked = 1;
|
||||
*/
|
||||
const char *s0, *s1;
|
||||
const size_t prev_line = scan.line;
|
||||
/*!stags:re2c format = 'const char *@@;\n'; */
|
||||
assert(x);
|
||||
if(!scan.buffer) return 0;
|
||||
x->s0 = x->s1 = 0;
|
||||
x->line = prev_line;
|
||||
x->ws_before = 0;
|
||||
x->new_paragraph = 0;
|
||||
scan:
|
||||
/*!re2c
|
||||
end = "\x00";
|
||||
@ -196,16 +201,17 @@ scan:
|
||||
{ if(!scan.edict.size) return x->symbol = SYNTAX, 0;
|
||||
scan.is_ws_expected = 0, scan.is_source = 0;
|
||||
expect_pop(); goto scan; }
|
||||
<! edict_keyword, edict_date, edict_freeform> { expect_pop(); }
|
||||
<edict_keyword> ws* @s0 id @s1 ws* ";"? / "]"?
|
||||
{ x->s0 = s0, x->s1 = s1; expect_pop();
|
||||
{ x->s0 = s0, x->s1 = s1;
|
||||
return x->symbol = ARG_KEYWORD, 1; }
|
||||
<edict_date> ws* @s0 date @s1 ws* ";"? / "]"?
|
||||
{ x->s0 = s0, x->s1 = s1; expect_pop();
|
||||
{ x->s0 = s0, x->s1 = s1;
|
||||
return x->symbol = ARG_DATE, 1; }
|
||||
<edict_freeform> ws* @s0
|
||||
[^ \t\n\r\v\f;[\]\x00][^\t\n\r\v\f;[\]\x00]*[^ \t\n\r\v\f;[\]\x00]*
|
||||
@s1 ws* ";"? / "]"?
|
||||
{ x->s0 = s0, x->s1 = s1; expect_pop();
|
||||
{ x->s0 = s0, x->s1 = s1;
|
||||
return x->symbol = ARG_FREEFORM, 1; }
|
||||
<edict, edict_end> "]" => text
|
||||
{ if(scan.edict.size) return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user