Skip to main content

oak_swift/parser/
mod.rs

1/// Element type definitions for Swift parser.
2pub mod element_type;
3
4use crate::language::SwiftLanguage;
5use oak_core::{
6    GreenNode, OakError, TextEdit,
7    parser::{
8        ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
9        pratt::{Associativity, Pratt, PrattParser, binary, unary},
10    },
11    source::Source,
12};
13
14pub(crate) type State<'a, S> = ParserState<'a, SwiftLanguage, S>;
15
16/// Parser for Swift source code.
17pub struct SwiftParser<'config> {
18    pub(crate) config: &'config SwiftLanguage,
19}
20
21impl<'config> SwiftParser<'config> {
22    /// Creates a new SwiftParser with the given language configuration.
23    pub fn new(config: &'config SwiftLanguage) -> Self {
24        Self { config }
25    }
26
27    fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
28        use crate::lexer::SwiftTokenType::*;
29        let kind = state.peek_kind();
30        // eprintln!("Parsing statement at {:?}, kind: {:?}", state.get_position(), kind);
31        match kind {
32            Some(Eof) | None => return Ok(()),
33            Some(Func) => self.parse_function_declaration(state)?,
34            Some(Var) | Some(Let) => self.parse_variable_declaration(state)?,
35            Some(If) => self.parse_if_statement(state)?,
36            Some(While) => self.parse_while_statement(state)?,
37            Some(For) => self.parse_for_statement(state)?,
38            Some(Return) => self.parse_return_statement(state)?,
39            Some(LeftBrace) => self.parse_block(state)?,
40            _ => {
41                let cp = state.checkpoint();
42                PrattParser::parse(state, 0, self);
43                state.eat(Semicolon);
44                state.finish_at(cp, crate::parser::element_type::SwiftElementType::ExpressionStatement);
45            }
46        }
47        Ok(())
48    }
49
50    fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
51        use crate::lexer::SwiftTokenType::*;
52        let cp = state.checkpoint();
53        state.expect(Func).ok();
54        state.expect(Identifier).ok();
55
56        if state.at(LeftParen) {
57            let pcp = state.checkpoint();
58            state.bump(); // (
59            while state.not_at_end() && !state.at(RightParen) {
60                let ppcp = state.checkpoint();
61                state.expect(Identifier).ok();
62                if state.eat(Colon) {
63                    state.expect(Identifier).ok();
64                }
65                state.finish_at(ppcp, crate::parser::element_type::SwiftElementType::Parameter);
66                if state.eat(Comma) {
67                    continue;
68                }
69                break;
70            }
71            state.expect(RightParen).ok();
72            state.finish_at(pcp, crate::parser::element_type::SwiftElementType::ParameterList);
73        }
74
75        if state.eat(Arrow) {
76            state.expect(Identifier).ok();
77        }
78
79        self.parse_block(state)?;
80        state.finish_at(cp, crate::parser::element_type::SwiftElementType::FunctionDeclaration);
81        Ok(())
82    }
83
84    fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
85        use crate::lexer::SwiftTokenType::*;
86        let cp = state.checkpoint();
87        state.bump(); // var/let
88        state.expect(Identifier).ok();
89        if state.eat(Colon) {
90            state.expect(Identifier).ok(); // Type
91        }
92        if state.eat(Assign) {
93            PrattParser::parse(state, 0, self);
94        }
95        state.eat(Semicolon);
96        state.finish_at(cp, crate::parser::element_type::SwiftElementType::VariableDeclaration);
97        Ok(())
98    }
99
100    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
101        use crate::lexer::SwiftTokenType::*;
102        let cp = state.checkpoint();
103        state.expect(If).ok();
104        PrattParser::parse(state, 0, self);
105        self.parse_block(state)?;
106        if state.eat(Else) {
107            if state.at(If) { self.parse_if_statement(state)? } else { self.parse_block(state)? }
108        }
109        state.finish_at(cp, crate::parser::element_type::SwiftElementType::IfStatement);
110        Ok(())
111    }
112
113    fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
114        use crate::lexer::SwiftTokenType::*;
115        let cp = state.checkpoint();
116        state.expect(While).ok();
117        PrattParser::parse(state, 0, self);
118        self.parse_block(state)?;
119        state.finish_at(cp, crate::parser::element_type::SwiftElementType::WhileStatement);
120        Ok(())
121    }
122
123    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
124        use crate::lexer::SwiftTokenType::*;
125        let cp = state.checkpoint();
126        state.expect(For).ok();
127        state.expect(Identifier).ok();
128        state.expect(In).ok();
129        PrattParser::parse(state, 0, self);
130        self.parse_block(state)?;
131        state.finish_at(cp, crate::parser::element_type::SwiftElementType::ForStatement);
132        Ok(())
133    }
134
135    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
136        use crate::lexer::SwiftTokenType::*;
137        let cp = state.checkpoint();
138        state.expect(Return).ok();
139        if state.not_at_end() && !state.at(Semicolon) && !state.at(RightBrace) {
140            PrattParser::parse(state, 0, self);
141        }
142        state.eat(Semicolon);
143        state.finish_at(cp, crate::parser::element_type::SwiftElementType::ReturnStatement);
144        Ok(())
145    }
146
147    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
148        use crate::lexer::SwiftTokenType::*;
149        let cp = state.checkpoint();
150        state.expect(LeftBrace).ok();
151        while state.not_at_end() && !state.at(RightBrace) {
152            self.parse_statement(state)?;
153        }
154        state.expect(RightBrace).ok();
155        state.finish_at(cp, crate::parser::element_type::SwiftElementType::Block);
156        Ok(())
157    }
158}
159
160impl<'config> Pratt<SwiftLanguage> for SwiftParser<'config> {
161    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, SwiftLanguage> {
162        use crate::lexer::SwiftTokenType::*;
163        state.skip_trivia();
164        let cp = state.checkpoint();
165        match state.peek_kind() {
166            Some(Identifier) => {
167                state.bump();
168                state.finish_at(cp, crate::parser::element_type::SwiftElementType::IdentifierExpression)
169            }
170            Some(NumberLiteral) | Some(StringLiteral) | Some(CharLiteral) | Some(BooleanLiteral) | Some(Nil) | Some(True) | Some(False) => {
171                state.bump();
172                state.finish_at(cp, crate::parser::element_type::SwiftElementType::LiteralExpression)
173            }
174            Some(LeftParen) => {
175                state.bump();
176                PrattParser::parse(state, 0, self);
177                state.expect(RightParen).ok();
178                state.finish_at(cp, crate::parser::element_type::SwiftElementType::IdentifierExpression) // Grouping expression
179            }
180            _ => {
181                let kind = state.peek_kind();
182                eprintln!("Unsupported primary kind: {:?}", kind);
183                state.bump();
184                state.finish_at(cp, crate::parser::element_type::SwiftElementType::Error)
185            }
186        }
187    }
188
189    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, SwiftLanguage> {
190        use crate::lexer::token_type::SwiftTokenType::*;
191        let kind = match state.peek_kind() {
192            Some(k) => k,
193            None => return self.primary(state),
194        };
195
196        match kind {
197            Plus | Minus | LogicalNot | BitNot => unary(state, kind, 12, UnaryExpression.into(), |s, p| PrattParser::parse(s, p, self)),
198            _ => self.primary(state),
199        }
200    }
201
202    fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, SwiftLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, SwiftLanguage>> {
203        use crate::lexer::token_type::SwiftTokenType::*;
204        let kind = state.peek_kind()?;
205
206        let (prec, assoc) = match kind {
207            Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AndAssign | OrAssign | XorAssign | LeftShiftAssign | RightShiftAssign => (1, Associativity::Right),
208            LogicalOr => (2, Associativity::Left),
209            LogicalAnd => (3, Associativity::Left),
210            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Is => (5, Associativity::Left),
211            Range | ClosedRange => (6, Associativity::None),
212            Plus | Minus | BitOr | BitXor => (7, Associativity::Left),
213            Star | Slash | Percent | BitAnd | LeftShift | RightShift => (8, Associativity::Left),
214            Dot | QuestionQuestion => (9, Associativity::Left),
215            LeftParen | LeftBracket => (10, Associativity::Left),
216            _ => return None,
217        };
218
219        if prec < min_precedence {
220            return None;
221        }
222
223        match kind {
224            Dot => {
225                let cp = state.checkpoint_before(left);
226                state.bump();
227                state.expect(Identifier).ok();
228                Some(state.finish_at(cp, crate::parser::element_type::SwiftElementType::MemberExpression))
229            }
230            LeftParen => {
231                let cp = state.checkpoint_before(left);
232                state.bump();
233                while state.not_at_end() && !state.at(RightParen) {
234                    PrattParser::parse(state, 0, self);
235                    if !state.eat(Comma) {
236                        break;
237                    }
238                }
239                state.expect(RightParen).ok();
240                Some(state.finish_at(cp, crate::parser::element_type::SwiftElementType::CallExpression))
241            }
242            LeftBracket => {
243                let cp = state.checkpoint_before(left);
244                state.bump();
245                PrattParser::parse(state, 0, self);
246                state.expect(RightBracket).ok();
247                Some(state.finish_at(cp, crate::parser::element_type::SwiftElementType::MemberExpression))
248            }
249            _ => Some(binary(state, left, kind, prec, assoc, BinaryExpression.into(), |s, p| PrattParser::parse(s, p, self))),
250        }
251    }
252}
253
254impl<'config> Parser<SwiftLanguage> for SwiftParser<'config> {
255    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<SwiftLanguage>) -> ParseOutput<'a, SwiftLanguage> {
256        let lexer = crate::lexer::SwiftLexer::new(self.config);
257        parse_with_lexer(&lexer, text, edits, cache, |state| {
258            use crate::lexer::SwiftTokenType::*;
259            let checkpoint = (0, 0);
260
261            while state.not_at_end() && !state.at(Eof) {
262                self.parse_statement(state)?
263            }
264
265            state.eat(Eof);
266
267            Ok(state.finish_at(checkpoint, crate::parser::element_type::SwiftElementType::SourceFile))
268        })
269    }
270}