Skip to main content

rantlr_core/
ast.rs

1//! Grammar AST shapes produced by the parser and consumed by linter / codegen.
2
3use serde::Serialize;
4
5use crate::span::Span;
6use crate::token::BuiltinType;
7
8/// Top-level compiled grammar unit.
9#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
10pub struct Grammar {
11    pub name: String,
12    #[serde(skip)]
13    pub name_span: Span,
14    pub items: Vec<GrammarItem>,
15    #[serde(skip)]
16    pub span: Span,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
20#[serde(tag = "kind", rename_all = "snake_case")]
21pub enum GrammarItem {
22    Token(TokenDecl),
23    Rule(RuleDecl),
24    Example(ExampleDecl),
25    Import(ImportDecl),
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
29pub struct TokenDecl {
30    pub name: String,
31    #[serde(skip)]
32    pub name_span: Span,
33    pub body: TokenBody,
34    pub skip: bool,
35    #[serde(skip)]
36    pub span: Span,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
40#[serde(tag = "kind", content = "value", rename_all = "snake_case")]
41pub enum TokenBody {
42    Builtin(BuiltinType),
43    /// Explicit literal pattern, e.g. `token Plus = "+";`
44    Literal(String),
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
48pub struct RuleDecl {
49    pub name: String,
50    #[serde(skip)]
51    pub name_span: Span,
52    pub body: Expr,
53    #[serde(skip)]
54    pub span: Span,
55}
56
57#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
58#[serde(tag = "kind", rename_all = "snake_case")]
59pub enum Expr {
60    /// Alternatives separated by `|`.
61    Alt { alts: Vec<Expr> },
62    /// Juxtaposed sequence.
63    Seq { items: Vec<Expr> },
64    /// `match a | b | c` — first-class choice of match arms.
65    Match { arms: Vec<Expr> },
66    /// `repeat { ... }` or `repeat(0..) { ... }`
67    Repeat {
68        min: Option<u64>,
69        max: Option<u64>,
70        body: Box<Expr>,
71    },
72    /// `optional { ... }`
73    Optional { body: Box<Expr> },
74    /// Reference to a rule or token name.
75    Ref {
76        name: String,
77        #[serde(skip)]
78        span: Span,
79    },
80    /// String literal (auto-inferred token).
81    Literal {
82        value: String,
83        #[serde(skip)]
84        span: Span,
85    },
86    Group { body: Box<Expr> },
87}
88
89impl Expr {
90    pub fn seq(mut items: Vec<Expr>) -> Self {
91        match items.len() {
92            0 => Self::Seq { items },
93            1 => items.remove(0),
94            _ => Self::Seq { items },
95        }
96    }
97
98    pub fn alt(mut alts: Vec<Expr>) -> Self {
99        match alts.len() {
100            0 => Self::Alt { alts },
101            1 => alts.remove(0),
102            _ => Self::Alt { alts },
103        }
104    }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
108pub struct ExampleDecl {
109    pub label: Option<String>,
110    pub input: String,
111    pub expect: Option<String>,
112    #[serde(skip)]
113    pub span: Span,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
117pub struct ImportDecl {
118    pub path: String,
119    #[serde(skip)]
120    pub span: Span,
121}