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 match state.peek_kind() {
25 Some(If) => self.parse_if_statement(state)?,
26 Some(While) => self.parse_while_statement(state)?,
27 Some(For) => self.parse_for_statement(state)?,
28 Some(Return) => self.parse_return_statement(state)?,
29 Some(LeftBrace) => self.parse_compound_statement(state)?,
30 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)?,
31 _ => {
32 PrattParser::parse(state, 0, self);
33 state.eat(Semicolon);
34 }
35 }
36 Ok(())
37 }
38
39 fn parse_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
40 use crate::lexer::CTokenType::*;
41 let cp = state.checkpoint();
42 while state.not_at_end() && !state.at(CTokenType::Semicolon) && !state.at(CTokenType::LeftBrace) {
43 state.advance();
44 }
45 if state.eat(LeftBrace) {
46 while state.not_at_end() && !state.at(RightBrace) {
47 self.parse_statement(state)?;
48 }
49 state.expect(RightBrace).ok();
50 state.finish_at(cp, CElementType::FunctionDefinition);
51 }
52 else {
53 state.eat(Semicolon);
54 state.finish_at(cp, CElementType::DeclarationStatement);
55 }
56 Ok(())
57 }
58
59 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
60 let cp = state.checkpoint();
61 state.bump(); state.expect(CTokenType::LeftParen).ok();
63 PrattParser::parse(state, 0, self);
64 state.expect(CTokenType::RightParen).ok();
65 self.parse_statement(state)?;
66 if state.eat(CTokenType::Else) {
67 self.parse_statement(state)?;
68 }
69 state.finish_at(cp, CElementType::IfStatement);
70 Ok(())
71 }
72
73 fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
74 let cp = state.checkpoint();
75 state.bump(); state.expect(CTokenType::LeftParen).ok();
77 PrattParser::parse(state, 0, self);
78 state.expect(CTokenType::RightParen).ok();
79 self.parse_statement(state)?;
80 state.finish_at(cp, CElementType::WhileStatement);
81 Ok(())
82 }
83
84 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
85 let cp = state.checkpoint();
86 state.bump(); state.expect(CTokenType::LeftParen).ok();
88 while state.not_at_end() && !state.at(CTokenType::RightParen) {
89 state.advance();
90 }
91 state.eat(CTokenType::RightParen);
92 self.parse_statement(state)?;
93 state.finish_at(cp, CElementType::ForStatement);
94 Ok(())
95 }
96
97 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
98 let cp = state.checkpoint();
99 state.bump(); if !state.at(CTokenType::Semicolon) {
101 PrattParser::parse(state, 0, self);
102 }
103 state.eat(CTokenType::Semicolon);
104 state.finish_at(cp, CElementType::ReturnStatement);
105 Ok(())
106 }
107
108 fn parse_compound_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
109 let cp = state.checkpoint();
110 state.expect(CTokenType::LeftBrace).ok();
111 while state.not_at_end() && !state.at(CTokenType::RightBrace) {
112 self.parse_statement(state)?;
113 }
114 state.expect(CTokenType::RightBrace).ok();
115 state.finish_at(cp, CElementType::CompoundStatement);
116 Ok(())
117 }
118}
119
120impl<'config> Pratt<CLanguage> for CParser<'config> {
121 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, CLanguage> {
122 use crate::lexer::CTokenType::*;
123 let cp = state.checkpoint();
124 match state.peek_kind() {
125 Some(Identifier) => {
126 state.bump();
127 state.finish_at(cp, CElementType::Token(Identifier))
128 }
129 Some(IntegerLiteral) | Some(FloatLiteral) | Some(CharLiteral) | Some(StringLiteral) => {
130 let _kind = state.peek_kind().unwrap();
131 state.bump();
132 state.finish_at(cp, CElementType::ExpressionStatement) }
134 Some(LeftParen) => {
135 state.bump();
136 PrattParser::parse(state, 0, self);
137 state.expect(RightParen).ok();
138 state.finish_at(cp, CElementType::ExpressionStatement)
139 }
140 _ => {
141 state.bump();
142 state.finish_at(cp, CElementType::Error)
143 }
144 }
145 }
146
147 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>> {
148 use crate::lexer::CTokenType::*;
149 let kind = state.peek_kind()?;
150
151 let (prec, assoc) = match kind {
152 Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AndAssign | OrAssign | XorAssign | LeftShiftAssign | RightShiftAssign => (1, Associativity::Right),
153 LogicalOr => (2, Associativity::Left),
154 LogicalAnd => (3, Associativity::Left),
155 Equal | NotEqual | Less | Greater | LessEqual | GreaterEqual => (4, Associativity::Left),
156 Plus | Minus => (10, Associativity::Left),
157 Star | Slash | Percent => (11, Associativity::Left),
158 LeftParen | LeftBracket | Dot | Arrow => (15, Associativity::Left),
159 _ => return None,
160 };
161
162 if prec < min_precedence {
163 return None;
164 }
165
166 match kind {
167 LeftParen => {
168 let cp = state.checkpoint();
169 state.push_child(left);
170 state.expect(LeftParen).ok();
171 while state.not_at_end() && !state.at(RightParen) {
172 state.advance();
173 }
174 state.expect(RightParen).ok();
175 Some(state.finish_at(cp, CElementType::ExpressionStatement))
176 }
177 LeftBracket => {
178 let cp = state.checkpoint();
179 state.push_child(left);
180 state.expect(LeftBracket).ok();
181 while state.not_at_end() && !state.at(RightBracket) {
182 state.advance();
183 }
184 state.expect(RightBracket).ok();
185 Some(state.finish_at(cp, CElementType::ExpressionStatement))
186 }
187 Dot | Arrow => {
188 let cp = state.checkpoint();
189 state.push_child(left);
190 state.expect(kind).ok();
191 state.expect(Identifier).ok();
192 Some(state.finish_at(cp, CElementType::ExpressionStatement))
193 }
194 _ => Some(binary(state, left, kind, prec, assoc, CElementType::ExpressionStatement, |s, p| PrattParser::parse(s, p, self))),
195 }
196 }
197}
198
199impl<'config> Parser<CLanguage> for CParser<'config> {
200 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<CLanguage>) -> ParseOutput<'a, CLanguage> {
201 let lexer = crate::lexer::CLexer::new(self.config);
202 parse_with_lexer(&lexer, text, edits, cache, |state| {
203 let cp = state.checkpoint();
204 while state.not_at_end() {
205 self.parse_statement(state).ok();
206 }
207 Ok(state.finish_at(cp, CElementType::Root))
208 })
209 }
210}