#model-parser #parser #grammar #ebnf #syn

syn-grammar-model

Shared model and parser for syn-grammar

8 releases (breaking)

new 0.8.0 Feb 19, 2026
0.7.1 Feb 17, 2026
0.6.0 Feb 8, 2026
0.5.0 Feb 7, 2026
0.2.0 Jan 31, 2026

#232 in Parser tooling


Used in 2 crates

MIT/Apache

70KB
2K SLoC

syn-grammar-model

Shared semantic model and parser for syn-grammar.

This crate provides the core logic for parsing the grammar! { ... } DSL, validating it, and transforming it into a semantic model. It is designed to be reusable for different backends (e.g., a winnow generator or a documentation generator).

Architecture

The processing pipeline consists of four stages:

  1. Parsing (parser): Converts the raw TokenStream into a syntactic AST (parser::GrammarDefinition). This handles the concrete syntax of the DSL.
  2. Transformation (model): Converts the syntactic AST into a semantic model (model::GrammarDefinition). This simplifies the structure (e.g., flattening groups, resolving inheritance placeholders).
  3. Validation (validator): Checks the semantic model for errors, such as undefined rules, argument mismatches, or invalid token usage.
  4. Analysis (analysis): Provides helper functions to query the model, such as detecting left-recursion, collecting custom keywords, or finding "Cut" operators.

Usage

If you are building a custom backend for syn-grammar, use the pipeline as follows:

use syn_grammar_model::{parser, model, validator, analysis};
use syn::parse_macro_input;
use proc_macro::TokenStream;

#[proc_macro]
pub fn my_grammar_backend(input: TokenStream) -> TokenStream {
    // 1. Parse: TokenStream -> Syntactic AST
    let p_ast = parse_macro_input!(input as parser::GrammarDefinition);

    // 2. Transform: Syntactic AST -> Semantic Model
    let m_ast: model::GrammarDefinition = p_ast.into();

    // 3. Validate: Check for semantic errors
    if let Err(e) = validator::validate(&m_ast) {
        return e.to_compile_error().into();
    }

    // 4. Analyze & Generate
    // e.g. Collect keywords to generate a module for them
    let keywords = analysis::collect_custom_keywords(&m_ast);
    
    // ... generate your code ...
    TokenStream::new()
}

Dependencies

~130–510KB
~12K SLoC