oak_wolfram/parser/
mod.rs1#![doc = include_str!("readme.md")]
2
3use crate::{ast::*, kind::WolframSyntaxKind};
4use oak_core::{
5 SourceLocation, SourceText, Token,
6 errors::{OakDiagnostics, OakError},
7};
8
9type WolframToken = Token<WolframSyntaxKind>;
10
11#[derive(Debug)]
13pub struct WolframParser {
14 _source: Option<SourceText>,
15 tokens: Vec<WolframToken>,
16 position: usize,
17 errors: Vec<OakError>,
18}
19
20impl WolframParser {
21 pub fn new() -> Self {
23 Self { tokens: Vec::new(), position: 0, errors: Vec::new(), _source: None }
24 }
25
26 pub fn parse(&mut self, tokens: Vec<WolframToken>) -> OakDiagnostics<WolframRoot> {
28 self.tokens = tokens;
29 self.position = 0;
30 self.errors.clear();
31
32 let mut items = Vec::new();
33
34 while !self.is_at_end() {
35 match self.parse_item() {
36 Ok(item) => items.push(item),
37 Err(err) => {
38 self.errors.push(err);
39 self.advance();
40 }
41 }
42 }
43
44 let diagnostics = core::mem::take(&mut self.errors);
45 OakDiagnostics { result: Ok(WolframRoot { items }), diagnostics }
46 }
47
48 fn parse_item(&mut self) -> Result<WolframItem, OakError> {
50 if self.match_token(&WolframSyntaxKind::LeftParen) {
51 if self.match_token(&WolframSyntaxKind::Module) {
52 return Ok(WolframItem::Module(self.parse_module()?));
53 }
54 else if self.match_token(&WolframSyntaxKind::Function) {
55 return Ok(WolframItem::Function(self.parse_function()?));
56 }
57 else if self.match_token(&WolframSyntaxKind::Module) {
58 return Ok(WolframItem::Memory(self.parse_memory()?));
59 }
60 else if self.match_token(&WolframSyntaxKind::Export) {
61 return Ok(WolframItem::Export(self.parse_export()?));
62 }
63 else if self.match_token(&WolframSyntaxKind::Import) {
64 return Ok(WolframItem::Import(self.parse_import()?));
65 }
66 }
67
68 Err(self.make_error("Expected item"))
69 }
70
71 fn parse_module(&mut self) -> Result<WolframModule, OakError> {
73 let name = if self.check(&WolframSyntaxKind::Identifier) {
74 self.advance();
75 Some(String::new())
76 }
77 else {
78 None
79 };
80
81 let mut items = Vec::new();
82
83 while !self.check(&WolframSyntaxKind::RightParen) && !self.is_at_end() {
84 match self.parse_item() {
85 Ok(item) => items.push(item),
86 Err(err) => {
87 self.errors.push(err);
88 self.advance();
89 }
90 }
91 }
92
93 self.consume(&WolframSyntaxKind::RightParen, "Expected ')' ")?;
94
95 Ok(WolframModule { name, items })
96 }
97
98 fn parse_function(&mut self) -> Result<WolframFunction, OakError> {
100 let name = if self.check(&WolframSyntaxKind::Identifier) {
101 self.advance();
102 Some(String::new())
103 }
104 else {
105 None
106 };
107
108 let params = Vec::new();
109 let result = None;
110 let locals = Vec::new();
111 let body = Vec::new();
112
113 self.consume(&WolframSyntaxKind::RightParen, "Expected ')' ")?;
114
115 Ok(WolframFunction { name, params, result, locals, body })
116 }
117
118 fn parse_memory(&mut self) -> Result<WolframMemory, OakError> {
120 let name = if self.check(&WolframSyntaxKind::Identifier) {
121 self.advance();
122 Some(String::new())
123 }
124 else {
125 None
126 };
127
128 let min = 1;
129 let max = None;
130
131 self.consume(&WolframSyntaxKind::RightParen, "Expected ')' ")?;
132
133 Ok(WolframMemory { name, min, max })
134 }
135
136 fn parse_export(&mut self) -> Result<WolframExport, OakError> {
138 let name = if self.check(&WolframSyntaxKind::String) {
139 self.advance();
140 String::new()
141 }
142 else {
143 String::new()
144 };
145
146 let kind = WolframExportKind::Function(String::new());
147
148 self.consume(&WolframSyntaxKind::RightParen, "Expected ')' ")?;
149
150 Ok(WolframExport { name, kind })
151 }
152
153 fn parse_import(&mut self) -> Result<WolframImport, OakError> {
155 let module = if self.check(&WolframSyntaxKind::String) {
156 self.advance();
157 String::new()
158 }
159 else {
160 String::new()
161 };
162 let name = if self.check(&WolframSyntaxKind::String) {
163 self.advance();
164 String::new()
165 }
166 else {
167 String::new()
168 };
169
170 let kind = WolframImportKind::Function(WolframFunctionType { params: Vec::new(), results: Vec::new() });
171
172 self.consume(&WolframSyntaxKind::RightParen, "Expected ')' ")?;
173
174 Ok(WolframImport { module, name, kind })
175 }
176
177 fn advance(&mut self) -> &WolframToken {
180 let idx = self.position;
181 if self.position < self.tokens.len() {
182 self.position += 1;
183 }
184 &self.tokens[idx]
185 }
186
187 fn is_at_end(&self) -> bool {
188 self.position >= self.tokens.len() || self.tokens[self.position].kind == WolframSyntaxKind::Eof
189 }
190
191 fn check(&self, kind: &WolframSyntaxKind) -> bool {
192 !self.is_at_end() && self.tokens[self.position].kind == *kind
193 }
194
195 fn match_token(&mut self, kind: &WolframSyntaxKind) -> bool {
196 if self.check(kind) {
197 self.advance();
198 true
199 }
200 else {
201 false
202 }
203 }
204
205 fn consume(&mut self, kind: &WolframSyntaxKind, msg: &str) -> Result<(), OakError> {
206 if self.check(kind) {
207 self.advance();
208 Ok(())
209 }
210 else {
211 Err(self.make_error(msg))
212 }
213 }
214
215 fn make_error(&self, message: &str) -> OakError {
216 let token =
217 if self.is_at_end() { &self.tokens[self.tokens.len().saturating_sub(1)] } else { &self.tokens[self.position] };
218 let source = SourceLocation {
219 line: 1, column: token.span.start as u32,
221 url: None,
222 };
223 OakError::syntax_error(message, source)
224 }
225
226 fn _get_token_text(&self, _token: &WolframToken) -> String {
228 String::new()
231 }
232}
233
234impl Default for WolframParser {
235 fn default() -> Self {
236 Self::new()
237 }
238}