use crate::firstpass::GetReqAttributes;
use crate::firstpass::ReqAttributes;
use crate::firstpass::RewriteToSynth;
use crate::parser::Span;
use std::fmt::Display;
use std::write;
use super::helpers::between_sep;
use super::CallingArgs;
use super::{LexerBridge, Parse, ParseResult, Peek, ResultPeek, SpannableNode, Tokens};
use wagon_lexer::{math::Math, productions::Productions};
use super::terminal::Terminal;
use super::assignment::Assignment;
use super::Ident;
use wagon_macros::new_unspanned;
#[derive(PartialEq, Debug, Eq, Hash, Clone)]
#[new_unspanned]
pub enum Symbol {
NonTerminal(SpannableNode<Ident>, Vec<SpannableNode<Ident>>),
Assignment(Vec<SpannableNode<Assignment>>),
Terminal(SpannableNode<Terminal>),
Epsilon
}
impl Parse for Symbol {
fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> where Self: Sized {
match lexer.peek_result()? {
Tokens::ProductionToken(Productions::Identifier(_)) => {
let ident = SpannableNode::parse(lexer)?;
let args = if lexer.peek() == Some(&Ok(Tokens::ProductionToken(Productions::Lt))) {
between_sep(lexer, &Tokens::ProductionToken(Productions::Lt), &Tokens::ProductionToken(Productions::Gt), Tokens::ProductionToken(Productions::Comma))?
} else {
Vec::new()
};
Ok(Self::NonTerminal(ident, args))
},
Tokens::ProductionToken(Productions::LCur) => {
lexer.next();
Ok(Self::Assignment(SpannableNode::parse_sep_end(lexer, Tokens::MathToken(Math::Semi), Tokens::MathToken(Math::RCur))?))
},
_ => Ok(Self::Terminal(SpannableNode::parse(lexer)?))
}
}
}
impl Default for Symbol {
fn default() -> Self {
Self::Epsilon
}
}
impl Symbol {
#[must_use]
pub const fn is_terminal(&self) -> bool {
matches!(self, Self::Terminal(..) | Self::Assignment(..) | Self::Epsilon)
}
#[must_use]
pub const fn is_assignment(&self) -> bool {
matches!(self, Self::Assignment(..))
}
#[must_use]
pub fn simple_terminal(ident: &str) -> Self {
Self::Terminal(SpannableNode::new(Terminal::LitString(ident.to_string()), 0..ident.len()))
}
#[must_use]
pub fn simple_ident(ident: &str) -> Self {
Self::NonTerminal(SpannableNode::new(Ident::Unknown(ident.to_string()), 0..ident.len()), Vec::new())
}
pub(crate) fn simple_ident_spanned_with_args(ident: &str, span: Span, args: Vec<SpannableNode<Ident>>) -> SpannableNode<Self> {
SpannableNode::new(Self::NonTerminal(SpannableNode::new(Ident::Unknown(ident.to_string()), span.clone()), args), span)
}
pub(crate) fn rewrite(&mut self) -> ReqAttributes {
match self {
Self::NonTerminal(_, v) => {
let mut req = ReqAttributes::with_capacity(v.len());
for i in v.iter_mut() {
match &i.node {
Ident::Inherit(s) | Ident::Local(s) | Ident::Unknown(s) => { i.node = Ident::Synth(s.clone());
},
Ident::Synth(_) => {}
}
if !req.contains(i) {
req.insert(i.clone());
}
}
req
},
Self::Assignment(v) => {
let mut req = ReqAttributes::new();
for a in v {
req.extend(a.rewrite_to_synth());
}
req
}
_ => ReqAttributes::new()
}
}
pub(crate) fn calling_args(&self) -> CallingArgs {
match self {
Self::NonTerminal(_, v) => v.clone(),
Self::Assignment(v) => {
let mut req = ReqAttributes::new();
for a in v {
req.extend(a.get_req_attributes());
}
req.into_iter().collect()
}
_ => CallingArgs::new()
}
}
}
impl GetReqAttributes for Symbol {
fn get_req_attributes(&self) -> ReqAttributes {
self.calling_args().into_iter().collect()
}
}
use itertools::Itertools;
impl Display for Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NonTerminal(i, args) => {
if args.is_empty() {
write!(f, "{i}")
} else {
write!(f, "{i}<{}>", args.iter().join(", "))
}
}
Self::Assignment(i) => write!(f, "{{{}}}", i.iter().join("; ")),
Self::Terminal(i) => write!(f, "{i}"),
Self::Epsilon => write!(f, "ε"),
}
}
}