tttm

git clone https://orangeshoelaces.net/git/tttm.git

a29516112673f736136b3bae56f597975a3133d7

Author: Vasily Kolobkov on 04/29/2016

Committer: Vasily Kolobkov on 04/29/2016

Cut parsing noise

Stats

parse.c | 547 ++++----
parse.h |  49 +-
2 files changed, 307 insertions(+), 289 deletions(-)

Patch

diff --git a/parse.c b/parse.c
index 7ff67d2..af2e702 100644
--- a/parse.c
+++ b/parse.c
@@ -52,30 +52,30 @@ static struct literal {
 
 struct parse_cur {
 	const char   *tok;
-	union marker *pt;
+	union parse_node *pt;
 };
 
 struct parse_ctx {
-	const char   *tok;
-	const char   *tokend;
-	size_t        toklen;
-	union marker *pt;
-	union marker *ptend;
-	size_t        ptlen;
-	struct parse_cur cur;
-	size_t        oblth;
-	int           e;
+	struct parse_cur  cur;
+	const char       *tok;
+	const char       *tokend;
+	size_t            toklen;
+	union parse_node *pt;
+	union parse_node *ptend;
+	size_t            ptlen;
+	int               e;
+	size_t            oblth;
 };
 
 typedef int parsefn(struct parse_ctx *);
 
 int
-parse_respln(const char *tok, size_t toklen, union marker *pt,
+parse_respln(const char *tok, size_t toklen, union parse_node *pt,
     size_t ptlen, size_t oblth)
 {
 	struct parse_ctx p = { tok, tok + toklen, toklen, pt,
 	    pt + ptlen, ptlen, { tok, pt }, oblth, 0 };
-	parse_respln(&p);
+	p_respln(&p);
 	return p->e;
 }
 
@@ -84,110 +84,105 @@ parse_respln(const char *tok, size_t toklen, union marker *pt,
 */
 
 int
-chkpoint(struct parse_ctx *p, struct parse_cur *cp)
+p_chk(struct parse_ctx *p, struct parse_cur *cp)
 {
 	*cp = p->cur;
 	return 1;
 }
 
 int
-markhdr(struct parse_ctx *p, int type)
+p_insint(struct parse_ctx *p, int prod, size_t len)
 {
-	if (p->cur.pt == p->ptend) {
-		p->e = ENOTENMK;
+	union parse_node *cur;
+
+	cur = p->cur.pt;
+	if (cur == p->ptend) {
+		p->e = PE_NOTENNODES;
 		return 0;
 	}
-	p->cur.pt.hdr.type = type;
+	cur->inter.type = PN_INTER;
+	cur->inter.prod = prod;
+	cur->inter.len = len;
 	p->cur.pt++;
 	return 1;
 }
 
 int
-intbeg(struct parse_ctx *p, struct parse_cur *beg, int type)
+p_beg(struct parse_ctx *p, struct parse_cur *beg, int prod)
 {
-	return chkpoint(p, beg) && markhdr(p, MK_INT | type);
+	return p_chk(p, beg) && p_insint(p, type, 0);
 }
 
 int
-intend(struct parse_ctx *p, struct parse_cur *beg)
+p_end(struct parse_ctx *p, struct parse_cur *beg)
 {
-	beg->len = p->cur.mark - beg->mark;
+	beg->pt->inter.len = p->cur.mark - beg->mark;
+	p->e = PE_OK;
 	return 1;
 }
 
 int
-rollback(struct parse_ctx *p, struct parse_cur *cp)
+p_rwd(struct parse_ctx *p, struct parse_cur *cp)
 {
 	p->cur = *cp;
 	if (!p->e)
-		p->e = EPARSE;
+		p->e = PE_PARSE;
 
 	return 0;
 }
 
 int
-opt(struct parse_ctx *p)
+p_opt(struct parse_ctx *p)
 {
-	if (p->e == EPARSE)
-		p->e = 0;
+	if (p->e == PE_PARSE)
+		p->e = PE_OK;
 
 	return !p->e;
 }
 
 /* prod *(SP prod) */
 int
-parse_list(struct parse_ctx *p, parsefn *prod)
+p_list(struct parse_ctx *p, parsefn *prod)
 {
 	int res;
 
-	res = prod(p);
-	while(res && parse_2xcombo(p, SP, prod))
+	for (res = prod(p); res && p_2xcombo(p, SP, prod);)
 		;
-	return res && opt(p);
+	return res && p_opt(p);
 }
 
 /* 1*prod */
 int
-parse_rep(struct parse_ctx *p, parsefn *prod)
+p_rep(struct parse_ctx *p, parsefn *prod)
 {
 	int res;
 
-	res = prod(p);
-	while(res && prod(p))
+	for (res = prod(p); res && prod(p);)
 		;
-	return res && opt(p);
+	return res && p_opt(p);
 }
 
-/* 1*<any char except those in `except'> */
+/* 1*<any char but those in `except'> */
 int
-parse_repchr(struct parse_ctx *p, const char *except, int type)
+p_repchr(struct parse_ctx *p, const char *except, int strtype)
 {
 	char *t;
-	union marker *pt;
+	size_t len;
 
 	t = p->cur.tok;
-	pt = p->cur.pt;
 
 	while (t != p->tokend && binsearch(except, *t) == -1)
 		t++;
 
-	if (!(t > p->cur.tok)) {
+	len = t - p->cur.tok;
+	if (len == 0) {
 		p->e = PE_PARSE;
 		goto exit;
-	} else if (p->ptlen < 2 || p->ptend - p->cur.pt < 2) {
-		p->e = PE_NOTENMK;
-		goto exit;
 	}
-
-	pt->hdr.type = MK_LEAF | type;
-	pt->hdr.len = 2;
-	pt++;
-	pt->str.tok = p->cur.tok;
-	pt->str.len = t - p->cur.tok;
-	pt++;
+	if (!p_insstr(p, strtype, p->cur.tok, len))
+		goto exit;
 
 	p->cur.tok = t;
-	p->cur.mark = m;
 	p->e = PE_OK;
 
  exit:
@@ -195,30 +190,29 @@ parse_repchr(struct parse_ctx *p, const char *except, int type)
 }
 
 int
-parse_2xcombo(struct parse_ctx *p, int ilit, parsefn *prod)
+p_2xcombo(struct parse_ctx *p, int lit, parsefn *prod)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, ilit) &&
-	    prod(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, lit) && prod(p) || p_rwd(p, &b);
 }
 
 int
-parse_3xcombo(struct parse_ctx *p, int ilit1, int ilit2, parsefn *prod)
+p_3xcombo(struct parse_ctx *p, int lit1, int lit2, parsefn *prod)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, ilit1) &&
-	    parse_lit(p, ilit2) && prod(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, lit1) &&
+	    p_lit(p, lit2) && prod(p) || p_rwd(p, &b);
 }
 
 int
-parse_3xcombor(struct parse_ctx *p, parsefn *prod, int ilit1, int ilit2)
+p_3xcombor(struct parse_ctx *p, parsefn *prod, int lit1, int lit2)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && prod(p) && parse_lit(p, ilit1) &&
-	    parse_lit(p, ilit2) || rollback(p, &b);
+	return p_chk(p, &b) && prod(p) && p_lit(p, lit1) &&
+	    p_lit(p, lit2) || p_rwd(p, &b);
 }
 
 /*
@@ -226,139 +220,139 @@ parse_3xcombor(struct parse_ctx *p, parsefn *prod, int ilit1, int ilit2)
 */
 
 int
