1pub mod element_type;
2
3use crate::{language::GoLanguage, lexer::GoLexer};
4use oak_core::{
5 OakError,
6 parser::{Associativity, ParseCache, ParseOutput, Parser, ParserState, Pratt, PrattParser, binary, parse_with_lexer, unary},
7 source::{Source, TextEdit},
8 tree::GreenNode,
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, GoLanguage, S>;
12
13pub struct GoParser<'config> {
15 pub(crate) config: &'config GoLanguage,
16}
17
18impl<'config> GoParser<'config> {
19 pub fn new(config: &'config GoLanguage) -> Self {
20 Self { config }
21 }
22
23 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
24 while state.not_at_end() {
25 if let Some(kind) = state.peek_kind() {
26 if kind.is_ignored() {
27 state.bump();
28 continue;
29 };
30 }
31 break;
32 }
33 }
34
35 pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
36 use crate::{GoElementType as E, GoTokenType as T};
37 self.skip_trivia(state);
38 match state.peek_kind() {
39 Some(T::Package) => self.parse_package_clause(state)?,
40 Some(T::Import) => self.parse_import_declaration(state)?,
41 Some(T::Func) => self.parse_function_declaration(state)?,
42 Some(T::Var) => self.parse_variable_declaration(state)?,
43 Some(T::Const) => self.parse_const_declaration(state)?,
44 Some(T::Type) => self.parse_type_declaration(state)?,
45 Some(T::If) => self.parse_if_statement(state)?,
46 Some(T::For) => self.parse_for_statement(state)?,
47 Some(T::Switch) => self.parse_switch_statement(state)?,
48 Some(T::Return) => self.parse_return_statement(state)?,
49 Some(T::LeftBrace) => self.parse_block(state)?,
50 _ => {
51 let cp = state.checkpoint();
52 PrattParser::parse(state, 0, self);
53
54 self.skip_trivia(state);
55 match state.peek_kind() {
56 Some(T::Assign) => {
57 state.bump();
58 self.skip_trivia(state);
59 PrattParser::parse(state, 0, self);
60 state.finish_at(cp, E::AssignmentStatement);
61 }
62 Some(T::ColonAssign) => {
63 state.bump();
64 self.skip_trivia(state);
65 PrattParser::parse(state, 0, self);
66 state.finish_at(cp, E::ShortVarDecl);
67 }
68 _ => {
69 }
71 }
72 self.skip_trivia(state);
73 state.eat(T::Semicolon);
74 }
75 }
76 self.skip_trivia(state);
77 Ok(())
78 }
79
80 fn parse_package_clause<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
81 use crate::{GoElementType as E, GoTokenType as T};
82 let cp = state.checkpoint();
83 state.expect(T::Package).ok();
84 self.skip_trivia(state);
85 state.expect(T::Identifier).ok();
86 state.finish_at(cp, E::PackageClause);
87 Ok(())
88 }
89
90 fn parse_import_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
91 use crate::{GoElementType as E, GoTokenType as T};
92 let cp = state.checkpoint();
93 state.expect(T::Import).ok();
94 if state.eat(T::LeftParen) {
95 while state.not_at_end() && !state.at(T::RightParen) {
96 state.advance();
97 }
98 state.expect(T::RightParen).ok();
99 }
100 else {
101 state.advance();
102 }
103 state.finish_at(cp, E::ImportDeclaration);
104 Ok(())
105 }
106
107 fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
108 use crate::{GoElementType as E, GoTokenType as T};
109 let cp = state.checkpoint();
110 state.expect(T::Func).ok();
111 self.skip_trivia(state);
112
113 if state.at(T::LeftParen) {
115 let rcp = state.checkpoint();
116 self.parse_parameter_list(state)?;
117 state.finish_at(rcp, E::Receiver);
118 self.skip_trivia(state);
119 }
120
121 if state.at(T::Identifier) {
123 state.bump();
124 self.skip_trivia(state);
125 }
126
127 self.parse_parameter_list(state)?;
129 self.skip_trivia(state);
130
131 if state.at(T::LeftParen) {
133 self.parse_parameter_list(state)?;
134 self.skip_trivia(state);
135 }
136 else if state.at(T::Identifier) || state.at(T::Star) {
137 let rtcp = state.checkpoint();
139 if state.eat(T::Star) {
140 self.skip_trivia(state);
141 }
142 state.expect(T::Identifier).ok();
143 state.finish_at(rtcp, E::Identifier); self.skip_trivia(state);
145 }
146
147 if state.at(T::LeftBrace) {
148 self.parse_block(state)?;
149 }
150 state.finish_at(cp, E::FunctionDeclaration);
151 Ok(())
152 }
153
154 fn parse_parameter_list<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
155 use crate::{GoElementType as E, GoTokenType as T};
156 let cp = state.checkpoint();
157 state.expect(T::LeftParen).ok();
158 self.skip_trivia(state);
159 while state.not_at_end() && !state.at(T::RightParen) {
160 let pcp = state.checkpoint();
161 while state.at(T::Identifier) {
163 state.bump();
164 self.skip_trivia(state);
165 if !state.eat(T::Comma) {
166 break;
167 }
168 self.skip_trivia(state);
169 }
170 if state.not_at_end() && !state.at(T::Comma) && !state.at(T::RightParen) {
172 if state.eat(T::Star) {
173 self.skip_trivia(state);
174 }
175 if state.at(T::Identifier) {
176 state.bump();
177 self.skip_trivia(state);
178 }
179 }
180 state.finish_at(pcp, E::ParameterDecl);
181 self.skip_trivia(state);
182 if !state.eat(T::Comma) {
183 break;
184 }
185 self.skip_trivia(state);
186 }
187 state.expect(T::RightParen).ok();
188 state.finish_at(cp, E::ParameterList);
189 Ok(())
190 }
191
192 fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
193 use crate::{GoElementType as E, GoTokenType as T};
194 let cp = state.checkpoint();
195 state.expect(T::Var).ok();
196 self.skip_trivia(state);
197
198 while state.at(T::Identifier) {
199 let vcp = state.checkpoint();
200 state.bump(); self.skip_trivia(state);
202
203 if state.at(T::Identifier) {
205 state.bump();
206 self.skip_trivia(state);
207 }
208
209 if state.eat(T::Assign) {
211 self.skip_trivia(state);
212 PrattParser::parse(state, 0, self);
213 }
214
215 state.finish_at(vcp, E::VariableSpec);
216 self.skip_trivia(state);
217
218 if !state.eat(T::Comma) {
219 break;
220 }
221 self.skip_trivia(state);
222 }
223
224 state.eat(T::Semicolon);
225 state.finish_at(cp, E::VariableDeclaration);
226 Ok(())
227 }
228
229 fn parse_const_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
230 use crate::{GoElementType as E, GoTokenType as T};
231 let cp = state.checkpoint();
232 state.expect(T::Const).ok();
233 while state.at(T::Identifier) {
234 state.bump();
235 if !state.eat(T::Semicolon) {
236 break;
237 }
238 }
239 state.eat(T::Semicolon);
240 state.finish_at(cp, E::ConstDeclaration);
241 Ok(())
242 }
243
244 fn parse_type_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
245 use crate::{GoElementType as E, GoTokenType as T};
246 let cp = state.checkpoint();
247 state.expect(T::Type).ok();
248 while state.at(T::Identifier) {
249 state.bump();
250 if !state.eat(T::Semicolon) {
251 break;
252 }
253 }
254 state.eat(T::Semicolon);
255 state.finish_at(cp, E::TypeDeclaration);
256 Ok(())
257 }
258
259 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
260 use crate::{GoElementType as E, GoTokenType as T};
261 let cp = state.checkpoint();
262 state.expect(T::If).ok();
263 self.skip_trivia(state);
264
265 if !state.at(T::LeftBrace) {
267 PrattParser::parse(state, 0, self);
268 self.skip_trivia(state);
269 }
270
271 self.parse_block(state)?;
272 self.skip_trivia(state);
273
274 if state.eat(T::Else) {
275 self.skip_trivia(state);
276 if state.at(T::If) {
277 self.parse_if_statement(state)?;
278 }
279 else {
280 self.parse_block(state)?;
281 }
282 self.skip_trivia(state);
283 }
284 state.finish_at(cp, E::IfStatement);
285 Ok(())
286 }
287
288 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
289 use crate::{GoElementType as E, GoTokenType as T};
290 let cp = state.checkpoint();
291 state.expect(T::For).ok();
292 self.skip_trivia(state);
293
294 if !state.at(T::LeftBrace) {
296 PrattParser::parse(state, 0, self);
298 self.skip_trivia(state);
299
300 if state.eat(T::Semicolon) {
301 self.skip_trivia(state);
302 if !state.at(T::Semicolon) {
304 PrattParser::parse(state, 0, self);
305 self.skip_trivia(state);
306 }
307 state.expect(T::Semicolon).ok();
308 self.skip_trivia(state);
309 if !state.at(T::LeftBrace) {
311 PrattParser::parse(state, 0, self);
312 self.skip_trivia(state);
313 }
314 }
315 }
316
317 self.parse_block(state)?;
318 self.skip_trivia(state);
319 state.finish_at(cp, E::ForStatement);
320 Ok(())
321 }
322
323 fn parse_switch_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
324 use crate::{GoElementType as E, GoTokenType as T};
325 let cp = state.checkpoint();
326 state.expect(T::Switch).ok();
327 while state.not_at_end() && !state.at(T::LeftBrace) {
328 state.advance();
329 }
330 self.parse_block(state)?;
331 state.finish_at(cp, E::SwitchStatement);
332 Ok(())
333 }
334
335 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
336 use crate::{GoElementType as E, GoTokenType as T};
337 let cp = state.checkpoint();
338 state.expect(T::Return).ok();
339 if !state.at(T::Semicolon) {
340 PrattParser::parse(state, 0, self);
341 }
342 state.eat(T::Semicolon);
343 state.finish_at(cp, E::ReturnStatement);
344 Ok(())
345 }
346
347 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
348 use crate::{GoElementType as E, GoTokenType as T};
349 let cp = state.checkpoint();
350 state.expect(T::LeftBrace).ok();
351 self.skip_trivia(state);
352 while state.not_at_end() && !state.at(T::RightBrace) {
353 self.parse_statement(state)?;
354 self.skip_trivia(state);
355 }
356 state.expect(T::RightBrace).ok();
357 state.finish_at(cp, E::Block);
358 Ok(())
359 }
360}
361
362impl<'config> Pratt<GoLanguage> for GoParser<'config> {
363 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
364 use crate::{GoElementType as E, GoTokenType as T};
365 self.skip_trivia(state);
366 let cp = state.checkpoint();
367 let kind = match state.peek_kind() {
368 Some(k) => k,
369 None => {
370 state.bump();
371 return state.finish_at(cp, E::Error);
372 }
373 };
374
375 match kind {
376 T::Identifier => {
377 state.bump();
378 state.finish_at(cp, E::Identifier)
379 }
380 T::IntLiteral | T::FloatLiteral | T::StringLiteral | T::RuneLiteral | T::BoolLiteral | T::NilLiteral => {
381 state.bump();
382 state.finish_at(cp, kind.into())
383 }
384 T::LeftParen => {
385 state.bump();
386 self.skip_trivia(state);
387 PrattParser::parse(state, 0, self);
388 self.skip_trivia(state);
389 state.expect(T::RightParen).ok();
390 state.finish_at(cp, E::BinaryExpression) }
392 _ => {
393 state.bump();
394 state.finish_at(cp, E::Error)
395 }
396 }
397 }
398
399 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
400 use crate::{GoElementType as E, GoTokenType as T};
401 let kind = match state.peek_kind() {
402 Some(k) => k,
403 None => return self.primary(state),
404 };
405
406 let prec = match kind {
407 T::Plus | T::Minus | T::LogicalNot | T::Caret | T::Star | T::Ampersand | T::Arrow => 7,
408 _ => return self.primary(state),
409 };
410
411 unary(state, kind, prec, E::BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self))
412 }
413
414 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, GoLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, GoLanguage>> {
415 use crate::{GoElementType as E, GoTokenType as T};
416 self.skip_trivia(state);
417 let kind = state.peek_kind()?;
418
419 if kind == T::LeftParen {
420 let prec = 8;
421 if prec < min_precedence {
422 return None;
423 }
424 let cp = state.checkpoint_before(left);
425 state.bump(); self.skip_trivia(state);
427
428 let arg_cp = state.checkpoint();
429 let mut has_args = false;
430 while state.not_at_end() && !state.at(T::RightParen) {
431 PrattParser::parse(state, 0, self);
432 has_args = true;
433 self.skip_trivia(state);
434 if !state.eat(T::Comma) {
435 break;
436 }
437 self.skip_trivia(state);
438 }
439 if has_args {
440 state.finish_at(arg_cp, E::ExpressionList);
441 }
442
443 state.expect(T::RightParen).ok();
444 return Some(state.finish_at(cp, E::CallExpression));
445 }
446
447 let (prec, assoc) = match kind {
448 T::Assign | T::ColonAssign => (1, Associativity::Right),
449 T::LogicalOr => (2, Associativity::Left),
450 T::LogicalAnd => (3, Associativity::Left),
451 T::Equal | T::NotEqual | T::Less | T::LessEqual | T::Greater | T::GreaterEqual => (4, Associativity::Left),
452 T::Plus | T::Minus | T::Pipe | T::Caret => (5, Associativity::Left),
453 T::Star | T::Slash | T::Percent | T::LeftShift | T::RightShift | T::Ampersand | T::AmpersandCaret => (6, Associativity::Left),
454 T::Dot => (8, Associativity::Left),
455 _ => return None,
456 };
457
458 if prec < min_precedence {
459 return None;
460 }
461
462 Some(binary(state, left, kind, prec, assoc, E::BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self)))
463 }
464}
465
466impl<'config> Parser<GoLanguage> for GoParser<'config> {
467 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<GoLanguage>) -> ParseOutput<'a, GoLanguage> {
468 let lexer = GoLexer::new(self.config);
469 parse_with_lexer(&lexer, text, edits, cache, |state| {
470 let cp = state.checkpoint();
471 while state.not_at_end() {
472 self.parse_statement(state)?
473 }
474 Ok(state.finish_at(cp, crate::parser::element_type::GoElementType::SourceFile))
475 })
476 }
477}