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