-parse_astring(struct parse_ctx *p)
+p_astring(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return intbeg(p, &b, MK_ASTRING) &&
-	    (parse_repchr(p, astr_specials, MK_ASTRLIT) || parse_string(p)) &&
-	    intend(p, &b) || rollback(p, &b);
+	return p_beg(p, &b, PR_ASTRING) &&
+	    (p_repchr(p, astr_specials, PN_STR) || p_string(p)) &&
+	    p_end(p, &b) || p_rwd(p, &b);
 }
 
 int
-parse_atom(struct parse_ctx *p)
+p_atom(struct parse_ctx *p)
 {
-	return parse_repchr(p, atom_specials, MK_ATOM);
+	return p_beg(p, &b, PR_ATOM) &&
+	    p_repchr(p, atom_specials, PN_STR) &&
+	    p_end(p, &b) || p_rwd(p, &b);
 }
 
 int
-parse_authtype(struct parse_ctx *p)
+p_authtype(struct parse_ctx *p)
 {
-	return parse_atom(p);
+	return p_atom(p);
 }
 
 int
-parse_badcscode(struct parse_ctx *p)
+p_badcscode(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return intbeg(p, &b, MK_BADCSCODE) &&
-	    parse_lit(p, BADCS) && (parse_badcsopt(p) || opt(p)) &&
-	    intend(p, &b) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, BADCS) &&
+	    (p_badcsopt(p) || p_opt(p)) || p_rwd(p, &b);
 }
 
 int
-parse_badcsopt(struct parse_ctx *p)
+p_badcsopt(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, SP) &&
-	    parse_lit(p, OPAR) && parse_list(p, parse_astring) &&
-	    parse_lit(p, CPAR) || rollback(p, &b);
+	return p_chk(p, &b) && p_sp(p) && p_opar(p) &&
+	    p_list(p, parse_astring) && p_cpar(p) || p_rwd(p, &b);
 }
 
 int
-parse_base64(struct parse_ctx *p)
+p_base64(struct parse_ctx *p)
 {
 	/* DO ME */
 }
 
 int
-parse_cap(struct parse_ctx *p)
+p_cap(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, SP) &&
-	    (parse_2xcombo(AUTHEQ, parse_authtype, p) || parse_atom(p)) ||
-	    rollback(p, &b);
+	return p_beg(p, &b, PR_CAP) && p_sp(p) &&
+	    (p_2xcombo(p, AUTHEQ, parse_authtype) || p_atom(p)) &&
+	    p_end(p, &b) || p_rwd(p, &b);
 }
 
 int
-parse_capdata(struct parse_ctx *p)
+p_capdata(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, CAP) &&
-	    parse_rep(p, parse_cap) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, CAP) &&
+	    p_rep(p, parse_cap) || p_rwd(p, &b);
 }
 
 int
-parse_contreq(struct parse_ctx *p)
+p_contreq(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) &&
-	    parse_lit(p, PLUS) && parse_lit(p, SP) &&
-	    (parse_resptext(p) || parse_base64(p)) &&
-	    parse_lit(p, EOL) || rollback(p, &b);
+	return p_chk(p, &b) &&
+	    p_lit(p, PLUS) && p_sp(p) &&
+	    (p_resptext(p) || p_base64(p)) &&
+	    p_lit(p, EOL) || p_rwd(p, &b);
 }
 
 int
-parse_dquotedchar(struct parse_ctx *p)
+p_dquotedchar(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, DQUOTE) &&
-	    parse_quotedchar(p) && parse_lit(p, DQUOTE) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_dquote(p) &&
+	    p_quotedchar(p) && p_dquote(p) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_escqspec(struct parse_ctx *p)
+p_escqspec(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, BSLASH) &&
-	    (parse_lit(p, DQUOTE) || parse_lit(p, BSLASH)) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, BSLASH) &&
+	    (p_dquote(p) || p_lit(p, BSLASH)) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_flag(struct parse_ctx *p)
+p_flag(struct parse_ctx *p)
 {
-	return parse_lit(p, ANSWERED) || parse_lit(p, FLAGGED) ||
-	    parse_lit(p, DELETED) || parse_lit(p, SEEN) ||
-	    parse_lit(p, DRAFT) || parse_flkeyword(p) ||
-	    parse_flext(p);
+	return p_lit(p, ANSWERED) || p_lit(p, FLAGGED) ||
+	    p_lit(p, DELETED) || p_lit(p, SEEN) ||
+	    p_lit(p, DRAFT) || p_flkeyword(p) ||
+	    p_flext(p);
 }
 
 int
-parse_flext(struct parse_ctx *p)
+p_flext(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, BSLASH) &&
-	    parse_atom(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, BSLASH) &&
+	    p_atom(p) || p_rwd(p, &b);
 }
 
 int
