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