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