wagon_parser/parser/
symbol.rs1
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]
22pub enum Symbol {
35 NonTerminal(SpannableNode<Ident>, Vec<SpannableNode<Ident>>),
37 Assignment(Vec<SpannableNode<Assignment>>),
39 Terminal(SpannableNode<Terminal>),
41 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 #[must_use]
76 pub const fn is_terminal(&self) -> bool {
77 matches!(self, Self::Terminal(..) | Self::Assignment(..) | Self::Epsilon)
78 }
79
80 #[must_use]
82 pub const fn is_assignment(&self) -> bool {
83 matches!(self, Self::Assignment(..))
84 }
85
86 #[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 #[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 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) => { 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}