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::Identifier) {
115 state.bump();
116 self.skip_trivia(state);
117 }
118
119 while state.not_at_end() && !state.at(T::LeftBrace) {
121 state.bump();
122 self.skip_trivia(state);
123 }
124
125 self.parse_block(state)?;
126 state.finish_at(cp, E::FunctionDeclaration);
127 Ok(())
128 }
129
130 fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
131 use crate::{GoElementType as E, GoTokenType as T};
132 let cp = state.checkpoint();
133 state.expect(T::Var).ok();
134 self.skip_trivia(state);
135
136 while state.at(T::Identifier) {
137 let vcp = state.checkpoint();
138 state.bump(); self.skip_trivia(state);
140
141 if state.at(T::Identifier) {
143 state.bump();
144 self.skip_trivia(state);
145 }
146
147 if state.eat(T::Assign) {
149 self.skip_trivia(state);
150 PrattParser::parse(state, 0, self);
151 }
152
153 state.finish_at(vcp, E::VariableSpec);
154 self.skip_trivia(state);
155
156 if !state.eat(T::Comma) {
157 break;
158 }
159 self.skip_trivia(state);
160 }
161
162 state.eat(T::Semicolon);
163 state.finish_at(cp, E::VariableDeclaration);
164 Ok(())
165 }
166
167 fn parse_const_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
168 use crate::{GoElementType as E, GoTokenType as T};
169 let cp = state.checkpoint();
170 state.expect(T::Const).ok();
171 while state.at(T::Identifier) {
172 state.bump();
173 if !state.eat(T::Semicolon) {
174 break;
175 }
176 }
177 state.eat(T::Semicolon);
178 state.finish_at(cp, E::ConstDeclaration);
179 Ok(())
180 }
181
182 fn parse_type_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
183 use crate::{GoElementType as E, GoTokenType as T};
184 let cp = state.checkpoint();
185 state.expect(T::Type).ok();
186 while state.at(T::Identifier) {
187 state.bump();
188 if !state.eat(T::Semicolon) {
189 break;
190 }
191 }
192 state.eat(T::Semicolon);
193 state.finish_at(cp, E::TypeDeclaration);
194 Ok(())
195 }
196
197 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
198 use crate::{GoElementType as E, GoTokenType as T};
199 let cp = state.checkpoint();
200 state.expect(T::If).ok();
201 self.skip_trivia(state);
202
203 if !state.at(T::LeftBrace) {
205 PrattParser::parse(state, 0, self);
206 self.skip_trivia(state);
207 }
208
209 self.parse_block(state)?;
210 self.skip_trivia(state);
211
212 if state.eat(T::Else) {
213 self.skip_trivia(state);
214 if state.at(T::If) {
215 self.parse_if_statement(state)?;
216 }
217 else {
218 self.parse_block(state)?;
219 }
220 self.skip_trivia(state);
221 }
222 state.finish_at(cp, E::IfStatement);
223 Ok(())
224 }
225
226 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
227 use crate::{GoElementType as E, GoTokenType as T};
228 let cp = state.checkpoint();
229 state.expect(T::For).ok();
230 self.skip_trivia(state);
231
232 if !state.at(T::LeftBrace) {
234 PrattParser::parse(state, 0, self);
236 self.skip_trivia(state);
237
238 if state.eat(T::Semicolon) {
239 self.skip_trivia(state);
240 if !state.at(T::Semicolon) {
242 PrattParser::parse(state, 0, self);
243 self.skip_trivia(state);
244 }
245 state.expect(T::Semicolon).ok();
246 self.skip_trivia(state);
247 if !state.at(T::LeftBrace) {
249 PrattParser::parse(state, 0, self);
250 self.skip_trivia(state);
251 }
252 }
253 }
254
255 self.parse_block(state)?;
256 self.skip_trivia(state);
257 state.finish_at(cp, E::ForStatement);
258 Ok(())
259 }
260
261 fn parse_switch_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
262 use crate::{GoElementType as E, GoTokenType as T};
263 let cp = state.checkpoint();
264 state.expect(T::Switch).ok();
265 while state.not_at_end() && !state.at(T::LeftBrace) {
266 state.advance();
267 }
268 self.parse_block(state)?;
269 state.finish_at(cp, E::SwitchStatement);
270 Ok(())
271 }
272
273 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
274 use crate::{GoElementType as E, GoTokenType as T};
275 let cp = state.checkpoint();
276 state.expect(T::Return).ok();
277 if !state.at(T::Semicolon) {
278 PrattParser::parse(state, 0, self);
279 }
280 state.eat(T::Semicolon);
281 state.finish_at(cp, E::ReturnStatement);
282 Ok(())
283 }
284
285 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
286 use crate::{GoElementType as E, GoTokenType as T};
287 let cp = state.checkpoint();
288 state.expect(T::LeftBrace).ok();
289 self.skip_trivia(state);
290 while state.not_at_end() && !state.at(T::RightBrace) {
291 self.parse_statement(state)?;
292 self.skip_trivia(state);
293 }
294 state.expect(T::RightBrace).ok();
295 state.finish_at(cp, E::Block);
296 Ok(())
297 }
298}
299
300impl<'config> Pratt<GoLanguage> for GoParser<'config> {
301 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
302 use crate::{GoElementType as E, GoTokenType as T};
303 self.skip_trivia(state);
304 let cp = state.checkpoint();
305 let kind = match state.peek_kind() {
306 Some(k) => k,
307 None => {
308 state.bump();
309 return state.finish_at(cp, E::Error);
310 }
311 };
312
313 match kind {
314 T::Identifier => {
315 state.bump();
316 state.finish_at(cp, E::Identifier)
317 }
318 T::IntLiteral | T::FloatLiteral | T::StringLiteral | T::RuneLiteral | T::BoolLiteral | T::NilLiteral => {
319 state.bump();
320 state.finish_at(cp, kind.into())
321 }
322 T::LeftParen => {
323 state.bump();
324 self.skip_trivia(state);
325 PrattParser::parse(state, 0, self);
326 self.skip_trivia(state);
327 state.expect(T::RightParen).ok();
328 state.finish_at(cp, E::BinaryExpression) }
330 _ => {
331 state.bump();
332 state.finish_at(cp, E::Error)
333 }
334 }
335 }
336
337 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
338 use crate::{GoElementType as E, GoTokenType as T};
339 let kind = match state.peek_kind() {
340 Some(k) => k,
341 None => return self.primary(state),
342 };
343
344 let prec = match kind {
345 T::Plus | T::Minus | T::LogicalNot | T::Caret | T::Star | T::Ampersand | T::Arrow => 7,
346 _ => return self.primary(state),
347 };
348
349 unary(state, kind, prec, E::BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self))
350 }
351
352 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>> {
353 use crate::{GoElementType as E, GoTokenType as T};
354 self.skip_trivia(state);
355 let kind = state.peek_kind()?;
356
357 if kind == T::LeftParen {
358 let prec = 8;
359 if prec < min_precedence {
360 return None;
361 }
362 let cp = state.checkpoint_before(left);
363 state.bump(); self.skip_trivia(state);
365
366 let arg_cp = state.checkpoint();
367 let mut has_args = false;
368 while state.not_at_end() && !state.at(T::RightParen) {
369 PrattParser::parse(state, 0, self);
370 has_args = true;
371 self.skip_trivia(state);
372 if !state.eat(T::Comma) {
373 break;
374 }
375 self.skip_trivia(state);
376 }
377 if has_args {
378 state.finish_at(arg_cp, E::ExpressionList);
379 }
380
381 state.expect(T::RightParen).ok();
382 return Some(state.finish_at(cp, E::CallExpression));
383 }
384
385 let (prec, assoc) = match kind {
386 T::Assign | T::ColonAssign => (1, Associativity::Right),
387 T::LogicalOr => (2, Associativity::Left),
388 T::LogicalAnd => (3, Associativity::Left),
389 T::Equal | T::NotEqual | T::Less | T::LessEqual | T::Greater | T::GreaterEqual => (4, Associativity::Left),
390 T::Plus | T::Minus | T::Pipe | T::Caret => (5, Associativity::Left),
391 T::Star | T::Slash | T::Percent | T::LeftShift | T::RightShift | T::Ampersand | T::AmpersandCaret => (6, Associativity::Left),
392 T::Dot => (8, Associativity::Left),
393 _ => return None,
394 };
395
396 if prec < min_precedence {
397 return None;
398 }
399
400 Some(binary(state, left, kind, prec, assoc, E::BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self)))
401 }
402}
403
404impl<'config> Parser<GoLanguage> for GoParser<'config> {
405 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<GoLanguage>) -> ParseOutput<'a, GoLanguage> {
406 let lexer = GoLexer::new(self.config);
407 parse_with_lexer(&lexer, text, edits, cache, |state| {
408 let cp = state.checkpoint();
409 while state.not_at_end() {
410 self.parse_statement(state)?
411 }
412 Ok(state.finish_at(cp, crate::parser::element_type::GoElementType::SourceFile))
413 })
414 }
415}