Skip to main content

oak_go/parser/
mod.rs

1use crate::{kind::GoSyntaxKind, language::GoLanguage, lexer::GoLexer};
2use oak_core::{
3    OakError,
4    parser::{Associativity, ParseCache, ParseOutput, Parser, ParserState, Pratt, PrattParser, binary, parse_with_lexer, unary},
5    source::{Source, TextEdit},
6    tree::GreenNode,
7};
8
9pub(crate) type State<'a, S> = ParserState<'a, GoLanguage, S>;
10
11/// Go 语言解析器
12pub struct GoParser<'config> {
13    pub(crate) config: &'config GoLanguage,
14}
15
16impl<'config> GoParser<'config> {
17    pub fn new(config: &'config GoLanguage) -> Self {
18        Self { config }
19    }
20
21    pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
22        use crate::kind::GoSyntaxKind::*;
23        match state.peek_kind() {
24            Some(Package) => self.parse_package_clause(state)?,
25            Some(Import) => self.parse_import_declaration(state)?,
26            Some(Func) => self.parse_function_declaration(state)?,
27            Some(Var) => self.parse_variable_declaration(state)?,
28            Some(Const) => self.parse_const_declaration(state)?,
29            Some(Type) => self.parse_type_declaration(state)?,
30            Some(If) => self.parse_if_statement(state)?,
31            Some(For) => self.parse_for_statement(state)?,
32            Some(Switch) => self.parse_switch_statement(state)?,
33            Some(Return) => self.parse_return_statement(state)?,
34            Some(LeftBrace) => self.parse_block(state)?,
35            _ => {
36                PrattParser::parse(state, 0, self);
37                state.eat(Semicolon);
38            }
39        }
40        Ok(())
41    }
42
43    fn parse_package_clause<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
44        let cp = state.checkpoint();
45        state.expect(GoSyntaxKind::Package).ok();
46        state.expect(GoSyntaxKind::Identifier).ok();
47        state.finish_at(cp, GoSyntaxKind::PackageClause.into());
48        Ok(())
49    }
50
51    fn parse_import_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
52        let cp = state.checkpoint();
53        state.expect(GoSyntaxKind::Import).ok();
54        if state.eat(GoSyntaxKind::LeftParen) {
55            while state.not_at_end() && !state.at(GoSyntaxKind::RightParen) {
56                state.advance();
57            }
58            state.expect(GoSyntaxKind::RightParen).ok();
59        }
60        else {
61            state.advance();
62        }
63        state.finish_at(cp, GoSyntaxKind::ImportDeclaration.into());
64        Ok(())
65    }
66
67    fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
68        let cp = state.checkpoint();
69        state.expect(GoSyntaxKind::Func).ok();
70        while state.not_at_end() && !state.at(GoSyntaxKind::LeftBrace) {
71            state.advance();
72        }
73        self.parse_block(state)?;
74        state.finish_at(cp, GoSyntaxKind::FunctionDeclaration.into());
75        Ok(())
76    }
77
78    fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
79        let cp = state.checkpoint();
80        state.expect(GoSyntaxKind::Var).ok();
81        while state.at(GoSyntaxKind::Identifier) {
82            state.bump();
83            if !state.eat(GoSyntaxKind::Semicolon) {
84                break;
85            }
86        }
87        state.eat(GoSyntaxKind::Semicolon);
88        state.finish_at(cp, GoSyntaxKind::VariableDeclaration.into());
89        Ok(())
90    }
91
92    fn parse_const_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
93        let cp = state.checkpoint();
94        state.expect(GoSyntaxKind::Const).ok();
95        while state.at(GoSyntaxKind::Identifier) {
96            state.bump();
97            if !state.eat(GoSyntaxKind::Semicolon) {
98                break;
99            }
100        }
101        state.eat(GoSyntaxKind::Semicolon);
102        state.finish_at(cp, GoSyntaxKind::ConstDeclaration.into());
103        Ok(())
104    }
105
106    fn parse_type_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
107        let cp = state.checkpoint();
108        state.expect(GoSyntaxKind::Type).ok();
109        while state.at(GoSyntaxKind::Identifier) {
110            state.bump();
111            if !state.eat(GoSyntaxKind::Semicolon) {
112                break;
113            }
114        }
115        state.eat(GoSyntaxKind::Semicolon);
116        state.finish_at(cp, GoSyntaxKind::TypeDeclaration.into());
117        Ok(())
118    }
119
120    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
121        let cp = state.checkpoint();
122        state.expect(GoSyntaxKind::If).ok();
123        while state.not_at_end() && !state.at(GoSyntaxKind::LeftBrace) {
124            state.advance();
125        }
126        self.parse_block(state)?;
127        if state.eat(GoSyntaxKind::Else) {
128            if state.at(GoSyntaxKind::If) {
129                self.parse_if_statement(state)?;
130            }
131            else {
132                self.parse_block(state)?;
133            }
134        }
135        state.finish_at(cp, GoSyntaxKind::IfStatement.into());
136        Ok(())
137    }
138
139    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
140        let cp = state.checkpoint();
141        state.expect(GoSyntaxKind::For).ok();
142        while state.not_at_end() && !state.at(GoSyntaxKind::LeftBrace) {
143            state.advance();
144        }
145        self.parse_block(state)?;
146        state.finish_at(cp, GoSyntaxKind::ForStatement.into());
147        Ok(())
148    }
149
150    fn parse_switch_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
151        let cp = state.checkpoint();
152        state.expect(GoSyntaxKind::Switch).ok();
153        while state.not_at_end() && !state.at(GoSyntaxKind::LeftBrace) {
154            state.advance();
155        }
156        self.parse_block(state)?;
157        state.finish_at(cp, GoSyntaxKind::SwitchStatement.into());
158        Ok(())
159    }
160
161    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
162        let cp = state.checkpoint();
163        state.expect(GoSyntaxKind::Return).ok();
164        if !state.at(GoSyntaxKind::Semicolon) {
165            PrattParser::parse(state, 0, self);
166        }
167        state.eat(GoSyntaxKind::Semicolon);
168        state.finish_at(cp, GoSyntaxKind::ReturnStatement.into());
169        Ok(())
170    }
171
172    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
173        let cp = state.checkpoint();
174        state.expect(GoSyntaxKind::LeftBrace).ok();
175        while state.not_at_end() && !state.at(GoSyntaxKind::RightBrace) {
176            self.parse_statement(state)?;
177        }
178        state.expect(GoSyntaxKind::RightBrace).ok();
179        state.finish_at(cp, GoSyntaxKind::Block.into());
180        Ok(())
181    }
182}
183
184impl<'config> Pratt<GoLanguage> for GoParser<'config> {
185    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
186        use crate::kind::GoSyntaxKind::*;
187        let cp = state.checkpoint();
188        match state.peek_kind() {
189            Some(Identifier) => {
190                state.bump();
191                state.finish_at(cp, Identifier.into())
192            }
193            Some(IntLiteral) | Some(FloatLiteral) | Some(StringLiteral) | Some(RuneLiteral) | Some(BoolLiteral) | Some(NilLiteral) => {
194                state.bump();
195                state.finish_at(cp, BinaryExpression.into()) // 简化处理
196            }
197            Some(LeftParen) => {
198                state.bump();
199                PrattParser::parse(state, 0, self);
200                state.expect(RightParen).ok();
201                state.finish_at(cp, BinaryExpression.into())
202            }
203            _ => {
204                state.bump();
205                state.finish_at(cp, Error.into())
206            }
207        }
208    }
209
210    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, GoLanguage> {
211        use crate::kind::GoSyntaxKind::*;
212        let kind = match state.peek_kind() {
213            Some(k) => k,
214            None => return self.primary(state),
215        };
216
217        let prec = match kind {
218            Plus | Minus | LogicalNot | Caret | Star | Ampersand | Arrow => 7,
219            _ => return self.primary(state),
220        };
221
222        unary(state, kind, prec, BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self))
223    }
224
225    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>> {
226        use crate::kind::GoSyntaxKind::*;
227        let kind = state.peek_kind()?;
228
229        let (prec, assoc) = match kind {
230            Star | Slash | Percent | LeftShift | RightShift | Ampersand | AmpersandCaret => (6, Associativity::Left),
231            Plus | Minus | Pipe | Caret => (5, Associativity::Left),
232            Equal | NotEqual | Less | LessEqual | Greater | GreaterEqual => (4, Associativity::Left),
233            LogicalAnd => (3, Associativity::Left),
234            LogicalOr => (2, Associativity::Left),
235            _ => return None,
236        };
237
238        if prec < min_precedence {
239            return None;
240        }
241
242        Some(binary(state, left, kind, prec, assoc, BinaryExpression.into(), |st, p| PrattParser::parse(st, p, self)))
243    }
244}
245
246impl<'config> Parser<GoLanguage> for GoParser<'config> {
247    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<GoLanguage>) -> ParseOutput<'a, GoLanguage> {
248        let lexer = GoLexer::new(self.config);
249        parse_with_lexer(&lexer, text, edits, cache, |state| {
250            let cp = state.checkpoint();
251            while state.not_at_end() {
252                self.parse_statement(state)?;
253            }
254            Ok(state.finish_at(cp, GoSyntaxKind::SourceFile.into()))
255        })
256    }
257}