Commit Diff


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)
 {