Skip to main content

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}