-
Notifications
You must be signed in to change notification settings - Fork 1
Hammer Quick Reference
Cheat sheet of every Hammer function and macro used in this wiki's examples, organized by category. Links jump to the page where each one is explained.
| Macro | Expands To | Docs |
|---|---|---|
H_RULE(name, def) |
HParser *name = def; |
Hammer Fundamentals |
H_ARULE(name, def) |
HParser *name = h_action(def, act_##name, NULL); |
NTP: Hex Preprocessing |
H_VRULE(name, def) |
HParser *name = h_attr_bool(def, validate_##name, NULL); |
Hammer Fundamentals |
H_VARULE(name, def) |
Validation after action: h_attr_bool(h_action(def, act_##name, NULL), validate_##name, NULL)
|
- |
H_AVRULE(name, def) |
Validation before action: h_action(h_attr_bool(def, validate_##name, NULL), act_##name, NULL)
|
- |
| Macro | Expands To |
|---|---|
H_ADRULE(name, def, data) |
h_action(def, act_##name, data) |
H_VDRULE(name, def, data) |
h_attr_bool(def, validate_##name, data) |
H_VADRULE(name, def, data) |
Validation after action, both receive data
|
H_AVDRULE(name, def, data) |
Validation before action, both receive data
|
| Macro | Purpose | Docs |
|---|---|---|
H_ACT_APPLY(myaction, paction, ...) |
Define myaction as a wrapper that calls parameterized action paction(__VA_ARGS__, p, user_data)
|
- |
H_VALIDATE_APPLY(myvalidation, pvalidation, ...) |
Define myvalidation as a wrapper that calls parameterized predicate pvalidation(__VA_ARGS__, p, user_data)
|
- |
| Macro | Purpose | Docs |
|---|---|---|
H_ALLOC(TYP) |
Allocate TYP from p->arena
|
((TYP *)h_arena_malloc(p->arena, sizeof(TYP))) |
H_MAKE(TYP, VAL) |
Create a token of custom type TT_##TYP. Requires TT_<type> constant ≥ TT_USER
|
- |
H_MAKE_SEQ() |
Creates an empty HParsedToken sequence |
NTP: Hex Preprocessing |
H_MAKE_SEQN(N) |
Create empty TT_SEQUENCE with expected capacity N
|
- |
H_MAKE_BYTES(ptr, len) |
Create TT_BYTES token |
- |
H_MAKE_SINT(val) |
Create TT_SINT token |
- |
H_MAKE_UINT(val) |
Creates an HParsedToken with an unsigned int value |
NTP: Hex Preprocessing |
H_MAKE_DOUBLE(val) |
Create TT_DOUBLE token |
- |
H_MAKE_FLOAT(val) |
Create TT_FLOAT token |
- |
| Macro | Purpose | Docs |
|---|---|---|
h_assert_type(T, tok) |
Assert tok->token_type == T and return tok (expression) |
- |
H_ASSERT(TYP, tok) |
Assert custom token type TT_##TYP
|
- |
H_ASSERT_SEQ(tok) |
Assert TT_SEQUENCE
|
- |
H_ASSERT_BYTES(tok) |
Assert TT_BYTES
|
- |
H_ASSERT_SINT(tok) |
Assert TT_SINT
|
- |
H_ASSERT_UINT(tok) |
Assert TT_UINT
|
- |
H_ASSERT_DOUBLE(tok) |
Assert TT_DOUBLE
|
- |
H_ASSERT_FLOAT(tok) |
Assert TT_FLOAT
|
- |
H_CAST(TYP, tok) |
Assert Custom type TT_##TYP, then return (TYP*)tok->token_data.user
|
- |
H_CAST_SEQ(tok) |
Assert sequence, then return tok->token_data.seq
|
- |
H_CAST_BYTES(tok) |
Assert bytes, then return tok->token_data.bytes
|
- |
H_CAST_SINT(tok) |
Assert sint, then return tok->token_data.sint
|
- |
H_CAST_UINT(tok) |
Assert uint, then return tok->token_data.uint
|
- |
H_CAST_DOUBLE(tok) |
Assert double, then return tok->token_data.dbl
|
- |
H_CAST_FLOAT(tok) |
Assert float, then return tok->token_data.flt
|
- |
H_INDEX_TOKEN(seq, ...) |
Nested index access via h_seq_index_path. Terminates path with -1 internally |
- |
H_INDEX(TYP, seq, ...) |
H_CAST(TYP, H_INDEX_TOKEN(seq, ...)) Nested sequence access |
- |
H_INDEX_SEQ(seq, ...) |
Nested access returning sequence pointer | - |
H_INDEX_BYTES(seq, ...) |
Nested access returning .bytes
|
- |
H_INDEX_SINT(seq, ...) |
Nested access returning .sint
|
- |
H_INDEX_UINT(seq, ...) |
Nested access returning .uint
|
- |
H_INDEX_DOUBLE(seq, ...) |
Nested access returning .dbl
|
- |
H_INDEX_FLOAT(seq, ...) |
Nested access returning .flt
|
- |
H_FIELD_TOKEN(...) |
Like H_INDEX_TOKEN but uses p->ast. For action functions |
- |
H_FIELD(TYP, ...) |
Like H_INDEX but uses p->ast. For action functions |
- |
H_FIELD_SEQ(...) |
Like H_INDEX_SEQ but uses p->ast
|
- |
H_FIELD_BYTES(...) |
Like H_INDEX_BYTES but uses p->ast
|
- |
H_FIELD_SINT(...) |
Like H_INDEX_SINT but uses p->ast
|
- |
H_FIELD_UINT(...) |
Like H_INDEX_UINT but uses p->ast
|
- |
H_FIELD_DOUBLE(...) |
Like H_INDEX_DOUBLE but uses p->ast
|
- |
H_FIELD_FLOAT(...) |
Like H_INDEX_FLOAT but uses p->ast
|
- |
| Macro | Purpose | Example Usage |
|---|---|---|
h_literal("str") |
Literal byte-string parser for string literals (expands to h_token((uint8_t*)s, sizeof(s)-1)) |
- |
h_drop_from(seq, ...) |
Convenience wrapper for h_drop_from_ that auto-terminates the index list with -1
|
- |
| Constant | Meaning |
|---|---|
BYTE_BIG_ENDIAN / BYTE_LITTLE_ENDIAN
|
Byte order |
BIT_BIG_ENDIAN / BIT_LITTLE_ENDIAN
|
Bit order within bytes |
| Function | Bits | Signed | Example Usage |
|---|---|---|---|
h_bits(n, signed) |
n | configurable | Parses into a 64-bit integer token; use n <= 64 to preserve value. NTP: Header - LI (2 bits), VN (3 bits), Mode (3 bits) |
h_bytes(len) |
len*8 |
- | TT_BYTES |
h_int8() |
8 | yes | NTP: Header - Poll, Precision |
h_uint8() |
8 | no | NTP: Header - Stratum |
h_int16() |
16 | yes | NTP: Data Fields - Root Delay/Dispersion halves |
h_uint16() |
16 | no | NTP: Extensions - Extension length |
h_int32() |
32 | yes | - |
h_uint32() |
32 | no | NTP: Data Fields - Reference ID, timestamp halves, Key ID |
h_int64() |
64 | yes | NTP: Extensions - Message Digest |
h_uint64() |
64 | no | - |
h_float16() |
16 | yes | - |
h_float32() |
32 | yes | - |
h_float64() |
64 | yes | - |
| Function | Description | Example Usage |
|---|---|---|
h_sequence(a, b, ..., NULL) |
Parse a, b, ... in order; result is a TT_SEQUENCE
|
NTP: Header |
h_many(p) |
Parse p zero or more times; result is a TT_SEQUENCE
|
NTP: Extensions |
h_many1(p) |
Parse p one or more times; result is a TT_SEQUENCE
|
DNS: Body |
h_many_cap(p, n) |
Parse p zero or more times up till n; result is a TT_SEQUENCE
|
|
h_many1_cap(p, n) |
Parse p one or more times up till n; result is a TT_SEQUENCE
|
|
h_repeat_n(p, n) |
Parse p exactly n times; result is a TT_SEQUENCE
|
NTP: Hex Preprocessing |
h_sepBy(p, sep) |
Zero or more p separated by sep; results of sep are discarded |
- |
h_sepBy1(p, sep) |
One or more p separated by sep; results of sep are discarded |
- |
h_permutation(a, b, ..., NULL) |
Match all parsers exactly once in any order; returns results in argument order | - |
h_many1vsh_sequence+h_many:h_many1(p)andh_sequence(p, h_many(p), NULL)match the same inputs, but their results differ.h_many1returns a flat sequence, while theh_sequenceversion returns a sequence whose second element is another sequence.
| Function | Description | Example Usage |
|---|---|---|
h_choice(a, b, ..., NULL) |
Try parsers in order; return first success | NTP: Assembling |
h_dispatch(discriminator, opcode_map, default) |
Given a dictionary-like OpcodeMap of parsers linked with opcodes, apply the parser linked to the opcode read by the discriminator parser; apply default parser if opcode doesn't match to a parser. |
- |
h_optional(p) |
Apply p; if it fails, succeed with TT_NONE instead. Never fails |
- |
h_int_range(p, lo, hi) |
Parse with p; fail if value is outside [lo, hi]
|
NTP: Header |
h_float_range(p, lo, hi) |
Parse with p; fail if value is outside [lo, hi]
|
- |
h_attr_bool(p, pred, data) |
Parse with p; fail unless pred(result, data) returns true |
Hammer Fundamentals |
h_butnot(p1, p2) |
Succeed if p1 matches and p2 fails, or p1's result is longer than p2's |
- |
h_difference(p1, p2) |
Succeed if p1 matches and p2 fails, or p1's result is at least as long as p2's |
- |
h_xor(p1, p2) |
Succeed if exactly one of p1 or p2 succeeds |
- |
| Function | Description | Example Usage |
|---|---|---|
h_left(a, b) |
Parse a then b; return only a's result |
NTP: Assembling |
h_right(a, b) |
Parse a then b; return only b's result |
- |
h_middle(a, b, c) |
Parse a, b, c in order; return only b's result |
- |
h_ignore(p) |
Parse with p; on success, return a NULL AST (elided from surrounding sequences) |
- |
h_whitespace(p) |
Consume and discard leading whitespace (space, tab, newline, etc.), then apply p
|
- |
h_drop_from_(seq, i0, i1, ..., -1) |
Parse a sequence but drop specified indices from the result sequence | - |
| Function | Description | Example Usage |
|---|---|---|
h_token(str, len) |
Match the literal byte string str of length len. Result is TT_BYTES
|
- |
h_ch(c) |
Match a single specific byte c. Result is TT_UINT
|
- |
h_ch_range(lo, hi) |
Match one byte in [lo, hi]. Result is TT_UINT
|
NTP: Hex Preprocessing |
h_in(charset, len) |
Match one byte if it appears in charset. Result is TT_UINT
|
- |
h_not_in(charset, len) |
Match one byte if it does not appear in charset. Result is TT_UINT
|
- |
| Function | Description |
|---|---|
h_and(p) |
Apply p without consuming input. Succeeds if p succeeds. AST is NULL
|
h_not(p) |
Apply p without consuming input. Succeeds if p fails. AST is NULL
|
h_end_p() |
Assert end of input (zero-width). NTP: Assembling |
| Function | Description |
|---|---|
h_epsilon_p() |
Consume no input, always succeed. Result is non-NULL but AST is NULL
|
h_nothing_p() |
Always fail. Useful for stubbing out parsers during development |
| Function | Description | Example Usage |
|---|---|---|
h_put_value(p, name) |
Parse with p; store result under name
|
NTP: Extensions |
h_get_value(name) |
Retrieve store value name without freeing |
- |
h_free_value(name) |
Retrieve stored value and free the binding | NTP: Extensions |
h_length_value(len_p, val_p) |
Parse len_p for a count n, then parse val_p n times |
NTP: Extensions |
h_action(p, fn, data) |
Parse with p; transform result with C function fn
|
NTP: Extensions |
h_action_stash(p, fn, data, collection) |
Parse with p; wait to transform result with C function fn until h_action_apply with collection is called |
- |
h_action_apply(p, collection) |
Parse with p; run matching stashed actions within p that share collection
|
- |
h_bind(p, k, env) |
Monadic bind for HParsers. Run p and call result x. Then run k(x, env). Fail if p fails or if k(env, x) fails or if k(env,x) is NULL. | - |
h_indirect() |
Create a forward-declared parser for recursive grammars | Hammer Fundamentals |
h_bind_indirect(indirect, p) |
Bind a parser created with h_indirect() to an actual parser p
|
Hammer Fundamentals |
| Function | Description | Docs |
|---|---|---|
h_skip(nbits) |
Skip nbits bits; AST is NULL
|
- |
h_seek(offset_bits, whence) |
Seek in bits (SEEK_SET/SEEK_CUR/SEEK_END); returns new position as TT_UINT
|
- |
h_tell() |
Current bit position; returns TT_UINT
|
DNS: Body |
h_with_endianness(flags, p) |
Run p under endianness flags (BYTE_* OR BIT_*) |
- |
| Function | Description | Docs |
|---|---|---|
h_parse(parser, data, len) |
Run parser on data; returns HParseResult * or NULL
|
Hammer Fundamentals |
| Function | Description | Docs |
|---|---|---|
h_parse_start(p) |
Start an incremental parse; returns HSuspendedParser* or NULL if unsupported. Only supported by some backends
|
- |
h_parse_chunk(s, input, length) |
Feed a chunk; returns true if parser s is done (needs no more input) |
- |
h_parse_finish(s) |
Finish incremental parse; signals end-of-input; returns HParseResult* or NULL
|
- |
| Function | Description | Docs |
|---|---|---|
h_parse_result_free(result) |
Free an HParseResult when done |
DNS: Assembling |
h_parser_free(parser) |
Free an HParser dynamically |
- |
h_parse_diagnostic_free(diagnostic) |
Free an HParseDiagnostic when done |
- |
| Function | Description | Docs |
|---|---|---|
h_pprint(stream, tok, indent, delta) |
Pretty-print an HParsedToken tree to a FILE * stream |
Running and Testing |
h_pprint_ast_indexed(stream, tok, indent) |
Pretty-print an HParsedToken abstract syntax tree with proper indexing |
- |
h_pprintln(stream, tok) |
Pretty-print an HParsedToken to the given output. Print a trailing newline |
- |
h_write_result_unamb(tok) |
Pretty-print an HParsedToken in an unambiguous form. Returns string that must be freed |
- |
Add #include <hammer/hammer_auto_source.h> after #include <hammer/hammer.h> to change all the combinators to macros that wrap the source location for the error report.
| Function | Description | Docs |
|---|---|---|
h_parse_debug(parser, input, length, diagnostic, show) |
like h_parse(), but collects an HParseDiagnostic diagnostic to collect failure info, when show is set to true it will print to stdout |
- |
h_parse_diagnostic_fprint(stream, diagnostic) |
Print a diagnostic to the given output. |
- |
h_parse_diagnostic_fprint_with_input |
combines h_parse_debug and h_parse_diagnostic_fprint
|
- |
h_parse_diagnostic_free(diagnostic) |
Free the given HParseDiagnostic
|
- |
h_parser_set_label(p,label) |
apply label to parser p to show as the name in debug diagnostics |
- |
h_parser_set_error_message(p, message) |
apply message to parser p to show as the error in debug diagnostics |
- |
h_parse_diagnostic_trace_fprint(diagnostic, length) |
Print a diagnostic's complete execution trace. |
- |
HParsedToken is a discriminated union. The token_type field tells you which member of token_data is valid. See Hammer Fundamentals for a full explanation.
HTokenType |
Value | Union Field | Description |
|---|---|---|---|
TT_INVALID |
0 | - | Invalid token types (internal / sentinel) |
TT_NONE |
1 | - | No value (used by h_optional on failure, h_end_p, etc.) |
TT_BYTES |
2 | .bytes |
Byte string with .token (pointer) and .len (length) |
TT_SINT |
4 | .sint |
Signed integer (int64_t) |
TT_UINT |
8 | .uint |
Unsigned integer (uint64_t) |
TT_DOUBLE |
12 | .dbl |
Double-precision float |
TT_FLOAT |
13 | .flt |
Single-precision float |
TT_SEQUENCE |
16 | .seq |
Sequence of HParsedToken * elements |
TT_ERR |
32 | - | Error token type (backend / internal use) |
TT_USER |
64+ | .user |
User-defined type (void *). See User-Defined Token Types
|
| API | Description | Example Usage |
|---|---|---|
result->ast |
Root HParsedToken * of a parse result |
NTP: Hex Preprocessing |
token->token_type |
The HTokenType discriminant indicating which union field is valid |
Hammer Fundamentals |
token->token_data.bytes.token |
Pointer to byte data in a TT_BYTES token |
- |
token->token_data.bytes.len |
Length of byte data in a TT_BYTES token |
- |
token->token_data.sint |
Signed integer value of a token | - |
token->token_data.uint |
Unsigned integer value of a token | NTP: Hex Preprocessing |
token->token_data.dbl |
Value for TT_DOUBLE
|
- |
token->token_data.flt |
Value for TT_FLOAT
|
- |
token->token_data.seq->used |
Number of elements in a sequence token | NTP: Hex Preprocessing |
token->token_data.seq->elements[i] |
Element pointers (raw) | - |
| API | Description | Example Usage |
|---|---|---|
h_seq_len(tok) |
Length of a sequence token | - |
h_seq_elements(tok) |
Pointer to element array | - |
h_seq_index(tok, i) |
Get element at index i of a sequence |
NTP: Hex Preprocessing |
h_seq_index_path(tok, i, ..., -1) |
Nested access by index path | - |
h_seq_snoc(seq_tok, elem_tok) |
Append one element to a sequence | NTP: Hex Preprocessing |
h_seq_append(seq_tok, other_seq_tok) |
Append many elements from another sequence | - |
h_seq_remove(seq_tok, n) |
Remove n elements from a sequence |
- |
h_seq_flatten(arena, tok) |
Flatten nested sequences into a single sequence | - |
| API | Description | Example Usage |
|---|---|---|
h_make(arena, type, value) |
Generic constructor | - |
h_make_seq(arena) |
Empty sequence | - |
h_make_seqn(arena, n) |
Empty sequence with expected size | - |
h_make_bytes(arena, ptr, len) |
Bytes token | - |
h_make_sint(arena, val) |
Signed int token | - |
h_make_uint(arena, val) |
Unsigned int token | - |
h_make_double(arena, val) |
Double token | - |
h_make_float(arena, val) |
Float token | - |
Hammer provides ready-made action functions you can pass to h_action or use with H_ARULE. These save you from writing common transformations by hand.
| Function | Description |
|---|---|
h_act_first |
Given a sequence, return its first element. Asserts the result is a sequence with >= 1 element |
h_act_second |
Given a sequence, return its second element. Asserts >= 2 elements |
h_act_last |
Given a sequence, return its last element. Asserts >= 1 element |
h_act_index(i, p, data) |
Given a sequence, return element at index i. Returns NULL AST if out of bounds |
h_act_flatten |
Recursively flatten nested sequences into a single top-level sequence |
h_act_ignore |
Replace the AST with NULL (action equivalent of the h_ignore combinator) |
H_RULE(pair, h_sequence(h_uint8(), h_uint16(), NULL));
HParser *first_only = h_action(pair, h_act_first, NULL);
HParser *second_only = h_action(pair, h_act_second, NULL);| Function | Description | Example Usage |
|---|---|---|
h_is_backend_available(backend) |
Returns 1 if backend is available, else 0 | - |
h_get_default_backend() |
Returns default backend (currently PB_PACKRAT) |
- |
h_get_default_backend_vtable() |
Returns default backend vtable | - |
h_query_backend_by_name(name) |
Lookup backend enum by name; returns PB_INVALID if unknown |
- |
h_get_backend_with_params_by_name("lalr(1)") |
Parse backend specification string into a backend+params config | - |
h_copy_backend_with_params(cfg) |
Copy a backend+params config | - |
h_free_backend_with_params(cfg) |
Free a backend+params config | - |
h_get_name_for_backend(backend) |
Get backend name (const; do not free) | - |
h_get_name_for_backend_with_params(cfg) |
Get backend name string (allocated; must free) | - |
h_get_descriptive_text_for_backend(backend) |
Get descriptive text (const; do not free) | - |
h_get_descriptive_text_for_backend_with_params(cfg) |
Get descriptive text (allocated; must free) | - |
| Function | Description | Example Usage |
|---|---|---|
h_compile(parser, backend, params) |
Compile a parser for a backend | - |
h_compile_for_backend_with_params(parser, cfg) |
Compile using a backend config created from name+params | - |
| Function | Description | Example Usage |
|---|---|---|
h_bit_writer_new(mm__) |
Create a new HBitWriter
|
- |
h_bit_writer_put(w, data, nbits) |
Append nbits bits of data into writer |
- |
h_bit_writer_get_buffer(w, &len) |
Get internal buffer pointer + length (bytes) | - |
h_bit_writer_free(w) |
Free writer and buffer | - |
| Function | Description | Example Usage |
|---|---|---|
h_benchmark(parser, testcases) |
Run parser against testcases across backends; returns results | - |
h_benchmark_report(stream, results) |
Print a report | - |
Low-level helpers used by some printers / registry functions.
| Function | Description | Example Usage |
|---|---|---|
h_append_buf(buf, input, len) |
Append string data to a result buffer | - |
h_append_buf_c(buf, char) |
Append one char | - |
h_append_buf_formatted(buf, fmt, ...) |
Append printf-style formatted text | - |
| Function | Description | Example Usage |
|---|---|---|
h_allocate_token_type(name) |
Allocate a new token type id | - |
h_allocate_token_new(name, unamb_sub, pprint) |
Allocate token type with print functions | - |
h_get_token_type_number(name) |
Lookup token type id by name | - |
h_get_token_type_name(token_type) |
Lookup token type name by id | - |
| Function | Description | Example Usage |
|---|---|---|
h_sloballoc(mem, size) |
Allocator backed by a fixed caller-provided memory region | - |
H_RULE(my_field, h_uint32());H_RULE(my_field, h_int_range(h_bits(3, false), 0, 7));H_RULE(my_field, h_sequence(h_int16(), h_int16(), NULL));HParsedToken *adjust_len(const HParseResult *p, void *user_data) {
return H_MAKE_UINT(p->ast->uint - HEADER_SIZE);
}
H_RULE(my_field,
h_sequence(
h_put_value(h_uint16(), "len"),
h_length_value(h_action(h_free_value("len"), adjust_len, NULL), h_uint8()),
NULL));H_RULE(many_fields, h_many(single_field));H_RULE(type_a, h_sequence(fields_a, h_end_p(), NULL));
H_RULE(type_b, h_sequence(fields_b, h_end_p(), NULL));
HParser *parser = h_left(h_choice(type_a, type_b, NULL), h_end_p());H_RULE(quoted, h_middle(h_ch('"'), h_many1(h_ch_range(0x20, 0x7E)), h_ch('"')));HParser *expr = h_indirect();
H_RULE(atom, h_choice(number, expr, NULL));
h_bind_indirect(expr, h_middle(h_ch('('), atom, h_ch(')')));Learn Hammer
Protocol Examples
NTP
- NTP Overview
- Parsing the Header
- Parsing Data Fields
- Extension Fields and MAC
- Assembling the Parser
- Hex Input Preprocessing
- Running and Testing
DNS
TFTP
- TFTP Overview
- RRQ/WRQ Packets
- DATA Packets
- ACK Packets
- ERROR Packets
- Assembling the Parser
- Running and Testing
References
- Hammer Quick Reference
- Parsing Backends
- Unit Testing
- Using RTEMS
- Extending Hammer
- Adding a New Example
- Adding a New Binding
Further Reading