-parse_flkeyword(struct parse_ctx *p)
+p_flkeyword(struct parse_ctx *p)
 {
-	return parse_atom(p);
+	return p_atom(p);
 }
 
 int
-parse_gencode(struct parse_ctx *p)
+p_gencode(struct parse_ctx *p)
 {
 	struct parse_cur opt;
 
-	return parse_atom(p) && (chkpoint(p, &opt) &&
-	    parse_lit(p, SP) && parse_genctext(p) ||
-	    rollback(p, &opt) || opt(p));
+	return p_atom(p) && (p_chk(p, &opt) &&
+	    p_sp(p) && p_genctext(p) ||
+	    p_rwd(p, &opt) || p_opt(p));
 }
 
 int
-parse_genctext(struct parse_ctx *p)
+p_genctext(struct parse_ctx *p)
 {
 	int res;
 	char *t;
@@ -378,57 +372,102 @@ parse_genctext(struct parse_ctx *p)
 }
 
 int
-parse_mailbox(struct parse_ctx *p)
+p_lit(struct parse_ctx *p, int lit)
+{
+	size_t left;
+
+	left = p->toklen - (p->cur.ntok - p->tokens);
+	if (left < literals[lit].len) {
+		p->e = 1;
+		goto exit;
+	}
+	if (strncasecmp(p->cur.tok, literals[lit].val, literals[lit].len) == 0) {
+		if (p->cur.nact == p->actend)) {
+			p->e = 2;
+			goto exit;
+		}
+		*p->cur.nact++ = { ... };
+		p->cur.ntok += literals[lit].len;
+		p->e = 0;
+	} else {
+		p->e = 1;
+		goto exit;
+	}
+ exit:
+	return !p->e;
+}
+
+int
+p_litstr(struct parse_ctx *p)
+{
+	int res;
+	size_t len;
+	struct parse_cur b;
+
+	res = p_beg(p, MK_LITSTR, &b) && p_lit(p, OBRACE) &&
+	    p_number(p) && p_lit(p, CBRACE) && p_lit(p, EOL) &&
+	    p_end(p, &b) || p_rwd(p, &b);
+
+	if (res) {
+		len = b.pt[4].num.val;
+		if (len < p->oblth)
+			p->cur.tok += len;
+	}
+	return res;
+}
+
+int
+p_mailbox(struct parse_ctx *p)
 {
-	return parse_lit(p, INBOX) || parse_astring(p);
+	return p_lit(p, INBOX) || p_astring(p);
 }
 
 int
-parse_mbdata(struct parse_ctx *p)
+p_mbdata(struct parse_ctx *p)
 {
-	return parse_mbflags(p) || parse_mblist(p) ||
-	    parse_mblsub(p) || parse_mbsearch(p) ||
-	    parse_mbstatus(p) || parse_mbexists(p) ||
-	    parse_mbrecent(p);
+	return p_mbflags(p) || p_mblist(p) ||
+	    p_mblsub(p) || p_mbsearch(p) ||
+	    p_mbstatus(p) || p_mbexists(p) ||
+	    p_mbrecent(p);
 }
 
 int
-parse_mbexists(struct parse_ctx *p)
+p_mbexists(struct parse_ctx *p)
 {
-	return parse_3xcombor(p, parse_number, SP, EXISTS);
+	return p_3xcombor(p, parse_number, SP, EXISTS);
 }
 
 int
-parse_mbflags(struct parse_ctx *p)
+p_mbflags(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	rerurn chkpoint(p, &b) && parse_lit(p, FLAGS) &&
-	    parse_lit(p, SP) && parse_lit(p, OPAR) &&
-	    (parse_list(p, parse_flag) || opt(p)) &&
-	    parse_lit(p, CPAR) || rollback(p, &b);
+	rerurn p_chk(p, &b) && p_lit(p, FLAGS) &&
+	    p_sp(p) && p_opar(p) &&
+	    (p_list(p, parse_flag) || p_opt(p)) &&
+	    p_cpar(p) || p_rwd(p, &b);
 }
 
 int
