Skip to main content

syn_grammar_model/model/
mod.rs

1// Moved from macros/src/model.rs
2pub mod backend;
3pub mod types;
4
5pub use backend::*;
6pub use types::*;
7
8use crate::parser;
9use proc_macro2::{Span, TokenStream};
10use syn::spanned::Spanned as _;
11use syn::{Attribute, Generics, Ident, ItemUse, Lit, Type};
12
13#[derive(Debug, Clone)]
14pub struct GrammarDefinition {
15    pub name: Ident,
16    pub inherits: Option<Ident>,
17    pub uses: Vec<ItemUse>,
18    pub rules: Vec<Rule>,
19}
20
21#[derive(Debug, Clone)]
22pub struct Rule {
23    pub attrs: Vec<Attribute>,
24    pub is_pub: bool,
25    pub name: Ident,
26    pub generics: Generics,
27    pub params: Vec<(Ident, Option<Type>)>,
28    pub return_type: Type,
29    pub variants: Vec<RuleVariant>,
30}
31
32#[derive(Debug, Clone)]
33pub struct RuleVariant {
34    pub pattern: Vec<ModelPattern>,
35    pub action: TokenStream,
36}
37
38#[derive(Debug, Clone)]
39pub enum ModelPattern {
40    Cut(Span),
41    Lit {
42        binding: Option<Ident>,
43        lit: Lit,
44    },
45    RuleCall {
46        binding: Option<Ident>,
47        rule_name: Ident,
48        args: Vec<ModelPattern>,
49    },
50    Group(Vec<Vec<ModelPattern>>, Span),
51    Bracketed(Vec<ModelPattern>, Span),
52    Braced(Vec<ModelPattern>, Span),
53    Parenthesized(Vec<ModelPattern>, Span),
54    Optional(Box<ModelPattern>, Span),
55    Repeat(Box<ModelPattern>, Span),
56    Plus(Box<ModelPattern>, Span),
57    SpanBinding(Box<ModelPattern>, Ident, Span),
58    Recover {
59        binding: Option<Ident>,
60        body: Box<ModelPattern>,
61        sync: Box<ModelPattern>,
62        span: Span,
63    },
64    Peek(Box<ModelPattern>, Span),
65    Not(Box<ModelPattern>, Span),
66}
67
68impl From<parser::GrammarDefinition> for GrammarDefinition {
69    fn from(p: parser::GrammarDefinition) -> Self {
70        Self {
71            name: p.name,
72            inherits: p.inherits.map(|spec| spec.name),
73            uses: p.uses,
74            rules: p.rules.into_iter().map(Into::into).collect(),
75        }
76    }
77}
78
79impl From<parser::Rule> for Rule {
80    fn from(p: parser::Rule) -> Self {
81        Self {
82            attrs: p.attrs,
83            is_pub: p.is_pub.is_some(),
84            name: p.name,
85            generics: p.generics,
86            params: p
87                .params
88                .into_iter()
89                .map(|param| (param.name, param.ty))
90                .collect(),
91            return_type: p.return_type,
92            variants: p.variants.into_iter().map(Into::into).collect(),
93        }
94    }
95}
96
97impl From<parser::RuleVariant> for RuleVariant {
98    fn from(p: parser::RuleVariant) -> Self {
99        Self {
100            pattern: p.pattern.into_iter().map(Into::into).collect(),
101            action: p.action,
102        }
103    }
104}
105
106impl From<parser::Pattern> for ModelPattern {
107    fn from(p: parser::Pattern) -> Self {
108        use parser::Pattern as P;
109        match p {
110            P::Cut(t) => ModelPattern::Cut(t.span()),
111            P::Lit { binding, lit } => ModelPattern::Lit { binding, lit },
112            P::RuleCall {
113                binding,
114                rule_name,
115                args,
116            } => ModelPattern::RuleCall {
117                binding,
118                rule_name,
119                args: args.into_iter().map(ModelPattern::from).collect(),
120            },
121            P::Group(alts, token) => ModelPattern::Group(
122                alts.into_iter()
123                    .map(|seq| seq.into_iter().map(ModelPattern::from).collect())
124                    .collect(),
125                token.span.join(),
126            ),
127            P::Bracketed(p, token) => ModelPattern::Bracketed(
128                p.into_iter().map(ModelPattern::from).collect(),
129                token.span.join(),
130            ),
131            P::Braced(p, token) => ModelPattern::Braced(
132                p.into_iter().map(ModelPattern::from).collect(),
133                token.span.join(),
134            ),
135            P::Parenthesized(p, _, token) => ModelPattern::Parenthesized(
136                p.into_iter().map(ModelPattern::from).collect(),
137                token.span.join(),
138            ),
139            P::Optional(p, token) => {
140                ModelPattern::Optional(Box::new(ModelPattern::from(*p)), token.span())
141            }
142            P::Repeat(p, token) => {
143                ModelPattern::Repeat(Box::new(ModelPattern::from(*p)), token.span())
144            }
145            P::Plus(p, token) => ModelPattern::Plus(Box::new(ModelPattern::from(*p)), token.span()),
146            P::SpanBinding(p, ident, token) => {
147                ModelPattern::SpanBinding(Box::new(ModelPattern::from(*p)), ident, token.span)
148            }
149            P::Recover {
150                binding,
151                body,
152                sync,
153                kw_token,
154            } => ModelPattern::Recover {
155                binding,
156                body: Box::new(ModelPattern::from(*body)),
157                sync: Box::new(ModelPattern::from(*sync)),
158                span: kw_token.span(),
159            },
160            P::Peek(p, token) => ModelPattern::Peek(Box::new(ModelPattern::from(*p)), token.span()),
161            P::Not(p, token) => ModelPattern::Not(Box::new(ModelPattern::from(*p)), token.span()),
162        }
163    }
164}
165
166impl ModelPattern {
167    pub fn span(&self) -> Span {
168        match self {
169            ModelPattern::Cut(s) => *s,
170            ModelPattern::Lit { lit, .. } => lit.span(),
171            ModelPattern::RuleCall { rule_name, .. } => rule_name.span(),
172            ModelPattern::Optional(_, s)
173            | ModelPattern::Repeat(_, s)
174            | ModelPattern::Plus(_, s) => *s,
175            ModelPattern::SpanBinding(_, _, s) => *s,
176            ModelPattern::Recover { span, .. } => *span,
177            ModelPattern::Group(_, s) => *s,
178            ModelPattern::Bracketed(_, s)
179            | ModelPattern::Braced(_, s)
180            | ModelPattern::Parenthesized(_, s) => *s,
181            ModelPattern::Peek(_, s) | ModelPattern::Not(_, s) => *s,
182        }
183    }
184}