oak_c/parser/
mod.rs

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(); // if
62        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(); // while
76        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(); // for
87        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(); // return
100        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) // įŽ€åŒ–å¤„į†
133            }
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}