-parse_mblist(struct parse_ctx *p)
+p_mblist(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, LIST) &&
-	    parse_lit(p, SP) && parse_mblistdata(p) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, LIST) &&
+	    p_sp(p) && p_mblistdata(p) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_mblistdata(struct parse_ctx *p)
+p_mblistdata(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, OPAR) &&
-	    (parse_list(p, parse_mblistfl) || opt(p)) &&
-	    parse_lit(p, CPAR) && parse_lit(p, SP) &&
-	    (parse_dquotedchar(p) || parse_lit(NIL)) &&
-	    parse_lit(p, SP) && parse_mailbox(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_opar(p) &&
+	    (p_list(p, parse_mblistfl) || p_opt(p)) &&
+	    p_cpar(p) && p_sp(p) &&
+	    (p_dquotedchar(p) || p_lit(NIL)) &&
+	    p_sp(p) && p_mailbox(p) || p_rwd(p, &b);
 }
 
 /*
@@ -436,89 +475,89 @@ parse_mblistdata(struct parse_ctx *p)
    be simpler and more readable?
 */
 int
-parse_mblistfl(struct parse_ctx *p)
+p_mblistfl(struct parse_ctx *p)
 {
-	return parse_mblistosfl(p) || parse_list(p, parse_mblistofl);
+	return p_mblistosfl(p) || p_list(p, parse_mblistofl);
 }
 
 int
-parse_mblistofl(struct parse_ctx *p)
+p_mblistofl(struct parse_ctx *p)
 {
-	return parse_lit(p, NOINFERIORS) || parse_flext(p);
+	return p_lit(p, NOINFERIORS) || p_flext(p);
 }
 
 int
-parse_mblistosfl(struc parse_ctx *p)
+p_mblistosfl(struc parse_ctx *p)
 {
 	int res;
 	struct parse_cur b;
 
 	checkpoint(p, &b);
 
-	res = parse_list(p, parse_mblistofl) &&
-	    parse_lit(p, SP) || rollback(p, &b) || opt(p);
+	res = p_list(p, parse_mblistofl) &&
+	    p_sp(p) || p_rwd(p, &b) || p_opt(p);
 
-	res = res && parse_mblistsfl(p);
+	res = res && p_mblistsfl(p);
 
-	res = res && chkpoint(p, &s) && parse_lit(p, SP) &&
-	    parse_list(p, parse_mblistofl) || rollback(p, &s) || opt(p);
+	res = res && p_chk(p, &s) && p_sp(p) &&
+	    p_list(p, parse_mblistofl) || p_rwd(p, &s) || p_opt(p);
 
-	return res || rollback(p, &b);
+	return res || p_rwd(p, &b);
 }
 
 int
-parse_mblistsfl(struct parse_ctx *p)
+p_mblistsfl(struct parse_ctx *p)
 {
-	return parse_lit(p, NOSEL) || parse_lit(p, MARKED) ||
-	    parse_lit(p, UNMARKED);
+	return p_lit(p, NOSEL) || p_lit(p, MARKED) ||
+	    p_lit(p, UNMARKED);
 }
 
 int
-parse_mblsub(struct parse_ctx *p)
+p_mblsub(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, LSUB) &&
-	    parse_lit(p, SP) && parse_mblistdata(p) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, LSUB) &&
+	    p_sp(p) && p_mblistdata(p) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_mbrecent(struct parse_ctx *p)
+p_mbrecent(struct parse_ctx *p)
 {
-	return parse_3xcombor(p, parse_number, SP, RECENT);
+	return p_3xcombor(p, parse_number, SP, RECENT);
 }
 
 int
-parse_mbsearch(struct parse_ctx *p)
+p_mbsearch(struct parse_ctx *p)
 {
 	struct parse_cur b, o;
 
-	return chkpoint(p, &b) && parse_lit(p, SEARCH) &&
-	    (chkpoint(p, &o) && parse_lit(p, SP) &&
-	    parse_list(p, parse_nznumber) || rollback(p, &o) || opt(p)) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, SEARCH) &&
+	    (p_chk(p, &o) && p_sp(p) &&
+	    p_list(p, parse_nznumber) || p_rwd(p, &o) || p_opt(p)) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_mbstatus(struct parse_ctx *p)
+p_mbstatus(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, STATUS) && parse_lit(p, SP) &&
-	    parse_mailbox(p) && parse_lit(p, SP) && parse_lit(p, OPAR) &&
-	    (parse_list(p, parse_stattrec) || opt(p)) && parse_lit(p, CPAR) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, STATUS) && p_sp(p) &&
+	    p_mailbox(p) && p_sp(p) && p_opar(p) &&
+	    (p_list(p, parse_stattrec) || p_opt(p)) && p_cpar(p) ||
+	    p_rwd(p, &b);
 }
 
 int
