Skip to content

Instantly share code, notes, and snippets.

@abiggerhammer
Created October 27, 2014 14:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abiggerhammer/5c34eafccb9e4dc5f4d6 to your computer and use it in GitHub Desktop.
Save abiggerhammer/5c34eafccb9e4dc5f4d6 to your computer and use it in GitHub Desktop.
/* Parser for ABNF, per RFC 5234. */
#include <hammer/hammer.h>
#include <hammer/glue.h>
const HParser* init_parser() {
static const HParser *ret = NULL;
if (ret)
return ret;
/* Core rules from Appendix B.1. Some rules appear out
* of order because of precedence. */
H_RULE(ALPHA, h_choice(h_ch_range('A', 'Z'),
h_ch_range('a', 'z'), NULL));
H_RULE(BIT, h_choice(h_ch('0'), h_ch('1'), NULL));
H_RULE(CHAR, h_ch_range('\x01', '\x7f'));
H_RULE(CR, h_ch('\x0d'));
H_RULE(LF, h_ch('\x0a'));
H_RULE(CRLF, h_sequence(CR, LF, NULL));
H_RULE(CTL, h_choice(h_ch_range('\x00', '\x1f'),
h_ch('\x7f'), NULL));
H_RULE(DIGIT, h_ch_range('0', '9'));
H_RULE(DQUOTE, h_ch('"'));
H_RULE(HEXDIG, h_choice(DIGIT,
h_ch_range('A', 'F'), NULL));
H_RULE(HTAB, h_ch('\x09'));
H_RULE(OCTET, h_ch_range('\x00', '\xff'));
H_RULE(SP, h_ch(' '));
H_RULE(VCHAR, h_ch_range('\x21', '\x7e'));
H_RULE(WSP, h_choice(SP, HTAB, NULL));
H_RULE(LWSP, h_many(h_choice(WSP,
h_sequence(CRLF, WSP, NULL),
NULL)));
/* ABNF definition of ABNF from section 4.2, mostly from the bottom up. */
H_RULE(prose_val, h_sequence(h_ch('<'), h_many(h_choice(h_ch_range('\x20', '\x3d'),
h_ch_range('\x3f', '\x7e'), NULL)),
h_ch('>'), NULL));
H_RULE(hex_val, h_sequence(h_ch('x'),
h_many1(HEXDIG),
h_optional(h_choice(h_many1(h_sequence(h_ch('.'),
h_many1(HEXDIG), NULL)),
h_sequence(h_ch('-'), h_many1(HEXDIG), NULL),
NULL)),
NULL));
H_RULE(dec_val, h_sequence(h_ch('d'),
h_many1(DIGIT),
h_optional(h_choice(h_many1(h_sequence(h_ch('.'),
h_many1(DIGIT), NULL)),
h_sequence(h_ch('-'), h_many1(DIGIT), NULL),
NULL)),
NULL));
H_RULE(bin_val, h_sequence(h_ch('b'),
h_many1(BIT),
h_optional(h_choice(h_many1(h_sequence(h_ch('.'),
h_many1(BIT), NULL)),
h_sequence(h_ch('-'), h_many1(BIT), NULL),
NULL)),
NULL));
H_RULE(num_val, h_sequence(h_ch('%'), h_choice(bin_val, dec_val, hex_val, NULL), NULL));
H_RULE(char_val, h_sequence(DQUOTE, h_many(h_choice(h_ch_range('\x20', '\x21'),
h_ch_range('\x23', '\x7e'), NULL)),
DQUOTE, NULL));
H_RULE(comment, h_sequence(h_ch(';'), h_many(h_choice(WSP, VCHAR, NULL)), CRLF, NULL));
H_RULE(c_nl, h_choice(comment, CRLF, NULL));
H_RULE(c_wsp, h_choice(WSP, h_sequence(c_nl, WSP, NULL), NULL));
H_RULE(alternation, h_indirect());
H_RULE(option, h_sequence(h_ch('['), h_many(c_wsp), alternation, h_many(c_wsp), h_ch(']'), NULL));
H_RULE(group, h_sequence(h_ch('('), h_many(c_wsp), alternation, h_many(c_wsp), h_ch(')'), NULL));
H_RULE(rulename, h_sequence(ALPHA, h_many(h_choice(ALPHA, DIGIT, h_ch('-'), NULL)), NULL));
H_RULE(element, h_choice(rulename, group, option, char_val, num_val, prose_val, NULL));
H_RULE(repeat, h_choice(h_many1(DIGIT),
h_sequence(h_many(DIGIT), h_ch('*'), h_many(DIGIT), NULL), NULL));
H_RULE(repetition, h_sequence(h_optional(repeat), element, NULL));
H_RULE(concatenation, h_sequence(repetition, h_many(h_sequence(h_many1(c_wsp), repetition, NULL)), NULL));
h_bind_indirect(alternation, h_sequence(concatenation, h_many(h_sequence(h_many(c_wsp), h_ch('/'),
h_many(c_wsp), concatenation,
NULL)), NULL));
H_RULE(elements, h_sequence(alternation, h_many(c_wsp), NULL));
H_RULE(defined_as, h_sequence(h_many(c_wsp), h_choice(h_ch('='), h_token("=/", 2), NULL),
h_many(c_wsp), NULL));
H_RULE(rule, h_sequence(rulename, defined_as, elements, c_nl, NULL));
H_RULE(rulelist, h_many1(h_choice(rule, h_sequence(h_many(c_wsp), c_nl, NULL), NULL)));
ret = rulelist;
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment