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
11pub 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()) }
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}