1use crate::{kind::ZigSyntaxKind, language::ZigLanguage, lexer::ZigLexer};
2use oak_core::{
3 GreenNode, OakError,
4 parser::{
5 ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
6 pratt::{Associativity, Pratt, PrattParser, binary, unary},
7 },
8 source::{Source, TextEdit},
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, ZigLanguage, S>;
12
13pub struct ZigParser<'config> {
14 pub(crate) config: &'config ZigLanguage,
15}
16
17impl<'config> ZigParser<'config> {
18 pub fn new(config: &'config ZigLanguage) -> Self {
19 Self { config }
20 }
21}
22
23impl<'config> Pratt<ZigLanguage> for ZigParser<'config> {
24 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, ZigLanguage> {
25 use crate::kind::ZigSyntaxKind::*;
26 let cp = state.checkpoint();
27 match state.peek_kind() {
28 Some(Identifier) => {
29 state.bump();
30 state.finish_at(cp, Identifier.into())
31 }
32 Some(IntegerLiteral) | Some(FloatLiteral) | Some(StringLiteral) | Some(CharLiteral) | Some(BooleanLiteral) | Some(Null) | Some(Undefined) => {
33 state.bump();
34 state.finish_at(cp, Root.into()) }
36 Some(LeftParen) => {
37 state.bump();
38 PrattParser::parse(state, 0, self);
39 state.expect(RightParen).ok();
40 state.finish_at(cp, Root.into())
41 }
42 _ => {
43 state.bump();
44 state.finish_at(cp, Error.into())
45 }
46 }
47 }
48
49 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, ZigLanguage> {
50 use crate::kind::ZigSyntaxKind::*;
51 let kind = match state.peek_kind() {
52 Some(k) => k,
53 None => return self.primary(state),
54 };
55
56 match kind {
57 Minus | Tilde | Exclamation | Ampersand | TryKeyword | AwaitKeyword => unary(state, kind, 12, Root.into(), |s, p| PrattParser::parse(s, p, self)),
58 _ => self.primary(state),
59 }
60 }
61
62 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, ZigLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, ZigLanguage>> {
63 use crate::kind::ZigSyntaxKind::*;
64 let kind = state.peek_kind()?;
65
66 let (prec, assoc) = match kind {
67 Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AmpersandAssign | PipeAssign | CaretAssign | LessLessAssign | GreaterGreaterAssign => (1, Associativity::Right),
68 Or | OrOr => (2, Associativity::Left),
69 And | AndAnd => (3, Associativity::Left),
70 Equal | NotEqual | Less | Greater | LessEqual | GreaterEqual => (4, Associativity::Left),
71 Plus | Minus | PlusPercent | MinusPercent | PlusPlus => (5, Associativity::Left),
72 Star | Slash | Percent | StarPercent | StarStar => (6, Associativity::Left),
73 CatchKeyword | OrElse => (7, Associativity::Right),
74 Dot | LeftParen | LeftBracket => (10, Associativity::Left),
75 _ => return None,
76 };
77
78 if prec < min_precedence {
79 return None;
80 }
81
82 match kind {
83 Dot => {
84 let cp = state.checkpoint();
85 state.push_child(left);
86 state.bump();
87 state.expect(Identifier).ok();
88 Some(state.finish_at(cp, Root.into()))
89 }
90 LeftParen => {
91 let cp = state.checkpoint();
92 state.push_child(left);
93 state.bump();
94 while state.not_at_end() && !state.at(RightParen) {
95 PrattParser::parse(state, 0, self);
96 if !state.eat(Comma) {
97 break;
98 }
99 }
100 state.expect(RightParen).ok();
101 Some(state.finish_at(cp, Root.into()))
102 }
103 LeftBracket => {
104 let cp = state.checkpoint();
105 state.push_child(left);
106 state.bump();
107 PrattParser::parse(state, 0, self);
108 state.expect(RightBracket).ok();
109 Some(state.finish_at(cp, Root.into()))
110 }
111 _ => Some(binary(state, left, kind, prec, assoc, Root.into(), |s, p| PrattParser::parse(s, p, self))),
112 }
113 }
114}
115
116impl<'config> Parser<ZigLanguage> for ZigParser<'config> {
117 fn parse<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<ZigLanguage>) -> ParseOutput<'a, ZigLanguage> {
118 let lexer = ZigLexer::new(&self.config);
119 parse_with_lexer(&lexer, source, edits, cache, |state| self.parse_root_internal(state))
120 }
121}
122
123impl<'p> ZigParser<'p> {
124 pub(crate) fn parse_root_internal<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<&'a GreenNode<'a, ZigLanguage>, OakError> {
125 let checkpoint = state.checkpoint();
126
127 while state.not_at_end() {
128 self.parse_statement(state)?;
129 }
130
131 Ok(state.finish_at(checkpoint, ZigSyntaxKind::Root.into()))
132 }
133
134 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
135 use crate::kind::ZigSyntaxKind::*;
136 match state.peek_kind() {
137 Some(Fn) => self.parse_function_declaration(state)?,
138 Some(Const) | Some(Var) => self.parse_variable_declaration(state)?,
139 Some(If) => self.parse_if_statement(state)?,
140 Some(While) => self.parse_while_statement(state)?,
141 Some(For) => self.parse_for_statement(state)?,
142 Some(Return) => self.parse_return_statement(state)?,
143 Some(LeftBrace) => self.parse_block(state)?,
144 _ => {
145 PrattParser::parse(state, 0, self);
146 state.eat(Semicolon);
147 }
148 }
149 Ok(())
150 }
151
152 fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
153 use crate::kind::ZigSyntaxKind::*;
154 let cp = state.checkpoint();
155 state.expect(Fn).ok();
156 state.expect(Identifier).ok();
157 state.expect(LeftParen).ok();
158 while state.not_at_end() && !state.at(RightParen) {
159 state.advance();
160 }
161 state.expect(RightParen).ok();
162 while state.not_at_end() && !state.at(LeftBrace) {
163 state.bump();
164 }
165 self.parse_block(state)?;
166 state.finish_at(cp, ZigSyntaxKind::FnDeclaration.into());
167 Ok(())
168 }
169
170 fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
171 use crate::kind::ZigSyntaxKind::*;
172 let cp = state.checkpoint();
173 state.bump(); state.expect(Identifier).ok();
175 if state.eat(Colon) {
176 while state.not_at_end() && !state.at(Assign) && !state.at(Semicolon) {
177 state.bump();
178 }
179 }
180 if state.eat(Assign) {
181 PrattParser::parse(state, 0, self);
182 }
183 state.eat(Semicolon);
184 state.finish_at(cp, ZigSyntaxKind::VarDeclaration.into());
185 Ok(())
186 }
187
188 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
189 use crate::kind::ZigSyntaxKind::*;
190 let cp = state.checkpoint();
191 state.expect(If).ok();
192 state.expect(LeftParen).ok();
193 PrattParser::parse(state, 0, self);
194 state.expect(RightParen).ok();
195 self.parse_statement(state)?;
196 if state.eat(Else) {
197 self.parse_statement(state)?;
198 }
199 state.finish_at(cp, ZigSyntaxKind::IfStatement.into());
200 Ok(())
201 }
202
203 fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
204 use crate::kind::ZigSyntaxKind::*;
205 let cp = state.checkpoint();
206 state.expect(While).ok();
207 state.expect(LeftParen).ok();
208 PrattParser::parse(state, 0, self);
209 state.expect(RightParen).ok();
210 self.parse_statement(state)?;
211 state.finish_at(cp, ZigSyntaxKind::WhileStatement.into());
212 Ok(())
213 }
214
215 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
216 use crate::kind::ZigSyntaxKind::*;
217 let cp = state.checkpoint();
218 state.expect(For).ok();
219 state.expect(LeftParen).ok();
220 PrattParser::parse(state, 0, self);
221 state.expect(RightParen).ok();
222 self.parse_statement(state)?;
223 state.finish_at(cp, ZigSyntaxKind::ForStatement.into());
224 Ok(())
225 }
226
227 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
228 use crate::kind::ZigSyntaxKind::*;
229 let cp = state.checkpoint();
230 state.expect(Return).ok();
231 if !state.at(Semicolon) {
232 PrattParser::parse(state, 0, self);
233 }
234 state.eat(Semicolon);
235 state.finish_at(cp, ZigSyntaxKind::ReturnStatement.into());
236 Ok(())
237 }
238
239 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
240 use crate::kind::ZigSyntaxKind::*;
241 let cp = state.checkpoint();
242 state.expect(LeftBrace).ok();
243 while state.not_at_end() && !state.at(RightBrace) {
244 self.parse_statement(state)?;
245 }
246 state.expect(RightBrace).ok();
247 state.finish_at(cp, ZigSyntaxKind::Block.into());
248 Ok(())
249 }
250}