zpl_toolchain_core
Parser, AST, validator, and glue for consuming generated spec tables.
Part of the zpl-toolchain project.
Parser
- Zero-allocation lexer:
Token<'a>borrows text directly from input (&'a str), eliminating per-token heap allocations. - Longest-match opcode lookup using the opcode trie (embedded in
parser_tables.json) with cachedParserTablesmethods (OnceLock). - Signature-driven argument parsing (joiner, allowEmptyTrailing).
- Handles glued forms (e.g.,
^A0N→f=0,o=N), comments;, field/raw regions. - Explicit state machine:
Mode::Normal,Mode::FieldData,Mode::RawData. - Emits
^XA/^XZas nodes while also delimiting labels. - Safe UTF-8 handling throughout (multi-byte character boundary checks).
AST
Ast { labels: Vec<Label> },Label { nodes: Vec<Node> }.Node::Command { code, args, span } | FieldData { content, hex_escaped, span } | RawData | Trivia.Nodeis#[non_exhaustive]to allow future variants without breaking downstream matches.spanon allNodevariants is a requiredSpan(notOption<Span>).ArgSlot { key, presence, value }with tri-statePresence.Span { start, end }byte span (re-exported fromdiagnosticscrate).
Validator
- Table-driven checks from
spec-tables:- Presence/required args; arity; type validation (
int,float,char); unknown commands. - Numeric/string constraints, enums, conditional range.
- Rounding policy (toMultiple) and profile gates (e.g.,
^PWwidth,^LLheight). - Constraints: requires, incompatible, order (before:/after:), emptyData, note.
- Presence/required args; arity; type validation (
- Spec-driven structural validation via
FieldTrackerusingCommandEntryflags (opens_field,closes_field,requires_field, etc.). - Semantic validation: duplicate
^FN, position bounds, font references,^FHhex escapes (configurable indicator viahex_escapemodule),^GFdata length (with multi-lineRawDatacontinuation support), barcode^FDdata format validation (character set and length/parity rules viafieldDataRules), and more. - Device-level state tracking:
DeviceStatewith unit system (^MU) persisting across labels;convert_to_dots()for unit-aware range validation. - Dynamic prefix/delimiter support:
^CC/~CC/^CT/~CTprefix changes and^CD/~CDdelimiter changes tracked at both lexer and parser levels (lexer re-tokenizes with new delimiter character); commands with non-comma signature joiners (:,.) correctly preserved. - Spec-driven
^Asplit rule viaSplitRulestruct (replaces hardcoded font+orientation splitting).
Usage
- Load
generated/parser_tables.jsonand (optionally) a profile; run parse → validate. - The crate root re-exports the most common entry points for convenience:
- Parser:
parse_str,parse_with_tables,ParseResult - AST:
Ast,Label,Node,ArgSlot,Presence - Emitter:
emit_zpl,strip_spans,EmitConfig,Indent - Diagnostics:
Diagnostic,Span,Severity,codes - Validator:
validate_with_profile,ValidationResult - Tables:
ParserTables - Serialization:
to_pretty_json
- Parser:
- Full module paths (
grammar::parser::parse_str, etc.) remain available for less common types.
Tests
- 255 tests split across focused test files:
parser.rs(61 tests) — tokenization, command recognition, AST structure, field/raw data modes, span tracking, prefix/delimiter, parser diagnostics, error recovery.validator.rs(111 tests) — validation diagnostics, profile constraints, printer gates, media modes, structural/semantic validation, cross-command constraints, barcode field data.emit_roundtrip.rs(23 tests) — formatter round-trip and idempotency.fuzz_smoke.rs(26 tests) — adversarial input and invariant checking.snapshots.rs(11 tests) — golden AST/diagnostic snapshots.samples.rs,cross_command_state.rs,rich_fields.rs,opcode_trie.rs,arg_union.rs— targeted integration tests.
- Shared helpers centralized in
common/mod.rs(extract_codes,find_args,find_diag, profile fixtures). all_diagnostic_ids_have_explanationstest validates all diagnostic codes haveexplain()entries.