1pub mod element_type;
2pub use element_type::CElementType;
3
4use crate::{language::CLanguage, lexer::CTokenType};
5use oak_core::{
6 GreenNode, OakError, Source,
7 parser::{Associativity, ParseCache, ParseOutput, Parser, ParserState, Pratt, PrattParser, binary, parse_with_lexer},
8 source::TextEdit,
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, CLanguage, S>;
12
13pub struct CParser<'config> {
14 pub(crate) config: &'config CLanguage,
15}
16
17impl<'config> CParser<'config> {
18 pub fn new(config: &'config CLanguage) -> Self {
19 Self { config }
20 }
21
22 pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
23 use crate::lexer::CTokenType::*;
24 self.skip_trivia(state);
25 match state.peek_kind() {
26 Some(If) => self.parse_if_statement(state)?,
27 Some(While) => self.parse_while_statement(state)?,
28 Some(For) => self.parse_for_statement(state)?,
29 Some(Return) => self.parse_return_statement(state)?,
30 Some(LeftBrace) => self.parse_compound_statement(state)?,
31 Some(Struct) | Some(Union) | Some(Enum) | Some(Typedef) | Some(Extern) | Some(Static) | Some(Int) | Some(Char) | Some(Void) | Some(Float) | Some(Double) => self.parse_declaration(state)?,
32 _ => {
33 let expr = PrattParser::parse(state, 0, self);
34 state.push_child(expr);
35 self.skip_trivia(state);
36 state.eat(Semicolon);
37 }
38 }
39 Ok(())
40 }
41
42 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
43 while let Some(kind) = state.peek_kind() {
44 if matches!(kind, CTokenType::Whitespace | CTokenType::Comment) {
45 state.bump();
46 }
47 else {
48 break;
49 }
50 }
51 }
52
53 fn parse_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
54 use crate::lexer::CTokenType::*;
55 let cp = state.checkpoint();
56
57 self.skip_trivia(state);
58 while state.not_at_end() && !state.at(Semicolon) && !state.at(LeftBrace) && !state.at(Assign) && !state.at(LeftParen) {
59 state.bump();
60 self.skip_trivia(state);
61 }
62
63 if state.at(LeftParen) {
64 let pcp = state.checkpoint();
65 state.bump(); self.skip_trivia(state);
67 while state.not_at_end() && !state.at(RightParen) {
68 if state.at(Identifier) || state.at(Int) || state.at(Char) || state.at(Float) || state.at(Double) || state.at(Void) {
69 state.bump();
70 }
71 else if state.at(Comma) {
72 state.bump();
73 }
74 else {
75 state.bump();
76 }
77 self.skip_trivia(state);
78 }
79 state.expect(RightParen).ok();
80 state.finish_at(pcp, CElementType::ParameterList);
81 }
82
83 self.skip_trivia(state);
84
85 if state.at(Assign) {
86 state.bump(); self.skip_trivia(state);
88 let expr = PrattParser::parse(state, 0, self);
89 state.push_child(expr);
90 }
91
92 self.skip_trivia(state);
93
94 if state.at(LeftBrace) {
95 state.bump(); self.skip_trivia(state);
97 while state.not_at_end() && !state.at(RightBrace) {
98 self.parse_statement(state)?;
99 self.skip_trivia(state);
100 }
101 state.expect(RightBrace).ok();
102 state.finish_at(cp, CElementType::FunctionDefinition);
103 }
104 else {
105 state.eat(Semicolon);
106 state.finish_at(cp, CElementType::DeclarationStatement);
107 }
108 Ok(())
109 }
110
111 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
112 let cp = state.checkpoint();
113 state.bump(); state.expect(CTokenType::LeftParen).ok();
115 let expr = PrattParser::parse(state, 0, self);
116 state.push_child(expr);
117 state.expect(CTokenType::RightParen).ok();
118 self.parse_statement(state)?;
119 if state.eat(CTokenType::Else) {
120 self.parse_statement(state)?;
121 }
122 state.finish_at(cp, CElementType::IfStatement);
123 Ok(())
124 }
125
126 fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
127 let cp = state.checkpoint();
128 state.bump(); state.expect(CTokenType::LeftParen).ok();
130 let expr = PrattParser::parse(state, 0, self);
131 state.push_child(expr);
132 state.expect(CTokenType::RightParen).ok();
133 self.parse_statement(state)?;
134 state.finish_at(cp, CElementType::WhileStatement);
135 Ok(())
136 }
137
138 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
139 let cp = state.checkpoint();
140 state.bump(); state.expect(CTokenType::LeftParen).ok();
142
143 if !state.at(CTokenType::Semicolon) {
145 let expr = PrattParser::parse(state, 0, self);
146 state.push_child(expr);
147 }
148 state.expect(CTokenType::Semicolon).ok();
149
150 if !state.at(CTokenType::Semicolon) {
152 let expr = PrattParser::parse(state, 0, self);
153 state.push_child(expr);
154 }
155 state.expect(CTokenType::Semicolon).ok();
156
157 if !state.at(CTokenType::RightParen) {
159 let expr = PrattParser::parse(state, 0, self);
160 state.push_child(expr);
161 }
162 state.expect(CTokenType::RightParen).ok();
163
164 self.parse_statement(state)?;
165 state.finish_at(cp, CElementType::ForStatement);
166 Ok(())
167 }
168
169 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
170 let cp = state.checkpoint();
171 state.bump(); if !state.at(CTokenType::Semicolon) {
173 let expr = PrattParser::parse(state, 0, self);
174 state.push_child(expr);
175 }
176 state.eat(CTokenType::Semicolon);
177 state.finish_at(cp, CElementType::ReturnStatement);
178 Ok(())
179 }
180
181 fn parse_compound_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
182 let cp = state.checkpoint();
183 state.expect(CTokenType::LeftBrace).ok();
184 while state.not_at_end() && !state.at(CTokenType::RightBrace) {
185 self.parse_statement(state)?;
186 }
187 state.expect(CTokenType::RightBrace).ok();
188 state.finish_at(cp, CElementType::CompoundStatement);
189 Ok(())
190 }
191}
192
193impl<'config> Pratt<CLanguage> for CParser<'config> {
194 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, CLanguage> {
195 use crate::lexer::CTokenType::*;
196 self.skip_trivia(state);
197 let cp = state.checkpoint();
198 match state.peek_kind() {
199 Some(Identifier) => {
200 state.bump();
201 state.finish_at(cp, CElementType::Token(Identifier))
202 }
203 Some(IntegerLiteral) | Some(FloatLiteral) | Some(CharLiteral) | Some(StringLiteral) => {
204 let _kind = state.peek_kind().unwrap();
205 state.bump();
206 state.finish_at(cp, CElementType::ExpressionStatement) }
208 Some(LeftParen) => {
209 state.bump();
210 let expr = PrattParser::parse(state, 0, self);
211 state.push_child(expr);
212 self.skip_trivia(state);
213 state.expect(RightParen).ok();
214 state.finish_at(cp, CElementType::ExpressionStatement)
215 }
216 _ => {
217 state.bump();
218 state.finish_at(cp, CElementType::Error)
219 }
220 }
221 }
222
223 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, CLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, CLanguage>> {
224 use crate::lexer::CTokenType::*;
225 self.skip_trivia(state);
226 let kind = state.peek_kind()?;
227
228 let (prec, assoc) = match kind {
229 Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AndAssign | OrAssign | XorAssign | LeftShiftAssign | RightShiftAssign => (1, Associativity::Right),
230 LogicalOr => (2, Associativity::Left),
231 LogicalAnd => (3, Associativity::Left),
232 Equal | NotEqual | Less | Greater | LessEqual | GreaterEqual => (4, Associativity::Left),
233 Plus | Minus => (10, Associativity::Left),
234 Star | Slash | Percent => (11, Associativity::Left),
235 LeftParen | LeftBracket | Dot | Arrow => (15, Associativity::Left),
236 _ => return None,
237 };
238
239 if prec < min_precedence {
240 return None;
241 }
242
243 match kind {
244 LeftParen => {
245 let cp = state.checkpoint();
246 state.push_child(left);
247 state.expect(LeftParen).ok();
248 while state.not_at_end() && !state.at(RightParen) {
249 let expr = PrattParser::parse(state, 0, self);
250 state.push_child(expr);
251 self.skip_trivia(state);
252 if !state.eat(Comma) {
253 break;
254 }
255 }
256 state.expect(RightParen).ok();
257 Some(state.finish_at(cp, CElementType::ExpressionStatement))
258 }
259 LeftBracket => {
260 let cp = state.checkpoint();
261 state.push_child(left);
262 state.expect(LeftBracket).ok();
263 let expr = PrattParser::parse(state, 0, self);
264 state.push_child(expr);
265 state.expect(RightBracket).ok();
266 Some(state.finish_at(cp, CElementType::ExpressionStatement))
267 }
268 Dot | Arrow => {
269 let cp = state.checkpoint();
270 state.push_child(left);
271 state.expect(kind).ok();
272 state.expect(Identifier).ok();
273 Some(state.finish_at(cp, CElementType::ExpressionStatement))
274 }
275 _ => Some(binary(state, left, kind, prec, assoc, CElementType::ExpressionStatement, |s, p| PrattParser::parse(s, p, self))),
276 }
277 }
278}
279
280impl<'config> Parser<CLanguage> for CParser<'config> {
281 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<CLanguage>) -> ParseOutput<'a, CLanguage> {
282 let lexer = crate::lexer::CLexer::new(self.config);
283 parse_with_lexer(&lexer, text, edits, cache, |state| {
284 let cp = state.checkpoint();
285 while state.not_at_end() {
286 self.parse_statement(state).ok();
287 }
288 Ok(state.finish_at(cp, CElementType::Root))
289 })
290 }
291}