wagon_parser/parser/
symbol.rs

1
2use crate::firstpass::GetReqAttributes;
3use crate::firstpass::ReqAttributes;
4use crate::firstpass::RewriteToSynth;
5use crate::parser::Span;
6use std::fmt::Display;
7use std::write;
8
9use super::helpers::between_sep;
10use super::CallingArgs;
11use super::{LexerBridge, Parse, ParseResult, Peek, ResultPeek, SpannableNode, Tokens};
12use wagon_lexer::{math::Math, productions::Productions};
13
14use super::terminal::Terminal;
15use super::assignment::Assignment;
16use super::Ident;
17
18use wagon_macros::new_unspanned;
19
20#[derive(PartialEq, Debug, Eq, Hash, Clone)]
21#[new_unspanned]
22/// A symbol in a [`Chunk`][super::chunk::Chunk].
23///
24/// A symbol is any individual element of a `Chunk`.
25///
26/// # Grammar
27/// <span><pre>
28/// [Symbol] -> [Ident] NTArgs?
29///        |  [Terminal]
30///        |  (`"{"` [Assignment]* `"}"`)?
31///        |  
32///        ;
33/// </pre></span>
34pub enum Symbol {
35    /// A non-terminal with optional parameters.
36	NonTerminal(SpannableNode<Ident>, Vec<SpannableNode<Ident>>),
37    /// A list of [`Assignment`] enclosed by `{}`.
38	Assignment(Vec<SpannableNode<Assignment>>),
39    /// A Terminal.
40	Terminal(SpannableNode<Terminal>),
41    /// Nothing.
42    Epsilon
43}
44
45impl Parse for Symbol {
46    fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> where Self: Sized {
47        match lexer.peek_result()? {
48        	Tokens::ProductionToken(Productions::Identifier(_)) => {
49                let ident = SpannableNode::parse(lexer)?;
50                let args = if lexer.peek() == Some(&Ok(Tokens::ProductionToken(Productions::Lt))) {
51                    between_sep(lexer, &Tokens::ProductionToken(Productions::Lt), &Tokens::ProductionToken(Productions::Gt), Tokens::ProductionToken(Productions::Comma))?
52                } else {
53                    Vec::new()
54                };
55    			Ok(Self::NonTerminal(ident, args))
56        	},
57        	Tokens::ProductionToken(Productions::LCur) => {
58                lexer.next();
59                Ok(Self::Assignment(SpannableNode::parse_sep_end(lexer, Tokens::MathToken(Math::Semi), Tokens::MathToken(Math::RCur))?))
60        	},
61        	_ => Ok(Self::Terminal(SpannableNode::parse(lexer)?))
62        }
63    }
64}
65
66impl Default for Symbol {
67    fn default() -> Self {
68        Self::Epsilon
69    }
70}
71
72impl Symbol {
73
74    /// Check if this symbol is not a non-terminal.
75    #[must_use] 
76    pub const fn is_terminal(&self) -> bool {
77        matches!(self, Self::Terminal(..) | Self::Assignment(..) | Self::Epsilon)
78    }
79
80    /// Check if this symbol is an [`Assignment`].
81    #[must_use] 
82    pub const fn is_assignment(&self) -> bool {
83        matches!(self, Self::Assignment(..))
84    }
85
86    /// Create a symbol which is just a [`Terminal::LitString`] representing the input parameter.
87    #[must_use] 
88    pub fn simple_terminal(ident: &str) -> Self {
89        Self::Terminal(SpannableNode::new(Terminal::LitString(ident.to_string()), 0..ident.len()))
90    }
91
92    /// Create a symbol which is just a non-terminal [`Ident::Unknown`] with no arguments, representing the input parameter.
93    #[must_use] 
94    pub fn simple_ident(ident: &str) -> Self {
95        Self::NonTerminal(SpannableNode::new(Ident::Unknown(ident.to_string()), 0..ident.len()), Vec::new())
96    }
97
98    /// Create a symbol which is just a spanned non-terminal [`Ident::Unknown`].
99    // pub(crate) fn simple_ident_spanned(ident: &str, span: Span) -> SpannableNode<Self> {
100    //     Self::simple_ident_spanned_with_args(ident, span, Vec::new())
101    // }
102
103    pub(crate) fn simple_ident_spanned_with_args(ident: &str, span: Span, args: Vec<SpannableNode<Ident>>) -> SpannableNode<Self> {
104        SpannableNode::new(Self::NonTerminal(SpannableNode::new(Ident::Unknown(ident.to_string()), span.clone()), args), span)
105    }
106
107    pub(crate) fn rewrite(&mut self) -> ReqAttributes {
108        match self {
109            Self::NonTerminal(_, v) => {
110                let mut req = ReqAttributes::with_capacity(v.len());
111                for i in v.iter_mut() {
112                    match &i.node {
113                        Ident::Inherit(s) | Ident::Local(s) | Ident::Unknown(s) => { // This happens in EBNF rewrites. Every change in EBNF created rules must be passed up.
114                            i.node = Ident::Synth(s.clone());
115                        },
116                        Ident::Synth(_) => {}
117                    }
118                    if !req.contains(i) {
119                        req.insert(i.clone());
120                    }
121                }
122                req
123            },
124            Self::Assignment(v) => {
125                let mut req = ReqAttributes::new();
126                for a in v {
127                    req.extend(a.rewrite_to_synth());
128                }
129                req
130            }
131            _ => ReqAttributes::new()
132        }
133    }
134
135    pub(crate) fn calling_args(&self) -> CallingArgs {
136        match self {
137            Self::NonTerminal(_, v) => v.clone(),
138            Self::Assignment(v) => {
139                let mut req = ReqAttributes::new();
140                for a in v {
141                    req.extend(a.get_req_attributes());
142                }
143                req.into_iter().collect()
144            }
145            _ => CallingArgs::new()
146        }
147    }
148}
149
150impl GetReqAttributes for Symbol {
151    fn get_req_attributes(&self) -> ReqAttributes {
152        self.calling_args().into_iter().collect()
153    }
154}
155
156use itertools::Itertools;
157impl Display for Symbol {
158    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159        match self {
160            Self::NonTerminal(i, args) => {
161                if args.is_empty() {
162                    write!(f, "{i}")
163                } else {
164                    write!(f, "{i}<{}>", args.iter().join(", "))
165                }
166            }
167            Self::Assignment(i) => write!(f, "{{{}}}", i.iter().join("; ")),
168            Self::Terminal(i) => write!(f, "{i}"),
169            Self::Epsilon => write!(f, "ε"),
170        }
171    }
172}