bluejay_parser/ast/
value.rs

1use crate::ast::{FromTokens, ParseError, Tokens};
2use crate::lexical_token::{
3    FloatValue, IntValue, LexicalToken, Name, PunctuatorType, StringValue, Variable,
4};
5use crate::{HasSpan, Span};
6use bluejay_core::{
7    AsIter, ListValue as CoreListValue, ObjectValue as CoreObjectValue, Value as CoreValue,
8    ValueReference,
9};
10
11#[derive(Debug)]
12pub enum Value<'a, const CONST: bool> {
13    Variable(Variable<'a>),
14    Integer(IntValue),
15    Float(FloatValue),
16    String(StringValue<'a>),
17    Boolean(BooleanValue),
18    Null(Name<'a>),
19    Enum(Name<'a>),
20    List(ListValue<'a, CONST>),
21    Object(ObjectValue<'a, CONST>),
22}
23
24impl<'a, const CONST: bool> CoreValue<CONST> for Value<'a, CONST> {
25    type List = ListValue<'a, CONST>;
26    type Object = ObjectValue<'a, CONST>;
27    type Variable = Variable<'a>;
28
29    fn as_ref(&self) -> ValueReference<'_, CONST, Self> {
30        match self {
31            Self::Variable(v) => ValueReference::Variable(v),
32            Self::Integer(i) => ValueReference::Integer(i.value()),
33            Self::Float(f) => ValueReference::Float(f.value()),
34            Self::String(s) => ValueReference::String(s.as_ref()),
35            Self::Boolean(b) => ValueReference::Boolean(b.value()),
36            Self::Null(_) => ValueReference::Null,
37            Self::Enum(e) => ValueReference::Enum(e.as_ref()),
38            Self::List(l) => ValueReference::List(l),
39            Self::Object(o) => ValueReference::Object(o),
40        }
41    }
42}
43
44impl<'a, const CONST: bool> FromTokens<'a> for Value<'a, CONST> {
45    fn from_tokens(tokens: &mut impl Tokens<'a>) -> Result<Self, ParseError> {
46        match tokens.next() {
47            Some(LexicalToken::IntValue(int)) => Ok(Self::Integer(int)),
48            Some(LexicalToken::FloatValue(float)) => Ok(Self::Float(float)),
49            Some(LexicalToken::StringValue(string)) => Ok(Self::String(string)),
50            Some(LexicalToken::Name(name)) => Ok(match name.as_str() {
51                "true" => Self::Boolean(BooleanValue {
52                    value: true,
53                    span: name.into(),
54                }),
55                "false" => Self::Boolean(BooleanValue {
56                    value: false,
57                    span: name.into(),
58                }),
59                "null" => Self::Null(name),
60                _ => Self::Enum(name),
61            }),
62            Some(LexicalToken::VariableName(name)) => {
63                if CONST {
64                    Err(ParseError::UnexpectedToken { span: name.into() })
65                } else {
66                    Ok(Self::Variable(name))
67                }
68            }
69            Some(LexicalToken::Punctuator(p))
70                if p.r#type() == PunctuatorType::OpenSquareBracket =>
71            {
72                let open_span = p.span().clone();
73                let mut list: Vec<Self> = Vec::new();
74                let close_span = loop {
75                    if let Some(close_span) =
76                        tokens.next_if_punctuator(PunctuatorType::CloseSquareBracket)
77                    {
78                        break close_span;
79                    }
80                    list.push(Self::from_tokens(tokens)?);
81                };
82                let span = open_span.merge(&close_span);
83                Ok(Self::List(ListValue {
84                    elements: list,
85                    span,
86                }))
87            }
88            Some(LexicalToken::Punctuator(p)) if p.r#type() == PunctuatorType::OpenBrace => {
89                let open_span = p.span().clone();
90                let mut object: Vec<_> = Vec::new();
91                let close_span = loop {
92                    if let Some(close_span) = tokens.next_if_punctuator(PunctuatorType::CloseBrace)
93                    {
94                        break close_span;
95                    }
96                    let name = tokens.expect_name()?;
97                    tokens.expect_punctuator(PunctuatorType::Colon)?;
98                    let value = Self::from_tokens(tokens)?;
99                    object.push((name, value));
100                };
101                let span = open_span.merge(&close_span);
102                Ok(Self::Object(ObjectValue {
103                    fields: object,
104                    span,
105                }))
106            }
107            token => Err(token
108                .map(|token| ParseError::UnexpectedToken { span: token.into() })
109                .unwrap_or_else(|| tokens.unexpected_eof())),
110        }
111    }
112}
113
114impl<'a, const CONST: bool> HasSpan for Value<'a, CONST> {
115    fn span(&self) -> &Span {
116        match self {
117            Self::Boolean(b) => &b.span,
118            Self::Enum(e) => e.span(),
119            Self::Float(f) => f.span(),
120            Self::Integer(i) => i.span(),
121            Self::List(l) => &l.span,
122            Self::Null(n) => n.span(),
123            Self::Object(o) => &o.span,
124            Self::String(s) => s.span(),
125            Self::Variable(v) => v.span(),
126        }
127    }
128}
129
130pub type ConstValue<'a> = Value<'a, true>;
131pub type VariableValue<'a> = Value<'a, false>;
132
133#[derive(Debug)]
134pub struct BooleanValue {
135    value: bool,
136    span: Span,
137}
138
139impl BooleanValue {
140    fn value(&self) -> bool {
141        self.value
142    }
143}
144
145#[derive(Debug)]
146pub struct ListValue<'a, const CONST: bool> {
147    elements: Vec<Value<'a, CONST>>,
148    span: Span,
149}
150
151impl<'a, const CONST: bool> CoreListValue<CONST> for ListValue<'a, CONST> {
152    type Value = Value<'a, CONST>;
153}
154
155impl<'a, const CONST: bool> AsIter for ListValue<'a, CONST> {
156    type Item = Value<'a, CONST>;
157    type Iterator<'b> = std::slice::Iter<'b, Self::Item> where 'a: 'b;
158
159    fn iter(&self) -> Self::Iterator<'_> {
160        self.elements.iter()
161    }
162}
163
164#[derive(Debug)]
165pub struct ObjectValue<'a, const CONST: bool> {
166    fields: Vec<(Name<'a>, Value<'a, CONST>)>,
167    span: Span,
168}
169
170impl<'a, const CONST: bool> CoreObjectValue<CONST> for ObjectValue<'a, CONST> {
171    type Key = Name<'a>;
172    type Value = Value<'a, CONST>;
173    type Iterator<'b> = std::iter::Map<std::slice::Iter<'b, (Name<'a>, Value<'a, CONST>)>, fn(&'b (Name<'a>, Value<'a, CONST>)) -> (&'b Name<'a>, &'b Value<'a, CONST>)> where 'a: 'b;
174
175    fn iter(&self) -> Self::Iterator<'_> {
176        self.fields.iter().map(|(key, value)| (key, value))
177    }
178}
179
180impl<'a, const CONST: bool> AsIter for ObjectValue<'a, CONST> {
181    type Item = (Name<'a>, Value<'a, CONST>);
182    type Iterator<'b> = std::slice::Iter<'b, (Name<'a>, Value<'a, CONST>)> where 'a: 'b;
183
184    fn iter(&self) -> Self::Iterator<'_> {
185        self.fields.iter()
186    }
187}
188
189impl<'a, const CONST: bool> HasSpan for ObjectValue<'a, CONST> {
190    fn span(&self) -> &Span {
191        &self.span
192    }
193}