Skip to main content

oak_j/parser/
mod.rs

1#![doc = include_str!("readme.md")]
2pub mod element_type;
3
4pub use element_type::JElementType;
5
6use crate::{language::JLanguage, lexer::JTokenType};
7use oak_core::{
8    OakError, TextEdit,
9    parser::{ParseCache, ParseOutput, Parser, ParserState},
10    source::Source,
11};
12
13pub(crate) type State<'a, S> = ParserState<'a, JLanguage, S>;
14
15pub struct JParser<'config> {
16    pub(crate) config: &'config JLanguage,
17}
18
19impl<'config> JParser<'config> {
20    pub fn new(config: &'config JLanguage) -> Self {
21        Self { config }
22    }
23
24    /// 解析 J 源代码的内部逻辑
25    fn run<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<&'a oak_core::GreenNode<'a, JLanguage>, OakError> {
26        let root_cp = state.checkpoint();
27        let unit_cp = state.checkpoint();
28
29        while state.not_at_end() {
30            if !self.parse_sentence(state) {
31                state.advance();
32            }
33        }
34
35        state.finish_at(unit_cp, JElementType::CompilationUnit);
36        let root = state.finish_at(root_cp, JElementType::Root);
37
38        Ok(root)
39    }
40
41    /// 解析句子 (Sentence)
42    fn parse_sentence<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> bool {
43        let cp = state.checkpoint();
44
45        // 简单的赋值或表达式解析
46        let mut matched = false;
47        if state.at(JTokenType::Identifier) && (state.peek_kind_at(1) == Some(JTokenType::IsGlobal) || state.peek_kind_at(1) == Some(JTokenType::IsLocal)) {
48            matched = self.parse_assignment(state);
49        }
50        else {
51            matched = self.parse_expression(state);
52        }
53
54        if matched {
55            state.finish_at(cp, JElementType::Sentence);
56        }
57        matched
58    }
59
60    /// 解析赋值 (Assignment)
61    fn parse_assignment<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> bool {
62        let cp = state.checkpoint();
63        state.eat(JTokenType::Identifier);
64        if state.at(JTokenType::IsGlobal) {
65            state.eat(JTokenType::IsGlobal);
66        }
67        else {
68            state.eat(JTokenType::IsLocal);
69        }
70        self.parse_expression(state);
71        state.finish_at(cp, JElementType::Assignment);
72        true
73    }
74
75    /// 解析表达式 (Expression)
76    fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> bool {
77        let cp = state.checkpoint();
78        let mut matched = false;
79
80        while state.not_at_end() && !state.at(JTokenType::Newline) && !state.at(JTokenType::Eof) {
81            if state.at(JTokenType::Identifier) {
82                state.eat(JTokenType::Identifier);
83                matched = true;
84            }
85            else if state.at(JTokenType::NumberLiteral) {
86                state.eat(JTokenType::NumberLiteral);
87                matched = true;
88            }
89            else if state.at(JTokenType::StringLiteral) {
90                state.eat(JTokenType::StringLiteral);
91                matched = true;
92            }
93            else if state.at(JTokenType::LeftParen) {
94                let group_cp = state.checkpoint();
95                state.eat(JTokenType::LeftParen);
96                self.parse_expression(state);
97                let _ = state.expect(JTokenType::RightParen);
98                state.finish_at(group_cp, JElementType::Group);
99                matched = true;
100            }
101            else {
102                // 可能是操作符
103                state.advance();
104                matched = true;
105            }
106        }
107
108        if matched {
109            state.finish_at(cp, JElementType::Expression);
110        }
111        matched
112    }
113}
114
115impl<'config> Parser<JLanguage> for JParser<'config> {
116    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<JLanguage>) -> ParseOutput<'a, JLanguage> {
117        let lexer = crate::lexer::JLexer::new(self.config);
118        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| self.run(state))
119    }
120}