1pub mod element_type;
3
4use crate::{
5 language::JuliaLanguage,
6 lexer::{JuliaLexer, token_type::JuliaTokenType},
7 parser::element_type::JuliaElementType,
8};
9use oak_core::{
10 OakError,
11 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
12 source::{Source, TextEdit},
13};
14
15pub(crate) type State<'a, S> = ParserState<'a, JuliaLanguage, S>;
17
18pub struct JuliaParser<'config> {
20 pub(crate) config: &'config JuliaLanguage,
21}
22
23impl<'config> JuliaParser<'config> {
24 pub fn new(config: &'config JuliaLanguage) -> Self {
26 Self { config }
27 }
28
29 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
30 while state.not_at_end() {
31 if let Some(kind) = state.peek_kind() {
32 if kind.is_trivia() {
33 state.bump();
34 continue;
35 }
36 }
37 break;
38 }
39 }
40
41 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
42 self.skip_trivia(state);
43 if state.at(JuliaTokenType::Function) {
44 self.parse_function(state)?;
45 }
46 else if state.at(JuliaTokenType::If) {
47 self.parse_if(state)?;
48 }
49 else if state.at(JuliaTokenType::For) {
50 self.parse_for(state)?;
51 }
52 else if state.at(JuliaTokenType::End) {
53 state.bump();
56 }
57 else {
58 self.parse_expression(state)?;
59 }
60 Ok(())
61 }
62
63 fn parse_if<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
64 let cp = state.checkpoint();
65 state.bump(); self.skip_trivia(state);
67
68 self.parse_expression(state)?;
69 self.skip_trivia(state);
70
71 while state.not_at_end() && !state.at(JuliaTokenType::Else) && !state.at(JuliaTokenType::ElseIf) && !state.at(JuliaTokenType::End) {
73 self.parse_statement(state)?;
74 self.skip_trivia(state);
75 }
76
77 if state.at(JuliaTokenType::Else) || state.at(JuliaTokenType::ElseIf) {
78 state.bump();
79 self.skip_trivia(state);
80 while state.not_at_end() && !state.at(JuliaTokenType::End) {
81 self.parse_statement(state)?;
82 self.skip_trivia(state);
83 }
84 }
85
86 if state.at(JuliaTokenType::End) {
87 state.bump();
88 }
89
90 state.finish_at(cp, JuliaElementType::If);
91 Ok(())
92 }
93
94 fn parse_for<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
95 let cp = state.checkpoint();
96 state.bump(); self.skip_trivia(state);
98
99 if state.at(JuliaTokenType::Identifier) {
100 state.bump();
101 }
102 self.skip_trivia(state);
103
104 if state.at(JuliaTokenType::Equal) || state.at(JuliaTokenType::In) {
105 state.bump();
106 }
107 self.skip_trivia(state);
108
109 self.parse_expression(state)?;
110 self.skip_trivia(state);
111
112 while state.not_at_end() && !state.at(JuliaTokenType::End) {
114 self.parse_statement(state)?;
115 self.skip_trivia(state);
116 }
117
118 if state.at(JuliaTokenType::End) {
119 state.bump();
120 }
121
122 state.finish_at(cp, JuliaElementType::For);
123 Ok(())
124 }
125
126 fn parse_function<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
127 let cp = state.checkpoint();
128 state.bump(); self.skip_trivia(state);
130
131 if state.at(JuliaTokenType::Identifier) {
132 let name_cp = state.checkpoint();
133 state.bump(); state.finish_at(name_cp, JuliaElementType::Identifier);
135 }
136
137 if state.at(JuliaTokenType::LeftParen) {
138 state.bump();
139 self.skip_trivia(state);
140 while state.not_at_end() && !state.at(JuliaTokenType::RightParen) {
142 state.bump();
143 }
144 if state.at(JuliaTokenType::RightParen) {
145 state.bump();
146 }
147 }
148
149 self.skip_trivia(state);
150
151 while state.not_at_end() && !state.at(JuliaTokenType::End) {
153 self.parse_statement(state)?;
154 self.skip_trivia(state);
155 }
156
157 if state.at(JuliaTokenType::End) {
158 state.bump();
159 }
160
161 state.finish_at(cp, JuliaElementType::Function);
162 Ok(())
163 }
164
165 fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
166 self.skip_trivia(state);
167 let cp = state.checkpoint();
168
169 if state.at(JuliaTokenType::Identifier) {
170 state.bump();
171 let id_node = state.finish_at(cp, JuliaElementType::Identifier);
172 self.skip_trivia(state);
173 if state.at(JuliaTokenType::LeftParen) {
174 let call_cp = state.checkpoint_before(id_node);
176 state.bump(); self.skip_trivia(state);
178 let arg_cp = state.checkpoint();
179 while state.not_at_end() && !state.at(JuliaTokenType::RightParen) {
180 self.parse_expression(state)?;
181 self.skip_trivia(state);
182 if state.at(JuliaTokenType::Comma) {
183 state.bump();
184 self.skip_trivia(state);
185 }
186 }
187 state.finish_at(arg_cp, JuliaElementType::ArgumentList);
188 if state.at(JuliaTokenType::RightParen) {
189 state.bump();
190 }
191 state.finish_at(call_cp, JuliaElementType::Call);
192 }
193 }
194 else if state.at(JuliaTokenType::StringLiteral) {
195 state.bump();
196 state.finish_at(cp, JuliaElementType::StringLiteral);
197 }
198 else if state.not_at_end() {
199 state.bump();
200 }
201
202 Ok(())
203 }
204}
205
206impl<'config> Parser<JuliaLanguage> for JuliaParser<'config> {
207 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<JuliaLanguage>) -> ParseOutput<'a, JuliaLanguage> {
208 let lexer = JuliaLexer::new(&self.config);
209 parse_with_lexer(&lexer, text, edits, cache, |state| {
210 let checkpoint = state.checkpoint();
211
212 while state.not_at_end() {
213 self.skip_trivia(state);
214 if !state.not_at_end() {
215 break;
216 }
217 self.parse_statement(state)?;
218 }
219
220 Ok(state.finish_at(checkpoint, JuliaElementType::Root))
221 })
222 }
223}