|
|
ae7810 |
/**************************************************************/
|
|
|
ae7810 |
/* treebnf: a tree oriented bnf library */
|
|
|
ae7810 |
/* Copyright (C) 2024 SysDeer Technologies, LLC */
|
|
|
ae7810 |
/* Released under GPLv2 and GPLv3; see COPYING.TREEBNF. */
|
|
|
ae7810 |
/**************************************************************/
|
|
|
ae7810 |
|
|
|
ae7810 |
#include <treebnf/treebnf.h>
|
|
|
ae7810 |
|
|
|
ae7810 |
#define TBNF_STATE_STACK_SIZE (512)
|
|
|
ae7810 |
|
|
|
ae7810 |
/* single token, read-only context */
|
|
|
ae7810 |
int tbnf_scan_token(const struct tbnf_scan_ctx * sctx, struct tbnf_token * tok)
|
|
|
ae7810 |
{
|
|
|
ae7810 |
int ret = 0;
|
|
|
ae7810 |
int len = 0;
|
|
|
ae7810 |
int type = 0;
|
|
|
ae7810 |
|
|
|
ae7810 |
int tidx = 0;
|
|
|
ae7810 |
int sidx = sctx->tok_scan_state;
|
|
|
ae7810 |
|
|
|
ae7810 |
for (; tidx < sctx->tok_scan_nents; ) {
|
|
|
ae7810 |
if (sctx->tok_scan_tbls[sidx][tidx].tok_scan_fn)
|
|
|
ae7810 |
ret = sctx->tok_scan_tbls[sidx][tidx].tok_scan_fn(sctx);
|
|
|
ae7810 |
|
|
|
ae7810 |
if (ret > len) {
|
|
|
ae7810 |
len = ret;
|
|
|
ae7810 |
type = tidx;
|
|
|
ae7810 |
}
|
|
|
ae7810 |
|
|
|
ae7810 |
tidx++;
|
|
|
ae7810 |
}
|
|
|
ae7810 |
|
|
|
ae7810 |
tok->tok_type = type;
|
|
|
ae7810 |
tok->tok_len = len;
|
|
|
ae7810 |
tok->tok_off = sctx->tok_scan_mark - sctx->tok_scan_base;
|
|
|
ae7810 |
|
|
|
ae7810 |
return (len > 0) ? 0 : -1;
|
|
|
ae7810 |
}
|
|
|
ae7810 |
|
|
|
ae7810 |
/* scan up to ntoks tokens, read-write context */
|
|
|
ae7810 |
int tbnf_scan_tokens(struct tbnf_scan_ctx * sctx, size_t ntoks, struct tbnf_token * tokv, int any)
|
|
|
ae7810 |
{
|
|
|
ae7810 |
int ret;
|
|
|
ae7810 |
int * state;
|
|
|
ae7810 |
int * stcap;
|
|
|
ae7810 |
int ststk[TBNF_STATE_STACK_SIZE];
|
|
|
ae7810 |
struct tbnf_scan_tbl * pentry;
|
|
|
ae7810 |
|
|
|
ae7810 |
ret = 0;
|
|
|
ae7810 |
ntoks = (ntoks > INT32_MAX) ? INT32_MAX : ntoks;
|
|
|
ae7810 |
|
|
|
ae7810 |
state = ststk;
|
|
|
ae7810 |
state[0] = sctx->tok_scan_state;
|
|
|
ae7810 |
|
|
|
ae7810 |
stcap = &state[TBNF_STATE_STACK_SIZE];
|
|
|
ae7810 |
stcap--;
|
|
|
ae7810 |
|
|
|
ae7810 |
/*******************************************************************/
|
|
|
ae7810 |
/* a positive return value that's smaller than the original ntoks, */
|
|
|
ae7810 |
/* in combination with mark < cap, indicates an error while trying */
|
|
|
ae7810 |
/* to obtain the next token. */
|
|
|
ae7810 |
/*******************************************************************/
|
|
|
ae7810 |
|
|
|
ae7810 |
for (; ntoks && (sctx->tok_scan_mark < sctx->tok_scan_cap); ) {
|
|
|
ae7810 |
if (tbnf_scan_token(sctx,tokv) < 0)
|
|
|
ae7810 |
return (ret > 0) ? ret : (-1);
|
|
|
ae7810 |
|
|
|
ae7810 |
pentry = &sctx->tok_scan_tbls[*state][tokv->tok_type];
|
|
|
ae7810 |
|
|
|
ae7810 |
switch (pentry->tok_state_op) {
|
|
|
ae7810 |
case TBNF_STATE_POP:
|
|
|
ae7810 |
if (state == ststk)
|
|
|
ae7810 |
return (-1);
|
|
|
ae7810 |
|
|
|
ae7810 |
state--;
|
|
|
ae7810 |
sctx->tok_scan_state = *state;
|
|
|
ae7810 |
break;
|
|
|
ae7810 |
|
|
|
ae7810 |
case TBNF_STATE_KEEP:
|
|
|
ae7810 |
break;
|
|
|
ae7810 |
|
|
|
ae7810 |
case TBNF_STATE_PUSH:
|
|
|
ae7810 |
if (state == stcap)
|
|
|
ae7810 |
return (-1);
|
|
|
ae7810 |
|
|
|
ae7810 |
sctx->tok_scan_state = pentry->tok_state_next;
|
|
|
ae7810 |
*++state = sctx->tok_scan_state;
|
|
|
ae7810 |
break;
|
|
|
ae7810 |
}
|
|
|
ae7810 |
|
|
|
ae7810 |
sctx->tok_scan_type = tokv->tok_type;
|
|
|
ae7810 |
sctx->tok_scan_mark += tokv->tok_len;
|
|
|
ae7810 |
|
|
|
ae7810 |
tokv->tok_any = any;
|
|
|
ae7810 |
tokv++;
|
|
|
ae7810 |
|
|
|
ae7810 |
ntoks--;
|
|
|
ae7810 |
ret++;
|
|
|
ae7810 |
}
|
|
|
ae7810 |
|
|
|
ae7810 |
return ret;
|
|
|
ae7810 |
}
|