-parse_number(struct parse_ctx *p)
+p_number(struct parse_ctx *p)
 {
 	/* DO ME */
 }
 
 int
-parse_nznumber(struct parse_ctx *p)
+p_nznumber(struct parse_ctx *p)
 {
 	int res;
 	char *t;
@@ -541,30 +580,30 @@ parse_nznumber(struct parse_ctx *p)
 }
 
 int
-parse_permfl(struct parse_ctx *p)
+p_permfl(struct parse_ctx *p)
 {
-	return parse_flag(p) || parse_lit(p, ANYFL);
+	return p_flag(p) || p_lit(p, ANYFL);
 }
 
 int
-parse_permflcode(struct parse_ctx *p)
+p_permflcode(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, PERMFL) &&
-	    parse_lit(p, SP) && parse_lit(p, OPAR) &&
-	    (parse_list(p, parse_permfl) || opt(p)) &&
-	    parse_lit(p, CPAR) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, PERMFL) &&
+	    p_sp(p) && p_opar(p) &&
+	    (p_list(p, parse_permfl) || p_opt(p)) &&
+	    p_cpar(p) || p_rwd(p, &b);
 }
 
 int
-parse_quotedchar(struct parse_ctx *p)
+p_quotedchar(struct parse_ctx *p)
 {
-	return parse_quotedcharclean(p) || parse_escqspec(p);
+	return p_quotedcharclean(p) || p_escqspec(p);
 }
 
 int
-parse_quotedcharclean(struct parse_ctx *p)
+p_quotedcharclean(struct parse_ctx *p)
 {
 	if (p->cur.ntok != p->tokend &&
 	    binsearch(quotedclean, *p->cur.ntok) == -1) {
@@ -577,176 +616,154 @@ parse_quotedcharclean(struct parse_ctx *p)
 }
 
 int
-parse_quotstr(struct parse_ctx *p)
+p_quotstr(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return intbeg(p, &b, MK_QUOTSTR) && parse_lit(p, DQUOTE) &&
-	    (parse_rep(p, parse_quotedchar) || opt(p)) &&
-	    parse_lit(p, DQUOTE) || rollback(p, &b);
+	return p_beg(p, &b, MK_QUOTSTR) && p_dquote(p) &&
+	    (p_rep(p, parse_quotedchar) || p_opt(p)) &&
+	    p_dquote(p) || p_rwd(p, &b);
 }
 
 int
-parse_respbye(struct parse_ctx *p)
+p_respbye(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, BYE) && parse_lit(p, SP) &&
-	    parse_resptext(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_lit(p, BYE) && p_sp(p) &&
+	    p_resptext(p) || p_rwd(p, &b);
 }
 
 int
-parse_respdata(struct parse_ctx *p)
+p_respdata(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_lit(p, ASTERISK) &&
-	    parse_lit(p, SP) && (parse_respstate(p) ||
-	    parse_respbye(p) || parse_mbdata(p) || parse_msgdata(p) ||
-	    parse_capdata(p)) && parse_eol(p) || rollback(p &s);
+	return p_chk(p, &b) && p_lit(p, ASTERISK) &&
+	    p_sp(p) && (p_respstate(p) ||
+	    p_respbye(p) || p_mbdata(p) || p_msgdata(p) ||
+	    p_capdata(p)) && p_eol(p) || p_rwd(p &s);
 }
 
 int
-parse_respln(struct parse_ctx *p)
+p_respln(struct parse_ctx *p)
 {
-	return parse_contreq(p) ||
-	    parse_respdata(p) ||
-	    parse_taggedresp(p);
+	return p_contreq(p) || p_respdata(p) || p_taggedresp(p);
 }
 
 int
-parse_respstate(struct parse_ctx *p)
+p_respstate(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && (parse_lit(p, OK) ||
-	    parse_lit(p, NO) || parse_lit(p, BAD)) &&
-	    parse_lit(p, SP) && parse_resptext(p) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) &&
+	    (p_lit(p, OK) || p_lit(p, NO) || p_lit(p, BAD)) &&
+	    p_sp(p) && p_resptext(p) || p_rwd(p, &b);
 }
 
 int
