oak_java/parser/
mod.rs

1use crate::{kind::JavaSyntaxKind, language::JavaLanguage, lexer::JavaLexer};
2use oak_core::{
3    GreenNode, OakError, TextEdit, TokenType,
4    parser::{
5        ParseCache, Parser, ParserState,
6        pratt::{Associativity, Pratt, PrattParser, binary},
7    },
8    source::Source,
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, JavaLanguage, S>;
12
13pub struct JavaParser<'config> {
14    pub(crate) config: &'config JavaLanguage,
15}
16
17impl<'config> Pratt<JavaLanguage> for JavaParser<'config> {
18    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, JavaLanguage> {
19        use crate::kind::JavaSyntaxKind::*;
20        let cp = state.checkpoint();
21        match state.peek_kind() {
22            Some(Identifier) => {
23                state.bump();
24                state.finish_at(cp, Identifier.into())
25            }
26            Some(IntegerLiteral) | Some(FloatingPointLiteral) | Some(BooleanLiteral) | Some(CharacterLiteral) | Some(StringLiteral) | Some(NullLiteral) => {
27                state.bump();
28                state.finish_at(cp, CompilationUnit.into()) // 简化处理
29            }
30            Some(LeftParen) => {
31                state.bump();
32                PrattParser::parse(state, 0, self);
33                state.expect(RightParen).ok();
34                state.finish_at(cp, CompilationUnit.into())
35            }
36            _ => {
37                state.bump();
38                state.finish_at(cp, Error.into())
39            }
40        }
41    }
42
43    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, JavaLanguage> {
44        self.primary(state)
45    }
46
47    fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, JavaLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, JavaLanguage>> {
48        use crate::kind::JavaSyntaxKind::*;
49        let kind = state.peek_kind()?;
50
51        let (prec, assoc) = match kind {
52            Assign | PlusEquals | MinusEquals | AsteriskEquals | SlashEquals | PercentEquals | LeftShiftEquals | RightShiftEquals | UnsignedRightShiftEquals | AmpersandEquals | PipeEquals | CaretEquals => (1, Associativity::Right),
53            PipePipe => (2, Associativity::Left),
54            AmpersandAmpersand => (3, Associativity::Left),
55            Equals | BangEquals | LessThan | GreaterThan | LessThanEquals | GreaterThanEquals => (4, Associativity::Left),
56            Plus | Minus => (10, Associativity::Left),
57            Asterisk | Slash | Percent => (11, Associativity::Left),
58            LeftParen | Dot => (15, Associativity::Left),
59            _ => return None,
60        };
61
62        if prec < min_precedence {
63            return None;
64        }
65
66        match kind {
67            LeftParen => {
68                let cp = state.checkpoint();
69                state.push_child(left);
70                state.expect(LeftParen).ok();
71                while state.not_at_end() && !state.at(RightParen) {
72                    state.advance();
73                }
74                state.expect(RightParen).ok();
75                Some(state.finish_at(cp, CompilationUnit.into()))
76            }
77            Dot => {
78                let cp = state.checkpoint();
79                state.push_child(left);
80                state.expect(Dot).ok();
81                state.expect(Identifier).ok();
82                Some(state.finish_at(cp, CompilationUnit.into()))
83            }
84            _ => Some(binary(state, left, kind, prec, assoc, CompilationUnit.into(), |s, p| PrattParser::parse(s, p, self))),
85        }
86    }
87}
88
89impl<'config> JavaParser<'config> {
90    pub fn new(config: &'config JavaLanguage) -> Self {
91        Self { config }
92    }
93
94    fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
95        use crate::kind::JavaSyntaxKind::*;
96        match state.peek_kind() {
97            Some(Public) | Some(Private) | Some(Protected) | Some(Static) | Some(Final) | Some(Class) | Some(Interface) | Some(Enum) => self.parse_declaration(state)?,
98            Some(If) => self.parse_if_statement(state)?,
99            Some(While) => self.parse_while_statement(state)?,
100            Some(For) => self.parse_for_statement(state)?,
101            Some(Return) => self.parse_return_statement(state)?,
102            Some(LeftBrace) => self.parse_block_statement(state)?,
103            Some(Package) => self.parse_package_declaration(state)?,
104            Some(Import) => self.parse_import_declaration(state)?,
105            _ => {
106                PrattParser::parse(state, 0, self);
107                state.eat(Semicolon);
108            }
109        }
110        Ok(())
111    }
112
113    fn parse_package_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
114        use crate::kind::JavaSyntaxKind::*;
115        state.expect(Package).ok();
116        state.advance_until(Semicolon);
117        state.eat(Semicolon);
118        Ok(())
119    }
120
121    fn parse_import_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
122        use crate::kind::JavaSyntaxKind::*;
123        state.expect(Import).ok();
124        state.advance_until(Semicolon);
125        state.eat(Semicolon);
126        Ok(())
127    }
128
129    fn parse_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
130        use crate::kind::JavaSyntaxKind::*;
131        // 处理修饰符
132        while state.not_at_end() && matches!(state.peek_kind(), Some(Public) | Some(Private) | Some(Protected) | Some(Static) | Some(Final) | Some(Abstract)) {
133            state.bump();
134        }
135
136        match state.peek_kind() {
137            Some(Class) => self.parse_class_declaration(state)?,
138            Some(Interface) => self.parse_interface_declaration(state)?,
139            Some(Enum) => self.parse_enum_declaration(state)?,
140            _ => {
141                // 可能是方法或字段
142                state.advance_until(Semicolon);
143                state.eat(Semicolon);
144            }
145        }
146        Ok(())
147    }
148
149    fn parse_class_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
150        use crate::kind::JavaSyntaxKind::*;
151        state.expect(Class).ok();
152        state.expect(Identifier).ok();
153        if state.eat(Extends) {
154            state.expect(Identifier).ok();
155        }
156        if state.eat(Implements) {
157            while state.not_at_end() && !state.at(LeftBrace) {
158                state.advance();
159            }
160        }
161        self.parse_block_statement(state)?;
162        Ok(())
163    }
164
165    fn parse_interface_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
166        use crate::kind::JavaSyntaxKind::*;
167        state.expect(Interface).ok();
168        state.expect(Identifier).ok();
169        self.parse_block_statement(state)?;
170        Ok(())
171    }
172
173    fn parse_enum_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
174        use crate::kind::JavaSyntaxKind::*;
175        state.expect(Enum).ok();
176        state.expect(Identifier).ok();
177        self.parse_block_statement(state)?;
178        Ok(())
179    }
180
181    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
182        state.bump(); // if
183        state.expect(crate::kind::JavaSyntaxKind::LeftParen).ok();
184        PrattParser::parse(state, 0, self);
185        state.expect(crate::kind::JavaSyntaxKind::RightParen).ok();
186        self.parse_statement(state)?;
187        if state.eat(crate::kind::JavaSyntaxKind::Else) {
188            self.parse_statement(state)?;
189        }
190        Ok(())
191    }
192
193    fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
194        state.bump(); // while
195        state.expect(crate::kind::JavaSyntaxKind::LeftParen).ok();
196        PrattParser::parse(state, 0, self);
197        state.expect(crate::kind::JavaSyntaxKind::RightParen).ok();
198        self.parse_statement(state)?;
199        Ok(())
200    }
201
202    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
203        state.bump(); // for
204        state.expect(crate::kind::JavaSyntaxKind::LeftParen).ok();
205        PrattParser::parse(state, 0, self);
206        state.expect(crate::kind::JavaSyntaxKind::RightParen).ok();
207        self.parse_statement(state)?;
208        Ok(())
209    }
210
211    fn parse_block_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
212        state.expect(crate::kind::JavaSyntaxKind::LeftBrace).ok();
213        while state.not_at_end() && !state.at(crate::kind::JavaSyntaxKind::RightBrace) {
214            self.parse_statement(state)?;
215        }
216        state.expect(crate::kind::JavaSyntaxKind::RightBrace).ok();
217        Ok(())
218    }
219
220    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
221        state.bump(); // return
222        if !state.at(crate::kind::JavaSyntaxKind::Semicolon) && !state.at(crate::kind::JavaSyntaxKind::RightBrace) {
223            PrattParser::parse(state, 0, self);
224        }
225        state.eat(crate::kind::JavaSyntaxKind::Semicolon);
226        Ok(())
227    }
228}
229
230impl<'config> Parser<JavaLanguage> for JavaParser<'config> {
231    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<JavaLanguage>) -> oak_core::ParseOutput<'a, JavaLanguage> {
232        let lexer = JavaLexer::new(self.config);
233        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
234            let checkpoint = state.checkpoint();
235            while state.not_at_end() {
236                if state.current().map(|t| t.kind.is_ignored()).unwrap_or(false) {
237                    state.advance();
238                    continue;
239                }
240                self.parse_statement(state).ok();
241            }
242            Ok(state.finish_at(checkpoint, JavaSyntaxKind::CompilationUnit.into()))
243        })
244    }
245}