oak_java/parser/mod.rs
1use oak_core::TokenType;
2
3/// Java element types.
4pub mod element_type;
5
6mod parse_declaration;
7mod parse_expression;
8mod parse_statement;
9
10use crate::{
11 language::JavaLanguage,
12 lexer::{JavaLexer, token_type::JavaTokenType},
13 parser::element_type::JavaElementType,
14};
15use oak_core::{
16 GreenNode, OakError, TextEdit,
17 parser::{
18 ParseCache, Parser, ParserState,
19 pratt::{Pratt, PrattParser},
20 },
21 source::Source,
22};
23
24/// Parser state type alias for Java parsing
25pub(crate) type State<'a, S> = ParserState<'a, JavaLanguage, S>;
26
27/// Java parser implementation that handles Java source code parsing
28///
29/// This parser supports modern Java features including:
30/// - Records
31/// - Sealed classes
32/// - Lambdas
33/// - Annotations
34/// - Generics
35/// - Pattern matching
36///
37/// # Example
38/// ```rust
39/// use oak_java::{JavaLanguage, JavaParser, SourceText};
40///
41/// let code = r#"
42/// public class Example {
43/// public static void main(String[] args) {
44/// System.out.println("Hello, World!");
45/// }
46/// }
47/// "#;
48///
49/// let source = SourceText::new(code);
50/// let config = JavaLanguage::new();
51/// let parser = JavaParser::new(&config);
52/// let result = parser.parse(&source);
53///
54/// assert!(result.is_success());
55/// ```
56pub struct JavaParser<'config> {
57 /// Parser configuration containing language-specific settings
58 pub(crate) config: &'config JavaLanguage,
59}
60
61impl<'config> JavaParser<'config> {
62 /// Creates a new `JavaParser` with the given configuration
63 ///
64 /// # Parameters
65 /// - `config`: The Java language configuration
66 ///
67 /// # Returns
68 /// A new instance of `JavaParser`
69 ///
70 /// # Example
71 /// ```rust
72 /// use oak_java::{JavaLanguage, JavaParser};
73 ///
74 /// let config = JavaLanguage::new();
75 /// let parser = JavaParser::new(&config);
76 /// ```
77 pub fn new(config: &'config JavaLanguage) -> Self {
78 Self { config }
79 }
80
81 /// Skip trivia tokens (whitespace, comments)
82 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
83 while state.not_at_end() {
84 let kind = state.peek_kind().unwrap();
85 if kind.is_ignored() {
86 state.bump();
87 }
88 else {
89 break;
90 }
91 }
92 }
93
94 fn parse_item<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
95 parse_statement::parse_statement(self, state)
96 }
97}
98
99impl<'config> Pratt<JavaLanguage> for JavaParser<'config> {
100 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, JavaLanguage> {
101 parse_expression::primary(self, state)
102 }
103
104 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, JavaLanguage> {
105 parse_expression::prefix(self, state)
106 }
107
108 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>> {
109 parse_expression::infix(self, state, left, min_precedence)
110 }
111}
112
113impl<'config> parse_declaration::DeclarationParser for JavaParser<'config> {}
114
115impl<'config> Parser<JavaLanguage> for JavaParser<'config> {
116 /// Parses Java source code into an abstract syntax tree
117 ///
118 /// # Parameters
119 /// - `text`: The source text to parse
120 /// - `edits`: Text edits for incremental parsing
121 /// - `cache`: Parse cache for incremental parsing
122 ///
123 /// # Returns
124 /// A parse output containing the syntax tree and diagnostics
125 ///
126 /// # Example
127 /// ```rust
128 /// use oak_core::parser::DefaultParseCache;
129 /// use oak_java::{JavaLanguage, JavaParser, SourceText};
130 ///
131 /// let code = "public class Example { }";
132 /// let source = SourceText::new(code);
133 /// let config = JavaLanguage::new();
134 /// let parser = JavaParser::new(&config);
135 /// let mut cache = DefaultParseCache::default();
136 ///
137 /// let result = parser.parse(&source, &[], &mut cache);
138 /// println!("Parse success: {}", result.is_success());
139 /// ```
140 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<JavaLanguage>) -> oak_core::parser::ParseOutput<'a, JavaLanguage> {
141 let lexer = JavaLexer::new(self.config);
142 oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
143 let checkpoint = state.checkpoint();
144 while state.not_at_end() {
145 self.parse_item(state).ok();
146 }
147 Ok(state.finish_at(checkpoint, JavaElementType::CompilationUnit))
148 })
149 }
150}