Repository navigation
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