bluejay_parser/ast/
value.rs

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