oak_ruby/parser/
mod.rs

1use crate::{kind::RubySyntaxKind, language::RubyLanguage, lexer::RubyLexer};
2use oak_core::{
3    GreenNode, OakError, TextEdit,
4    parser::{
5        ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
6        pratt::{Associativity, Pratt, PrattParser, binary, unary},
7    },
8    source::Source,
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, RubyLanguage, S>;
12
13pub struct RubyParser<'config> {
14    pub(crate) config: &'config RubyLanguage,
15}
16
17impl<'config> RubyParser<'config> {
18    pub fn new(config: &'config RubyLanguage) -> Self {
19        Self { config }
20    }
21
22    pub(crate) fn parse_root_internal<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<&'a GreenNode<'a, RubyLanguage>, OakError> {
23        let cp = state.checkpoint();
24        while state.not_at_end() {
25            if state.peek_kind().map(|k| k.is_ignored()).unwrap_or(false) {
26                state.bump();
27                continue;
28            }
29            self.parse_statement(state).ok();
30        }
31        Ok(state.finish_at(cp, RubySyntaxKind::Root))
32    }
33
34    fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
35        use crate::kind::RubySyntaxKind::*;
36        match state.peek_kind() {
37            Some(Def) => self.parse_method_def(state)?,
38            Some(Class) => self.parse_class_def(state)?,
39            Some(Module) => self.parse_module_def(state)?,
40            Some(If) => self.parse_if_stmt(state)?,
41            Some(While) => self.parse_while_stmt(state)?,
42            Some(Return) => self.parse_return_stmt(state)?,
43            _ => {
44                PrattParser::parse(state, 0, self);
45                state.eat(Semicolon);
46                state.eat(Newline);
47            }
48        }
49        Ok(())
50    }
51
52    fn parse_method_def<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
53        use crate::kind::RubySyntaxKind::*;
54        let cp = state.checkpoint();
55        state.bump(); // def
56        state.expect(Identifier).ok();
57        if state.eat(LeftParen) {
58            while state.not_at_end() && !state.at(RightParen) {
59                state.advance();
60            }
61            state.expect(RightParen).ok();
62        }
63        self.parse_body(state)?;
64        state.finish_at(cp, MethodDefinition);
65        Ok(())
66    }
67
68    fn parse_body<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
69        use crate::kind::RubySyntaxKind::*;
70        while state.not_at_end() && !state.at(End) && !state.at(Else) && !state.at(Elsif) && !state.at(Rescue) && !state.at(Ensure) {
71            self.parse_statement(state)?;
72        }
73        state.eat(End);
74        Ok(())
75    }
76
77    fn parse_class_def<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
78        use crate::kind::RubySyntaxKind::*;
79        let cp = state.checkpoint();
80        state.bump(); // class
81        state.expect(Constant).ok();
82        self.parse_body(state)?;
83        state.finish_at(cp, ClassDefinition);
84        Ok(())
85    }
86
87    fn parse_module_def<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
88        use crate::kind::RubySyntaxKind::*;
89        let cp = state.checkpoint();
90        state.bump(); // module
91        state.expect(Constant).ok();
92        self.parse_body(state)?;
93        state.finish_at(cp, ModuleDefinition);
94        Ok(())
95    }
96
97    fn parse_if_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
98        use crate::kind::RubySyntaxKind::*;
99        let cp = state.checkpoint();
100        state.bump(); // if
101        PrattParser::parse(state, 0, self);
102        self.parse_body(state)?;
103        state.finish_at(cp, IfStatement);
104        Ok(())
105    }
106
107    fn parse_while_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
108        use crate::kind::RubySyntaxKind::*;
109        let cp = state.checkpoint();
110        state.bump(); // while
111        PrattParser::parse(state, 0, self);
112        self.parse_body(state)?;
113        state.finish_at(cp, WhileStatement);
114        Ok(())
115    }
116
117    fn parse_return_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
118        use crate::kind::RubySyntaxKind::*;
119        let cp = state.checkpoint();
120        state.bump(); // return
121        PrattParser::parse(state, 0, self);
122        state.finish_at(cp, ReturnStatement);
123        Ok(())
124    }
125}
126
127impl<'config> Pratt<RubyLanguage> for RubyParser<'config> {
128    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, RubyLanguage> {
129        use crate::kind::RubySyntaxKind::*;
130        let cp = state.checkpoint();
131        match state.peek_kind() {
132            Some(Identifier) | Some(Constant) | Some(GlobalVariable) | Some(InstanceVariable) | Some(ClassVariable) => {
133                state.bump();
134                state.finish_at(cp, Identifier)
135            }
136            Some(IntegerLiteral) | Some(FloatLiteral) | Some(StringLiteral) | Some(True) | Some(False) | Some(Nil) | Some(Self_) => {
137                state.bump();
138                state.finish_at(cp, LiteralExpression) // 简化处理
139            }
140            Some(LeftParen) => {
141                state.bump();
142                PrattParser::parse(state, 0, self);
143                state.expect(RightParen).ok();
144                state.finish_at(cp, ParenExpression) // 简化处理
145            }
146            _ => {
147                state.bump();
148                state.finish_at(cp, Error)
149            }
150        }
151    }
152
153    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, RubyLanguage> {
154        use crate::kind::RubySyntaxKind::*;
155        match state.peek_kind() {
156            Some(kind @ (Plus | Minus | Not | Tilde)) => {
157                state.bump();
158                unary(state, kind, 13, UnaryExpression, |st, p| PrattParser::parse(st, p, self))
159            }
160            _ => self.primary(state),
161        }
162    }
163
164    fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, RubyLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, RubyLanguage>> {
165        use crate::kind::RubySyntaxKind::*;
166        let kind = state.peek_kind()?;
167
168        let (prec, assoc) = match kind {
169            Power => (30, Associativity::Right),
170            Multiply | Divide | Modulo => (20, Associativity::Left),
171            Plus | Minus => (10, Associativity::Left),
172            EqualEqual | NotEqual | Less | Greater | LessEqual | GreaterEqual => (5, Associativity::Left),
173            AndAnd => (2, Associativity::Left),
174            OrOr => (1, Associativity::Left),
175            _ => return None,
176        };
177
178        if prec < min_precedence {
179            return None;
180        }
181
182        Some(binary(state, left, kind, prec, assoc, BinaryExpression, |s, p| PrattParser::parse(s, p, self)))
183    }
184}
185
186impl<'config> Parser<RubyLanguage> for RubyParser<'config> {
187    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<RubyLanguage>) -> ParseOutput<'a, RubyLanguage> {
188        let lexer = RubyLexer::new(self.config);
189        parse_with_lexer(&lexer, text, edits, cache, |state| self.parse_root_internal(state))
190    }
191}