commit e3cbf911592479fbaa8b6f9edaf54328d9cee629 from: Sven M. Hallberg date: Mon May 11 12:18:06 2020 UTC add TRY() to avoid premature execution of ACTION commit - c64af147da5a26f0586e7d201175c5f9864ab478 commit + e3cbf911592479fbaa8b6f9edaf54328d9cee629 blob - f1b6210ea9098ef2ec08b8495cbc6a9af114776b blob + dd835e84fec59008d7c3219a6d67879906247244 --- ini_a.c +++ ini_a.c @@ -103,18 +103,20 @@ DEF_(leftbr, CHAR('[')) DEF_(rightbr, CHAR(']')) DEF_(eol, CHOICE(nl, end)) -DEF_(bra, SEQ(wss, leftbr)) +DEF_(bra, TRY(wss, leftbr)) DEF_(ket, SEQ(rightbr, wss)) DEF_(comment, OPT(semi, lchars)) DEF_(sname, MANY1(schar)) DEF_(key, MANY1(kchar)) DEF_(value, MANY1(lchar)) -DEF_(empties, MANY(wss, comment, nl)) -DEF_(header, SEQ(empties, bra, sname, ket, eol)) -DEF_(entries, MANY(empties, key, eq, value, eol)) +DEF_(empty, TRY(wss, comment, nl)) +DEF_(empties, MANY(empty)) +DEF_(header, TRY(empties, bra, sname, ket, eol)) +DEF_(entry, TRY(empties, key, eq, value, eol)) +DEF_(entries, MANY(entry)) -DEF_(tail, OPT(eof, wss, eol, anys)) +DEF_(tail, TRY(eof, wss, eol, anys) || EPSILON) DEF_(sects, MANY(header, entries)) DEF_(inifile, SEQ(sects, empties, wss, tail)) @@ -125,6 +127,9 @@ trace(void *ctx, void *env, const char *s, size_t len) const char *begin = env; size_t pos; + if (env == NULL) + return true; + pos = s - begin; printf("%4zx: %4zu byte %s\n", pos, len, nt); return true; blob - 465924eae396069cc11288010225f6cdc0a46c65 blob + 7fb3f05287cc2fe0e730c1507bd28fd0e841c444 --- minip_a.h +++ minip_a.h @@ -68,7 +68,22 @@ typedef stream parser(stream, const stream, void *); typedef bool action(void *, void *, const char *, size_t); #define ACTION(F, C) (F)((C), env_, inp_, p_ - inp_) +/* + * to avoid premature execution of actions, TRY(...) can be used in place of + * SEQ on any sequence where actions could execute before a later nonterminal + * fails. note: + * + * - single-element sequences do not need TRY. + * - multi-argument calls of MANY, MANY1, OPT may need to be replaced. + * - OPT(...) can be replaced with TRY(...) || EPSILON. + * + * in any case, beware of the overhead. since TRY executes the sequence twice, + * it can easily lead to a substantial increase in recognition time. + */ +#define MATCH(...) seq_(inp_, endp_, NULL, PARGS(__VA_ARGS__)) +#define TRY(...) (env_ == NULL || MATCH(__VA_ARGS__)) && SEQ(__VA_ARGS__) + static inline stream anychar_(stream p, const stream endp) {