1pub mod element_type;
3
4use crate::language::PerlLanguage;
5use oak_core::{
6 OakError,
7 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
8 source::{Source, TextEdit},
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, PerlLanguage, S>;
12
13pub struct PerlParser<'config> {
17 pub(crate) config: &'config PerlLanguage,
19}
20
21impl<'config> PerlParser<'config> {
22 pub fn new(config: &'config PerlLanguage) -> Self {
24 Self { config }
25 }
26
27 pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
29 use crate::lexer::token_type::PerlTokenType::*;
30 self.skip_trivia(state);
31
32 if !state.not_at_end() {
33 return Ok(());
34 }
35
36 match state.peek_kind() {
37 Some(Sub) => self.parse_sub_declaration(state),
38 Some(Package) => self.parse_package_declaration(state),
39 Some(Use) => self.parse_use_statement(state),
40 Some(If) => self.parse_if_statement(state),
41 Some(Unless) => self.parse_unless_statement(state),
42 Some(While) => self.parse_while_statement(state),
43 Some(Until) => self.parse_until_statement(state),
44 Some(For) | Some(Foreach) => self.parse_for_statement(state),
45 Some(Do) => self.parse_do_statement(state),
46 Some(My) | Some(Our) | Some(Local) => self.parse_variable_declaration(state),
47 _ => self.parse_expression_statement(state),
48 }
49 }
50
51 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
52 use crate::lexer::token_type::PerlTokenType::*;
53 while state.at(Whitespace) || state.at(Newline) || state.at(Comment) {
54 state.bump();
55 }
56 }
57
58 fn parse_sub_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
59 use crate::lexer::token_type::PerlTokenType::*;
60 let cp = state.checkpoint();
61 state.expect(Sub)?;
62 self.skip_trivia(state);
63 state.expect(Identifier).ok();
64 self.skip_trivia(state);
65 if state.at(LeftBrace) {
66 self.parse_block(state)?;
67 }
68 else {
69 state.expect(Semicolon).ok();
70 }
71 state.finish_at(cp, element_type::PerlElementType::SubroutineDeclaration);
72 Ok(())
73 }
74
75 fn parse_package_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
76 use crate::lexer::token_type::PerlTokenType::*;
77 let cp = state.checkpoint();
78 state.expect(Package)?;
79 self.skip_trivia(state);
80 state.expect(Identifier)?;
81 self.skip_trivia(state);
82 state.expect(Semicolon)?;
83 state.finish_at(cp, element_type::PerlElementType::PackageDeclaration);
84 Ok(())
85 }
86
87 fn parse_use_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
88 use crate::lexer::token_type::PerlTokenType::*;
89 let cp = state.checkpoint();
90 state.expect(Use)?;
91 self.skip_trivia(state);
92 state.expect(Identifier)?;
93 self.skip_trivia(state);
94 while state.not_at_end() && !state.at(Semicolon) {
95 state.bump();
96 }
97 state.expect(Semicolon).ok();
98 state.finish_at(cp, element_type::PerlElementType::UseStatement);
99 Ok(())
100 }
101
102 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
103 use crate::lexer::token_type::PerlTokenType::*;
104 let cp = state.checkpoint();
105 state.expect(If)?;
106 self.skip_trivia(state);
107 state.expect(LeftParen)?;
108 while state.not_at_end() && !state.at(RightParen) {
109 state.bump();
110 }
111 state.expect(RightParen).ok();
112 self.skip_trivia(state);
113 self.parse_block(state)?;
114
115 self.skip_trivia(state);
116 while state.at(Elsif) {
117 state.bump();
118 self.skip_trivia(state);
119 state.expect(LeftParen)?;
120 while state.not_at_end() && !state.at(RightParen) {
121 state.bump();
122 }
123 state.expect(RightParen).ok();
124 self.skip_trivia(state);
125 self.parse_block(state)?;
126 self.skip_trivia(state);
127 }
128
129 if state.at(Else) {
130 state.bump();
131 self.skip_trivia(state);
132 self.parse_block(state)?;
133 }
134
135 state.finish_at(cp, element_type::PerlElementType::IfStatement);
136 Ok(())
137 }
138
139 fn parse_unless_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
140 use crate::lexer::token_type::PerlTokenType::*;
141 let cp = state.checkpoint();
142 state.expect(Unless)?;
143 self.skip_trivia(state);
144 state.expect(LeftParen)?;
145 while state.not_at_end() && !state.at(RightParen) {
146 state.bump();
147 }
148 state.expect(RightParen).ok();
149 self.skip_trivia(state);
150 self.parse_block(state)?;
151 state.finish_at(cp, element_type::PerlElementType::UnlessStatement);
152 Ok(())
153 }
154
155 fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
156 use crate::lexer::token_type::PerlTokenType::*;
157 let cp = state.checkpoint();
158 state.expect(While)?;
159 self.skip_trivia(state);
160 state.expect(LeftParen)?;
161 while state.not_at_end() && !state.at(RightParen) {
162 state.bump();
163 }
164 state.expect(RightParen).ok();
165 self.skip_trivia(state);
166 self.parse_block(state)?;
167 state.finish_at(cp, element_type::PerlElementType::WhileStatement);
168 Ok(())
169 }
170
171 fn parse_until_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
172 use crate::lexer::token_type::PerlTokenType::*;
173 let cp = state.checkpoint();
174 state.expect(Until)?;
175 self.skip_trivia(state);
176 state.expect(LeftParen)?;
177 while state.not_at_end() && !state.at(RightParen) {
178 state.bump();
179 }
180 state.expect(RightParen).ok();
181 self.skip_trivia(state);
182 self.parse_block(state)?;
183 state.finish_at(cp, element_type::PerlElementType::UntilStatement);
184 Ok(())
185 }
186
187 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
188 use crate::lexer::token_type::PerlTokenType::*;
189 let cp = state.checkpoint();
190 if state.at(For) {
191 state.bump();
192 }
193 else {
194 state.expect(Foreach)?;
195 }
196 self.skip_trivia(state);
197 if state.at(LeftParen) {
198 state.bump();
199 while state.not_at_end() && !state.at(RightParen) {
200 state.bump();
201 }
202 state.expect(RightParen).ok();
203 }
204 self.skip_trivia(state);
205 self.parse_block(state)?;
206 state.finish_at(cp, element_type::PerlElementType::ForStatement);
207 Ok(())
208 }
209
210 fn parse_do_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
211 use crate::lexer::token_type::PerlTokenType::*;
212 let cp = state.checkpoint();
213 state.expect(Do)?;
214 self.skip_trivia(state);
215 if state.at(LeftBrace) {
216 self.parse_block(state)?;
217 }
218 else {
219 while state.not_at_end() && !state.at(Semicolon) {
221 state.bump();
222 }
223 }
224 state.expect(Semicolon).ok();
225 state.finish_at(cp, element_type::PerlElementType::DoStatement);
226 Ok(())
227 }
228
229 fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
230 use crate::lexer::token_type::PerlTokenType::*;
231 let cp = state.checkpoint();
232 state.bump(); self.skip_trivia(state);
234 while state.not_at_end() && !state.at(Semicolon) {
235 state.bump();
236 }
237 state.expect(Semicolon).ok();
238 state.finish_at(cp, element_type::PerlElementType::VariableDeclaration);
239 Ok(())
240 }
241
242 fn parse_expression_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
243 use crate::lexer::token_type::PerlTokenType::*;
244 let cp = state.checkpoint();
245 while state.not_at_end() && !state.at(Semicolon) {
246 state.bump();
247 }
248 state.expect(Semicolon).ok();
249 state.finish_at(cp, element_type::PerlElementType::Statement);
250 Ok(())
251 }
252
253 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
254 use crate::lexer::token_type::PerlTokenType::*;
255 let cp = state.checkpoint();
256 state.expect(LeftBrace)?;
257 while state.not_at_end() && !state.at(RightBrace) {
258 self.parse_statement(state)?;
259 }
260 state.expect(RightBrace).ok();
261 state.finish_at(cp, element_type::PerlElementType::Block);
262 Ok(())
263 }
264}
265
266impl<'config> Parser<PerlLanguage> for PerlParser<'config> {
267 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<PerlLanguage>) -> ParseOutput<'a, PerlLanguage> {
268 let lexer = crate::lexer::PerlLexer::new(&self.config);
269 parse_with_lexer(&lexer, text, edits, cache, |state| {
270 let checkpoint = state.checkpoint();
271 while state.not_at_end() {
272 if self.parse_statement(state).is_err() {
273 break;
274 }
275 }
276 Ok(state.finish_at(checkpoint, element_type::PerlElementType::Root))
277 })
278 }
279}