sipha_parse/grammar/
mod.rs

1//! Grammar rule definitions.
2//!
3//! This module defines the `GrammarRule` enum, which provides a declarative
4//! way to specify grammar rules. Rules can be combined to build complex
5//! grammars using sequences, choices, repetitions, and more.
6
7mod builder;
8mod evaluator;
9mod validation;
10
11pub use builder::GrammarRuleBuilder;
12pub use evaluator::GrammarRuleParser;
13pub use validation::validate_rule;
14
15use sipha_core::traits::{RuleId, TokenKind};
16pub use sipha_pratt::Precedence;
17
18/// High-level grammar building block.
19///
20/// # Serialization
21///
22/// When the `serde` feature is enabled, this type implements `Serialize` and `Deserialize`.
23/// Note that `K` and `R` must also implement these traits for serialization to work.
24#[derive(Clone, Debug)]
25#[cfg_attr(
26    feature = "serde",
27    derive(serde::Serialize, serde::Deserialize),
28    serde(
29        bound = "K: serde::Serialize + serde::de::DeserializeOwned, R: serde::Serialize + serde::de::DeserializeOwned"
30    )
31)]
32pub enum GrammarRule<K: TokenKind, R: RuleId> {
33    /// Sequence: `a b c`.
34    Sequence(Vec<GrammarRule<K, R>>),
35    /// Choice: `a | b | c`.
36    Choice(Vec<GrammarRule<K, R>>),
37    /// Optional: `a?`.
38    Optional(Box<GrammarRule<K, R>>),
39    /// Zero or more: `a*`.
40    ZeroOrMore(Box<GrammarRule<K, R>>),
41    /// One or more: `a+`.
42    OneOrMore(Box<GrammarRule<K, R>>),
43    /// Range repetition: `a{min,max}`.
44    Range {
45        /// Rule that must repeat.
46        rule: Box<GrammarRule<K, R>>,
47        /// Minimum number of occurrences (inclusive).
48        min: usize,
49        /// Maximum number of occurrences (inclusive).
50        max: usize,
51    },
52    /// Delegate to the Pratt parser for expression parsing.
53    PrattExpr(Precedence),
54    /// Terminal token literal.
55    Token(K),
56    /// Rule reference.
57    Rule(R),
58    /// Conditional rule that depends on the parser position.
59    Conditional {
60        /// Nested rule to evaluate when the condition succeeds.
61        rule: Box<GrammarRule<K, R>>,
62        /// Condition receives the parser position and returns whether the rule
63        /// should run.
64        #[cfg_attr(
65            feature = "serde",
66            serde(skip_serializing, deserialize_with = "deserialize_condition")
67        )]
68        condition: fn(usize) -> bool,
69    },
70    /// Negative lookahead: succeeds if the rule does NOT match.
71    NegativeLookahead(Box<GrammarRule<K, R>>),
72    /// Positive lookahead: succeeds if the rule matches, but doesn't consume input.
73    PositiveLookahead(Box<GrammarRule<K, R>>),
74}
75
76#[cfg(feature = "serde")]
77const DEFAULT_CONDITION: fn(usize) -> bool = |_| false;
78
79#[cfg(feature = "serde")]
80fn deserialize_condition<'de, D>(_deserializer: D) -> Result<fn(usize) -> bool, D::Error>
81where
82    D: serde::Deserializer<'de>,
83{
84    Ok(DEFAULT_CONDITION)
85}