1use crate::{
2 VonLanguage,
3 ast::{VonArray, VonBoolean, VonEnum, VonField, VonNull, VonNumber, VonObject, VonRoot, VonString, VonValue},
4 lexer::{VonLexer, VonTokenType},
5 parser::{VonElementType, VonParser},
6};
7use oak_core::{Builder, BuilderCache, GreenNode, Lexer, OakDiagnostics, OakError, Parser, SourceText, TextEdit, parser::session::ParseSession, source::Source};
8
9#[derive(Clone)]
11pub struct VonBuilder<'config> {
12 config: &'config VonLanguage,
13}
14
15impl<'config> VonBuilder<'config> {
16 pub fn new(config: &'config VonLanguage) -> Self {
18 Self { config }
19 }
20}
21
22impl<'config> Builder<VonLanguage> for VonBuilder<'config> {
23 fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<VonLanguage>) -> OakDiagnostics<VonRoot> {
24 let parser = VonParser::new(self.config);
25 let lexer = VonLexer::new(self.config);
26
27 let mut parse_session = ParseSession::<VonLanguage>::default();
28 lexer.lex(source, edits, &mut parse_session);
29 let parse_result = parser.parse(source, edits, &mut parse_session);
30
31 match parse_result.result {
32 Ok(green_tree) => {
33 let text = source.get_text_in((0..source.length()).into());
34 let source_text = SourceText::new(text.into_owned());
35 match self.build_root(&green_tree, &source_text) {
36 Ok(ast_root) => OakDiagnostics { result: Ok(ast_root), diagnostics: parse_result.diagnostics },
37 Err(build_error) => {
38 let mut diagnostics = parse_result.diagnostics;
39 diagnostics.push(build_error.clone());
40 OakDiagnostics { result: Err(build_error), diagnostics }
41 }
42 }
43 }
44 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
45 }
46 }
47}
48
49impl<'config> VonBuilder<'config> {
50 fn build_root<'a>(&self, green_tree: &GreenNode<'a, VonLanguage>, source: &SourceText) -> Result<VonRoot, OakError> {
51 let root_node = match green_tree.children.first() {
53 Some(oak_core::GreenTree::Node(n)) => n,
54 _ => return Err(OakError::unexpected_eof(0, None)),
55 };
56
57 let value = self.build_value(root_node, 0, source)?;
58 Ok(VonRoot { value })
59 }
60
61 fn build_value<'a>(&self, node: &GreenNode<'a, VonLanguage>, offset: usize, source: &SourceText) -> Result<VonValue, OakError> {
62 let span: oak_core::Range<usize> = (offset..offset + node.byte_length as usize).into();
63
64 match node.kind {
65 VonElementType::Object => {
66 let mut fields = Vec::new();
67 let mut current_offset = offset;
68 for child in node.children {
69 match child {
70 oak_core::GreenTree::Node(n) => {
71 if n.kind == VonElementType::ObjectEntry {
72 fields.push(self.build_field(n, current_offset, source)?);
73 }
74 current_offset += n.byte_length as usize;
75 }
76 oak_core::GreenTree::Leaf(l) => {
77 current_offset += l.length as usize;
78 }
79 }
80 }
81 Ok(VonValue::Object(VonObject { fields, span }))
82 }
83 VonElementType::Array => {
84 let mut elements = Vec::new();
85 let mut current_offset = offset;
86 for child in node.children {
87 match child {
88 oak_core::GreenTree::Node(n) => {
89 if n.kind == VonElementType::ArrayElement {
90 elements.push(self.build_value(n, current_offset, source)?);
91 }
92 current_offset += n.byte_length as usize;
93 }
94 oak_core::GreenTree::Leaf(l) => {
95 current_offset += l.length as usize;
96 }
97 }
98 }
99 Ok(VonValue::Array(VonArray { elements, span }))
100 }
101 VonElementType::Enum => {
102 let mut variant = None;
103 let mut payload = None;
104 let mut current_offset = offset;
105 for child in node.children {
106 match child {
107 oak_core::GreenTree::Node(n) => {
108 payload = Some(Box::new(self.build_value(n, current_offset, source)?));
109 current_offset += n.byte_length as usize;
110 }
111 oak_core::GreenTree::Leaf(l) => {
112 if l.kind == VonTokenType::Identifier {
113 let v_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
114 variant = Some(source.get_text_in(v_span).to_string());
115 }
116 current_offset += l.length as usize;
117 }
118 }
119 }
120 let variant = variant.ok_or_else(|| OakError::expected_token("Variant", span.start, None))?;
121 Ok(VonValue::Enum(VonEnum { variant, payload, span }))
122 }
123 VonElementType::Value | VonElementType::ArrayElement | VonElementType::Root => {
124 let mut current_offset = offset;
125 for child in node.children {
126 if let oak_core::GreenTree::Node(n) = child {
127 return self.build_value(n, current_offset, source);
128 }
129 else if let oak_core::GreenTree::Leaf(l) = child {
130 if l.kind == VonTokenType::StringLiteral {
131 let s_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
132 let mut text = source.get_text_in(s_span.clone());
133 let is_raw = text.starts_with("raw") && (text[3..].starts_with('"') || text[3..].starts_with('\''));
135 if is_raw {
136 match text {
137 std::borrow::Cow::Borrowed(s) => text = std::borrow::Cow::Borrowed(&s[3..]),
138 std::borrow::Cow::Owned(ref mut s) => {
139 s.drain(..3);
140 }
141 }
142 }
143 let quote_char = text.chars().next().unwrap();
145 let mut quote_count = 0;
146 for c in text.chars() {
147 if c == quote_char {
148 quote_count += 1;
149 }
150 else {
151 break;
152 }
153 }
154 let value = if text.len() >= quote_count * 2 { &text[quote_count..text.len() - quote_count] } else { "" };
155 return Ok(VonValue::String(VonString { value: value.to_string(), span: s_span }));
156 }
157 else if l.kind == VonTokenType::NumberLiteral {
158 let n_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
159 let text = source.get_text_in(n_span.clone());
160 let clean_text = text.replace('_', "");
162 let value = clean_text.parse::<f64>().map_err(|e| {
163 OakError::custom_error(format!(
164 "Numeric parse failure: text='{}', error={:?}, span={:?}, source_around='{}'",
165 text,
166 e,
167 n_span,
168 source.get_text_in(oak_core::Range::from(n_span.start.saturating_sub(10)..n_span.end.saturating_add(10)))
169 ))
170 })?;
171 return Ok(VonValue::Number(VonNumber { value, span: n_span }));
172 }
173 else if l.kind == VonTokenType::BoolLiteral {
174 let b_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
175 let text = source.get_text_in(b_span.clone());
176 let value = text == "true";
177 return Ok(VonValue::Boolean(VonBoolean { value, span: b_span }));
178 }
179 else if l.kind == VonTokenType::NullLiteral {
180 let n_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
181 return Ok(VonValue::Null(VonNull { span: n_span }));
182 }
183 current_offset += l.length as usize;
184 }
185 }
186 Err(OakError::unexpected_eof(span.start, None))
187 }
188 _ => Err(OakError::syntax_error(format!("Unexpected node kind: {:?}", node.kind), span.start, None)),
189 }
190 }
191
192 fn build_field<'a>(&self, node: &GreenNode<'a, VonLanguage>, offset: usize, source: &SourceText) -> Result<VonField, OakError> {
193 let span: oak_core::Range<usize> = (offset..offset + node.byte_length as usize).into();
194
195 let mut name = None;
196 let mut value = None;
197 let mut current_offset = offset;
198
199 for child in node.children {
200 match child {
201 oak_core::GreenTree::Node(n) => {
202 if n.kind == VonElementType::Value || n.kind == VonElementType::Object || n.kind == VonElementType::Array || n.kind == VonElementType::Enum {
203 value = Some(self.build_value(n, current_offset, source)?);
204 }
205 current_offset += n.byte_length as usize
206 }
207 oak_core::GreenTree::Leaf(l) => {
208 if l.kind == VonTokenType::Identifier || l.kind == VonTokenType::StringLiteral {
209 let b_span: oak_core::Range<usize> = (current_offset..current_offset + l.length as usize).into();
210 let text = source.get_text_in(b_span.clone());
211 name = Some(text.trim_matches('"').to_string());
212 }
213 current_offset += l.length as usize
214 }
215 }
216 }
217
218 let name = name.ok_or_else(|| OakError::expected_token("Key", span.start, None))?;
219 let value = value.ok_or_else(|| OakError::expected_token("Value", span.start, None))?;
220
221 Ok(VonField { name, value, span })
222 }
223}