-parse_resptext(struct parse_ctx *p)
+p_resptext(struct parse_ctx *p)
 {
 	int res;
 	struct parse_cur b;
 
-	res = chkpoint(p, &b) && parse_lit(p, OBRACK) &&
-	    parse_resptextcode(p) && parse_lit(p, CBRACK) &&
-	    parse_lit(p, SP) || rollback(p, &b) || opt(p);
+	res = p_chk(p, &b) && p_lit(p, OBRACK) &&
+	    p_resptextcode(p) && p_lit(p, CBRACK) &&
+	    p_sp(p) || p_rwd(p, &b) || p_opt(p);
 
-	return res && parse_text(p);
+	return res && p_text(p);
 }
 
 int
-parse_resptextcode(struct parse_ctx *p)
+p_resptextcode(struct parse_ctx *p)
 {
-	return parse_lit(p, ALERT) || parse_badcscode(p) ||
-	    parse_capdata(p) || parse_lit(p, PARSE) ||
-	    parse_permflcode(p) || parse_lit(p, RO) ||
-	    parse_lit(p, RW) || parse_lit(p, TRYC) ||
-	    parse_uidncode(p) || parse_uidvcode(p) ||
-	    parse_unseencode(p) || parse_gencode(p);
+	return p_lit(p, ALERT) || p_badcscode(p) ||
+	    p_capdata(p) || p_lit(p, PARSE) ||
+	    p_permflcode(p) || p_lit(p, RO) ||
+	    p_lit(p, RW) || p_lit(p, TRYC) ||
+	    p_uidncode(p) || p_uidvcode(p) ||
+	    p_unseencode(p) || p_gencode(p);
 }
 
 int
-parse_statt(struct parse_ctx *p)
+p_statt(struct parse_ctx *p)
 {
-	return parse_lit(p, MESSAGES) || parse_lit(p, RECENT) ||
-	    parse_lit(p, UIDNEXT) || parse_lit(p, UIDVAL) ||
-	    parse_lit(p, UNSEEN);
+	return p_lit(p, MESSAGES) || p_lit(p, RECENT) ||
+	    p_lit(p, UIDNEXT) || p_lit(p, UIDVAL) ||
+	    p_lit(p, UNSEEN);
 }
 
 int
-parse_stattrec(struct parse_ctx *p)
+p_stattrec(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_statt(p) && parse_lit(p, SP) &&
-	    parse_number(p) || rollback(p, &b);
+	return p_chk(p, &b) && p_statt(p) && p_sp(p) &&
+	    p_number(p) || p_rwd(p, &b);
 }
 
 int
-parse_string(struct parse_ctx *p)
+p_string(struct parse_ctx *p)
 {
-	return parse_qoutstr(p) || parse_litstr(p);
+	return p_qoutstr(p) || p_litstr(p);
 }
 
 int
-parse_tag(struct parse_ctx *p)
+p_tag(struct parse_ctx *p)
 {
-	return parse_repchr(p, tag_specials);
+	return p_repchr(p, tag_specials);
 }
 
 int
-parse_taggedresp(struct parse_ctx *p)
+p_taggedresp(struct parse_ctx *p)
 {
 	struct parse_cur b;
 
-	return chkpoint(p, &b) && parse_tag(p) && parse_lit(p, SP) &&
-	    parse_respstate(p) && parse_eol(p) ||
-	    rollback(p, &b);
+	return p_chk(p, &b) && p_tag(p) && p_sp(p) &&
+	    p_respstate(p) && p_eol(p) || p_rwd(p, &b);
 }
 
 int
