Skip to main content

oak_go/parser/
mod.rs

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
13/// Go 语言解析器
14pub 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                        // 纯表达式语句
70                    }
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        // 解析函数名
114        if state.at(T::Identifier) {
115            state.bump();
116            self.skip_trivia(state);
117        }
118
119        // 解析参数列表和返回值 (简单跳过直到 {)
120        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(); // name
139            self.skip_trivia(state);
140
141            // 可选类型
142            if state.at(T::Identifier) {
143                state.bump();
144                self.skip_trivia(state);
145            }
146
147            // 可选赋值
148            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        // 解析条件
204        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        // 尝试解析 init; condition; post
233        if !state.at(T::LeftBrace) {
234            // 至少解析一个表达式/语句
235            PrattParser::parse(state, 0, self);
236            self.skip_trivia(state);
237
238            if state.eat(T::Semicolon) {
239                self.skip_trivia(state);
240                // condition
241                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                // post
248                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) // 或者 ParenExpression
329            }
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(); // (
364            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}