wagon_parser/parser/
atom.rs1use std::fmt::Display;
2use std::hash::Hash;
3use std::write;
4
5use super::{Parse, LexerBridge, ParseResult, Tokens, WagParseError, Ident, SpannableNode, Spannable, expression::Expression, ResultNext};
6use super::helpers::{between, between_right};
7use crate::either_token;
8use crate::firstpass::{GetReqAttributes, RewriteToSynth};
9
10use wagon_lexer::math::Math;
11use wagon_macros::match_error;
12use wagon_utils::ConversionError;
13use wagon_value::{Valueable, Value, RecursiveValue};
14
15use ordered_float::NotNan;
16
17use wagon_macros::new_unspanned;
18
19#[derive(PartialEq, Debug, Eq, Hash, Clone)]
20pub struct Dictionary(Ident, Expression);
25
26impl Dictionary {
27 #[must_use]
29 pub const fn deconstruct(&self) -> (&Ident, &Expression) {
30 (&self.0, &self.1)
31 }
32}
33
34#[derive(PartialEq, Debug, Eq, Hash, Clone)]
35#[new_unspanned]
36pub enum Atom {
54 Ident(Ident),
56 Dict(Dictionary),
58 LitBool(bool),
60 LitNum(i32),
62 LitFloat(NotNan<f32>),
64 LitString(String),
66 Group(SpannableNode<Expression>)
68}
69
70impl Parse for Atom {
71
72 fn parse(lexer: &mut LexerBridge) -> ParseResult<Self> {
73 match_error!(match lexer.next_result()? {
74 #[expect("identifier or dictionary")]
75 either_token!(Identifier(x)) => {
76 if let Ok(inner) = between(lexer, &Tokens::MathToken(Math::LBr), &Tokens::MathToken(Math::RBr)) {
77 Ok(Self::Dict(Dictionary(x, inner)))
78 } else {
79 Ok(Self::Ident(x))
80 }
81 },
82 Tokens::MathToken(Math::LitBool(x)) => Ok(Self::LitBool(x)),
83 Tokens::MathToken(Math::LitInt(x)) => Ok(Self::LitNum(x)),
84 Tokens::MathToken(Math::LitFloat(x)) => {
85 match NotNan::new(x) {
86 Ok(f) => Ok(Self::LitFloat(f)),
87 Err(e) => Err(WagParseError::FloatError(e, lexer.span())),
88 }
89 },
90 #[expect("string")]
91 either_token!(LitString(x)) => Ok(Self::LitString(x)),
92 Tokens::MathToken(Math::LPar) => {
93 let resp = between_right(lexer, &Tokens::MathToken(Math::RPar))?;
94 Ok(Self::Group(resp))
95 },
96 })
97 }
98}
99
100impl GetReqAttributes for Atom {
101 fn get_req_attributes(&self) -> crate::firstpass::ReqAttributes {
102 match self {
103 Self::Ident(i) => {
104 let mut req = crate::firstpass::ReqAttributes::new();
105 req.insert(i.clone().into());
106 req
107 },
108 Self::Group(e) => e.get_req_attributes(),
109 _ => crate::firstpass::ReqAttributes::new()
110 }
111 }
112}
113
114impl RewriteToSynth for Atom {
115 fn rewrite_to_synth(&mut self) -> crate::firstpass::ReqAttributes {
116 match self {
117 Self::Ident(i) => {
118 let mut req = crate::firstpass::ReqAttributes::new();
119 let as_synth = i.to_synth();
120 req.insert(i.clone().into());
121 *i = as_synth;
122 req
123 },
124 Self::Group(e) => e.rewrite_to_synth(),
125 _ => crate::firstpass::ReqAttributes::new()
126 }
127 }
128}
129
130impl Display for Atom {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 match self {
133 Self::Ident(x) => write!(f, "{x}"),
134 Self::Dict(x) => write!(f, "{x}"),
135 Self::LitBool(x) => write!(f, "{x}"),
136 Self::LitNum(x) => write!(f, "{x}"),
137 Self::LitFloat(x) => write!(f, "{x}"),
138 Self::LitString(x) => write!(f, "\"{x}\""),
139 Self::Group(x) => write!(f, "({x})"),
140 }
141 }
142}
143
144impl Display for Dictionary {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 write!(f, "{}[{}]", self.0, self.1)
147 }
148}
149
150impl<T: Valueable> TryFrom<Atom> for Value<T> {
151 type Error = ConversionError<Atom, Self>;
152
153 fn try_from(value: Atom) -> Result<Self, Self::Error> {
154 match value {
155 Atom::LitBool(b) => Ok(Self::Bool(b)),
156 Atom::LitNum(i) => Ok(Self::Natural(i)),
157 Atom::LitFloat(f) => Ok(Self::Float(f)),
158 Atom::LitString(s) => Ok(Self::String(s)),
159 other => Err(ConversionError::new(other)),
160 }
161 }
162}
163
164impl TryFrom<Atom> for RecursiveValue {
165 type Error = ConversionError<Atom, Self>;
166
167 fn try_from(value: Atom) -> Result<Self, Self::Error> {
168 Ok(Self::from(Value::try_from(value).map_err(wagon_utils::ConversionError::convert)?))
169 }
170}