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}