-parse_lit(int i, struct parse_ctx *p)
+p_uidncode(struct parse_ctx *p)
 {
-	size_t left;
+	return p_3xcombo(UIDNEXT, SP, parse_nznumber);
+}
 
-	left = p->toklen - (p->cur.ntok - p->tokens);
-	if (left < literals[i].len) {
-		p->e = 1;
-		goto exit;
-	}
-	if (strncasecmp(p->cur.ntok, literals[i].val, literals[i].len) == 0) {
-		if (p->cur.nact == p->actend)) {
-			p->e = 2;
-			goto exit;
-		}
-		*p->cur.nact++ = { ... };
-		p->cur.ntok += literals[i].len;
-		p->e = 0;
-	} else {
-		p->e = 1;
-		goto exit;
-	}
- exit:
-	return !p->e;
+int
+p_uidvcode(struct parse_ctx *p)
+{
+	return p_3xcombo(UIDVAL, SP, parse_nznumber);
 }
 
 int
-parse_litstr(struct parse_ctx *p)
+p_unseencode(struct parse_ctx *p)
 {
-	int res;
-	size_t len;
-	struct parse_cur b;
+	return p_3xcombo(UNSEEN, SP, parse_nznumber);
+}
 
-	res = intbeg(p, MK_LITSTR, &b) && par_lit(p, OBRACE) &&
-	    par_number(p) && par_lit(p, CBRACE) && par_lit(p, EOL) &&
-	    intend(p, &b) || rollback(p, &b);
+/* shortcuts for some common literals and means
+   of imrpoving legibility of bulky productions */
 
-	if (res) {
-		len = b.pt[4].num.val;
-		if (len < p->oblth)
-			p->cur.tok += len;
-	}
-	return res;
+int
+p_cpar(struct parse_ctx *p)
+{
+	return p_lit(p, CPAR);
 }
 
 int
-parse_uidncode(struct parse_ctx *p)
+p_dquote(struct parse_ctx *p)
 {
-	return parse_3xcombo(UIDNEXT, SP, parse_nznumber);
+	return p_lit(p, DQUOTE);
 }
 
 int
-parse_uidvcode(struct parse_ctx *p)
+p_opar(struct parse_ctx *p)
 {
-	return parse_3xcombo(UIDVAL, SP, parse_nznumber);
+	return p_lit(p, OPAR);
 }
 
 int
-parse_unseencode(struct parse_ctx *p)
+p_sp(struct parse_ctx *p)
 {
-	return parse_3xcombo(UNSEEN, SP, parse_nznumber);
+	return p_lit(p, SP);
 }
diff --git a/parse.h b/parse.h
index e576636..9ab51dd 100644
--- a/parse.h
+++ b/parse.h
@@ -1,33 +1,34 @@
-union marker {
-	struct {
-		int    type;
-		int    aux;
-		size_t len;
-	} hdr;
-	struct {
-		char  *tok;
-		size_t len;
-	} str;
-	struct {
-		char  *tok;
-		size_t len;
-	} lstr;
+enum parse_lit { };
+enum parse_prod { };
+
+enum { PN_INTER, PN_LIT, PN_NUM, PN_STR, PN_QSTR, PN_LSTR, PN_OBLSTR };
+
+enum { PE_OK, PE_PARSE, PE_NOTENNODES };
+
+union parse_node {
+	int type;
 	struct {
-		size_t iob;
+		int type;
+		int prod;
 		size_t len;
-	} oblstr;
+	} inter;
 	struct {
-		char  *tok;
-		size_t len;
-	} qstr;
+		int type;
+		int val;
+	} lit;
 	struct {
+		int type;
 		size_t val;
 	} num;
+	struct {
+		int type;
+		uint32_t len;
+		union {
+			char *tok;
+			size_t iob;
+		};
+	} str;
 };
 
-enum { PE_OK, PE_PARSE, PE_NOTENMK };
-
-enum { MK_INT, MK_LEAF, MK_ATOM, ... };
-
-int parse_respln(const char *tok, size_t toklen, union marker *pt,
+int parse_respln(const char *tok, size_t toklen, union parse_node *pt,
     size_t ptlen, size_t oblth)