1use crate::{
2 JsonLanguage,
3 ast::{JsonArray, JsonBoolean, JsonField, JsonNull, JsonNumber, JsonObject, JsonRoot, JsonString, JsonValueNode},
4 lexer::JsonLexer,
5 parser::JsonParser,
6};
7use oak_core::{Builder, BuilderCache, GreenNode, Lexer, OakDiagnostics, OakError, Parser, SourceText, TextEdit, parser::session::ParseSession, source::Source};
8
9#[derive(Clone)]
11pub struct JsonBuilder<'config> {
12 config: &'config JsonLanguage,
13}
14
15impl<'config> JsonBuilder<'config> {
16 pub fn new(config: &'config JsonLanguage) -> Self {
18 Self { config }
19 }
20}
21
22impl<'config> Builder<JsonLanguage> for JsonBuilder<'config> {
23 fn build<'a, S: Source + ?Sized>(&self, source: &S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<JsonLanguage>) -> OakDiagnostics<JsonRoot> {
24 let parser = JsonParser::new(self.config);
25 let lexer = JsonLexer::new(self.config);
26
27 let mut cache = ParseSession::<JsonLanguage>::default();
28 lexer.lex(source, edits, &mut cache);
29 let parse_result = parser.parse(source, edits, &mut cache);
30 let OakDiagnostics { result, diagnostics } = parse_result;
31
32 match result {
33 Ok(green_tree) => {
34 let text = source.get_text_in((0..source.length()).into());
35 let source_text = SourceText::new(text.into_owned());
36 match self.build_root(&green_tree, &source_text) {
37 Ok(ast_root) => OakDiagnostics { result: Ok(ast_root), diagnostics },
38 Err(build_error) => {
39 let mut diagnostics = diagnostics;
40 diagnostics.push(build_error.clone());
41 OakDiagnostics { result: Err(build_error), diagnostics }
42 }
43 }
44 }
45 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics },
46 }
47 }
48}
49
50impl<'config> JsonBuilder<'config> {
51 fn build_root<'a>(&self, green_tree: &GreenNode<'a, JsonLanguage>, source: &SourceText) -> Result<JsonRoot, OakError> {
52 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(JsonRoot { value })
59 }
60
61 fn build_value<'a>(&self, node: &GreenNode<'a, JsonLanguage>, offset: usize, source: &SourceText) -> Result<JsonValueNode, OakError> {
62 use crate::parser::element_type::JsonElementType;
63 let span: oak_core::Range<usize> = (offset..offset + node.byte_length as usize).into();
64
65 match node.kind {
66 JsonElementType::Object => {
67 let mut fields = Vec::new();
68 let mut current_offset = offset;
69 for child in node.children {
70 match child {
71 oak_core::GreenTree::Node(n) => {
72 if n.kind == JsonElementType::ObjectEntry {
73 fields.push(self.build_field(n, current_offset, source)?);
74 }
75 current_offset += n.byte_length as usize;
76 }
77 oak_core::GreenTree::Leaf(l) => {
78 current_offset += l.length as usize;
79 }
80 }
81 }
82 Ok(JsonValueNode::Object(JsonObject { fields, span }))
83 }
84 JsonElementType::Array => {
85 let mut elements = Vec::new();
86 let mut current_offset = offset;
87 for child in node.children {
88 match child {
89 oak_core::GreenTree::Node(n) => {
90 match n.kind {
91 JsonElementType::ArrayElement | JsonElementType::Value | JsonElementType::Object | JsonElementType::Array | JsonElementType::String | JsonElementType::Number | JsonElementType::Boolean | JsonElementType::Null => {
92 elements.push(self.build_value(n, current_offset, source)?);
93 }
94 _ => {}
95 }
96 current_offset += n.byte_length as usize;
97 }
98 oak_core::GreenTree::Leaf(l) => {
99 current_offset += l.length as usize;
100 }
101 }
102 }
103 Ok(JsonValueNode::Array(JsonArray { elements, span }))
104 }
105 JsonElementType::String => {
106 let text = source.get_text_in(span.clone());
107 let value = text.trim_matches('"').to_string();
108 Ok(JsonValueNode::String(JsonString { value, span }))
109 }
110 JsonElementType::Number => {
111 let text = source.get_text_in(span.clone());
112 let value = text.parse::<f64>().map_err(|_| OakError::syntax_error(format!("Invalid number: {}", text), span.start, None))?;
113 Ok(JsonValueNode::Number(JsonNumber { value, span }))
114 }
115 JsonElementType::Boolean => {
116 let text = source.get_text_in(span.clone());
117 let value = text == "true";
118 Ok(JsonValueNode::Boolean(JsonBoolean { value, span }))
119 }
120 JsonElementType::Null => Ok(JsonValueNode::Null(JsonNull { span })),
121 JsonElementType::Value | JsonElementType::ArrayElement | JsonElementType::Root => {
122 let mut current_offset = offset;
123 for child in node.children {
124 if let oak_core::GreenTree::Node(n) = child {
125 return self.build_value(n, current_offset, source);
126 }
127 else if let oak_core::GreenTree::Leaf(l) = child {
128 current_offset += l.length as usize;
129 }
130 }
131 Err(OakError::unexpected_eof(span.start, None))
132 }
133 _ => Err(OakError::syntax_error(format!("Unexpected node kind: {:?}", node.kind), span.start, None)),
134 }
135 }
136
137 fn build_field<'a>(&self, node: &GreenNode<'a, JsonLanguage>, offset: usize, source: &SourceText) -> Result<JsonField, OakError> {
138 use crate::{lexer::token_type::JsonTokenType, parser::element_type::JsonElementType};
139 let span: oak_core::Range<usize> = (offset..offset + node.byte_length as usize).into();
140 let mut name = None;
141 let mut value = None;
142 let mut seen_colon = false;
143 let mut current_offset = offset;
144
145 for child in node.children {
146 match child {
147 oak_core::GreenTree::Node(n) => {
148 if !seen_colon {
149 if n.kind == JsonElementType::String {
150 let s_span: oak_core::Range<usize> = (current_offset..current_offset + n.byte_length as usize).into();
151 let text = source.get_text_in(s_span.clone());
152 name = Some(JsonString { value: text.trim_matches('"').to_string(), span: s_span });
153 }
154 }
155 else if value.is_none() {
156 match n.kind {
157 JsonElementType::Value | JsonElementType::Object | JsonElementType::Array | JsonElementType::String | JsonElementType::Number | JsonElementType::Boolean | JsonElementType::Null => {
158 value = Some(self.build_value(n, current_offset, source)?);
159 }
160 _ => {}
161 }
162 }
163 current_offset += n.byte_length as usize;
164 }
165 oak_core::GreenTree::Leaf(l) => {
166 if l.kind == JsonTokenType::Colon {
167 seen_colon = true;
168 }
169 current_offset += l.length as usize;
170 }
171 }
172 }
173
174 Ok(JsonField { name: name.ok_or_else(|| OakError::syntax_error("Missing field name", offset, None))?, value: value.ok_or_else(|| OakError::syntax_error("Missing field value", offset, None))?, span })
175 }
176}