blob: b5469591181f618174cc7a421b0cc7636cf52412 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
/**************************************************************/
/* treebnf: a tree oriented bnf library */
/* Copyright (C) 2024 SysDeer Technologies, LLC */
/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */
/**************************************************************/
#include <treebnf/treebnf.h>
#define TBNF_STATE_STACK_SIZE (512)
/* single token, read-only context */
int tbnf_scan_token(const struct tbnf_scan_ctx * sctx, struct tbnf_token * tok)
{
int ret = 0;
int len = 0;
int type = 0;
int tidx = 0;
int sidx = sctx->tok_scan_state;
for (; tidx < sctx->tok_scan_nents; ) {
if (sctx->tok_scan_tbls[sidx][tidx].tok_scan_fn)
ret = sctx->tok_scan_tbls[sidx][tidx].tok_scan_fn(sctx);
if (ret > len) {
len = ret;
type = tidx;
}
tidx++;
}
tok->tok_type = type;
tok->tok_len = len;
tok->tok_off = sctx->tok_scan_mark - sctx->tok_scan_base;
return (len > 0) ? 0 : -1;
}
/* scan up to ntoks tokens, read-write context */
int tbnf_scan_tokens(struct tbnf_scan_ctx * sctx, size_t ntoks, struct tbnf_token * tokv, int any)
{
int ret;
int * state;
int * stcap;
int ststk[TBNF_STATE_STACK_SIZE];
struct tbnf_scan_tbl * pentry;
ret = 0;
ntoks = (ntoks > INT32_MAX) ? INT32_MAX : ntoks;
state = ststk;
state[0] = sctx->tok_scan_state;
stcap = &state[TBNF_STATE_STACK_SIZE];
stcap--;
/*******************************************************************/
/* a positive return value that's smaller than the original ntoks, */
/* in combination with mark < cap, indicates an error while trying */
/* to obtain the next token. */
/*******************************************************************/
for (; ntoks && (sctx->tok_scan_mark < sctx->tok_scan_cap); ) {
if (tbnf_scan_token(sctx,tokv) < 0)
return (ret > 0) ? ret : (-1);
pentry = &sctx->tok_scan_tbls[*state][tokv->tok_type];
switch (pentry->tok_state_op) {
case TBNF_STATE_POP:
if (state == ststk)
return (-1);
state--;
sctx->tok_scan_state = *state;
break;
case TBNF_STATE_KEEP:
break;
case TBNF_STATE_PUSH:
if (state == stcap)
return (-1);
sctx->tok_scan_state = pentry->tok_state_next;
*++state = sctx->tok_scan_state;
break;
}
sctx->tok_scan_type = tokv->tok_type;
sctx->tok_scan_mark += tokv->tok_len;
tokv->tok_any = any;
tokv++;
ntoks--;
ret++;
}
return ret;
}
|