1use std::fmt;
2
3use crate::{keywords::Keyword, lexer::Lexer, token::Token};
4
5mod advanced_objects;
6mod alter;
7mod create;
8mod cursor;
9mod delete;
10mod domain;
11mod drop;
12mod expressions;
13mod grant;
14mod helpers;
15mod index;
16mod insert;
17mod introspection;
18mod prepared;
19mod revoke;
20mod role;
21mod schema;
22mod select;
23mod table_options;
24mod transaction;
25mod trigger;
26mod truncate;
27mod update;
28mod view;
29
30#[derive(Debug, Clone, PartialEq)]
32pub struct ParseError {
33 pub message: String,
34}
35
36impl fmt::Display for ParseError {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(f, "Parse error: {}", self.message)
39 }
40}
41
42pub struct Parser {
44 tokens: Vec<Token>,
45 position: usize,
46 placeholder_count: usize,
49}
50
51impl Parser {
52 pub fn new(tokens: Vec<Token>) -> Self {
54 Parser { tokens, position: 0, placeholder_count: 0 }
55 }
56
57 pub fn parse_comma_separated_list<T, F>(&mut self, parse_item: F) -> Result<Vec<T>, ParseError>
79 where
80 F: Fn(&mut Self) -> Result<T, ParseError>,
81 {
82 let mut items = Vec::new();
83
84 items.push(parse_item(self)?);
86
87 while matches!(self.peek(), Token::Comma) {
89 self.advance(); items.push(parse_item(self)?);
91 }
92
93 Ok(items)
94 }
95
96 pub fn parse_sql(input: &str) -> Result<vibesql_ast::Statement, ParseError> {
98 let mut lexer = Lexer::new(input);
99 let tokens =
100 lexer.tokenize().map_err(|e| ParseError { message: format!("Lexer error: {}", e) })?;
101
102 let mut parser = Parser::new(tokens);
103 parser.parse_statement()
104 }
105
106 pub fn parse_statement(&mut self) -> Result<vibesql_ast::Statement, ParseError> {
108 match self.peek() {
109 Token::Keyword(Keyword::Select) | Token::Keyword(Keyword::With) => {
110 let select_stmt = self.parse_select_statement()?;
111 Ok(vibesql_ast::Statement::Select(Box::new(select_stmt)))
112 }
113 Token::Keyword(Keyword::Insert) => {
114 let insert_stmt = self.parse_insert_statement()?;
115 Ok(vibesql_ast::Statement::Insert(insert_stmt))
116 }
117 Token::Keyword(Keyword::Replace) => {
118 let insert_stmt = self.parse_replace_statement()?;
119 Ok(vibesql_ast::Statement::Insert(insert_stmt))
120 }
121 Token::Keyword(Keyword::Update) => {
122 let update_stmt = self.parse_update_statement()?;
123 Ok(vibesql_ast::Statement::Update(update_stmt))
124 }
125 Token::Keyword(Keyword::Delete) => {
126 let delete_stmt = self.parse_delete_statement()?;
127 Ok(vibesql_ast::Statement::Delete(delete_stmt))
128 }
129 Token::Keyword(Keyword::Create) => {
130 if self.peek_next_keyword(Keyword::Or)
132 && matches!(self.peek_at_offset(2), Token::Keyword(Keyword::Replace))
133 {
134 if matches!(self.peek_at_offset(3), Token::Keyword(Keyword::View))
136 || matches!(self.peek_at_offset(3), Token::Keyword(Keyword::Temp))
137 || matches!(self.peek_at_offset(3), Token::Keyword(Keyword::Temporary))
138 {
139 return Ok(vibesql_ast::Statement::CreateView(
140 self.parse_create_view_statement()?,
141 ));
142 }
143 }
144 if self.peek_next_keyword(Keyword::Table) {
145 Ok(vibesql_ast::Statement::CreateTable(self.parse_create_table_statement()?))
146 } else if self.peek_next_keyword(Keyword::Schema) {
147 Ok(vibesql_ast::Statement::CreateSchema(self.parse_create_schema_statement()?))
148 } else if self.peek_next_keyword(Keyword::Role) {
149 Ok(vibesql_ast::Statement::CreateRole(self.parse_create_role_statement()?))
150 } else if self.peek_next_keyword(Keyword::Domain) {
151 Ok(vibesql_ast::Statement::CreateDomain(self.parse_create_domain_statement()?))
152 } else if self.peek_next_keyword(Keyword::Sequence) {
153 Ok(vibesql_ast::Statement::CreateSequence(
154 self.parse_create_sequence_statement()?,
155 ))
156 } else if self.peek_next_keyword(Keyword::Type) {
157 Ok(vibesql_ast::Statement::CreateType(self.parse_create_type_statement()?))
158 } else if self.peek_next_keyword(Keyword::Collation) {
159 Ok(vibesql_ast::Statement::CreateCollation(
160 self.parse_create_collation_statement()?,
161 ))
162 } else if self.peek_next_keyword(Keyword::Character) {
163 Ok(vibesql_ast::Statement::CreateCharacterSet(
164 self.parse_create_character_set_statement()?,
165 ))
166 } else if self.peek_next_keyword(Keyword::Translation) {
167 Ok(vibesql_ast::Statement::CreateTranslation(
168 self.parse_create_translation_statement()?,
169 ))
170 } else if self.peek_next_keyword(Keyword::View) {
171 Ok(vibesql_ast::Statement::CreateView(self.parse_create_view_statement()?))
172 } else if self.peek_next_keyword(Keyword::Temp)
173 || self.peek_next_keyword(Keyword::Temporary)
174 {
175 Ok(vibesql_ast::Statement::CreateView(self.parse_create_view_statement()?))
177 } else if self.peek_next_keyword(Keyword::Trigger) {
178 Ok(vibesql_ast::Statement::CreateTrigger(
179 self.parse_create_trigger_statement()?,
180 ))
181 } else if self.peek_next_keyword(Keyword::Index)
182 || self.peek_next_keyword(Keyword::Unique)
183 || self.peek_next_keyword(Keyword::Fulltext)
184 || self.peek_next_keyword(Keyword::Spatial)
185 {
186 Ok(vibesql_ast::Statement::CreateIndex(self.parse_create_index_statement()?))
187 } else if self.peek_next_keyword(Keyword::Assertion) {
188 Ok(vibesql_ast::Statement::CreateAssertion(
189 self.parse_create_assertion_statement()?,
190 ))
191 } else if self.peek_next_keyword(Keyword::Procedure) {
192 Ok(vibesql_ast::Statement::CreateProcedure(
193 self.parse_create_procedure_statement()?,
194 ))
195 } else if self.peek_next_keyword(Keyword::Function) {
196 Ok(vibesql_ast::Statement::CreateFunction(
197 self.parse_create_function_statement()?,
198 ))
199 } else {
200 Err(ParseError {
201 message:
202 "Expected TABLE, SCHEMA, ROLE, DOMAIN, SEQUENCE, TYPE, COLLATION, CHARACTER, TRANSLATION, VIEW, TRIGGER, INDEX, ASSERTION, PROCEDURE, or FUNCTION after CREATE"
203 .to_string(),
204 })
205 }
206 }
207 Token::Keyword(Keyword::Drop) => {
208 if self.peek_next_keyword(Keyword::Table) {
209 Ok(vibesql_ast::Statement::DropTable(self.parse_drop_table_statement()?))
210 } else if self.peek_next_keyword(Keyword::Schema) {
211 Ok(vibesql_ast::Statement::DropSchema(self.parse_drop_schema_statement()?))
212 } else if self.peek_next_keyword(Keyword::Role) {
213 Ok(vibesql_ast::Statement::DropRole(self.parse_drop_role_statement()?))
214 } else if self.peek_next_keyword(Keyword::Domain) {
215 Ok(vibesql_ast::Statement::DropDomain(self.parse_drop_domain_statement()?))
216 } else if self.peek_next_keyword(Keyword::Sequence) {
217 Ok(vibesql_ast::Statement::DropSequence(self.parse_drop_sequence_statement()?))
218 } else if self.peek_next_keyword(Keyword::Type) {
219 Ok(vibesql_ast::Statement::DropType(self.parse_drop_type_statement()?))
220 } else if self.peek_next_keyword(Keyword::Collation) {
221 Ok(vibesql_ast::Statement::DropCollation(
222 self.parse_drop_collation_statement()?,
223 ))
224 } else if self.peek_next_keyword(Keyword::Character) {
225 Ok(vibesql_ast::Statement::DropCharacterSet(
226 self.parse_drop_character_set_statement()?,
227 ))
228 } else if self.peek_next_keyword(Keyword::Translation) {
229 Ok(vibesql_ast::Statement::DropTranslation(
230 self.parse_drop_translation_statement()?,
231 ))
232 } else if self.peek_next_keyword(Keyword::View) {
233 Ok(vibesql_ast::Statement::DropView(self.parse_drop_view_statement()?))
234 } else if self.peek_next_keyword(Keyword::Trigger) {
235 Ok(vibesql_ast::Statement::DropTrigger(self.parse_drop_trigger_statement()?))
236 } else if self.peek_next_keyword(Keyword::Index) {
237 Ok(vibesql_ast::Statement::DropIndex(self.parse_drop_index_statement()?))
238 } else if self.peek_next_keyword(Keyword::Assertion) {
239 Ok(vibesql_ast::Statement::DropAssertion(
240 self.parse_drop_assertion_statement()?,
241 ))
242 } else if self.peek_next_keyword(Keyword::Procedure) {
243 Ok(vibesql_ast::Statement::DropProcedure(
244 self.parse_drop_procedure_statement()?,
245 ))
246 } else if self.peek_next_keyword(Keyword::Function) {
247 Ok(vibesql_ast::Statement::DropFunction(self.parse_drop_function_statement()?))
248 } else {
249 Err(ParseError {
250 message:
251 "Expected TABLE, SCHEMA, ROLE, DOMAIN, SEQUENCE, TYPE, COLLATION, CHARACTER, TRANSLATION, VIEW, TRIGGER, INDEX, ASSERTION, PROCEDURE, or FUNCTION after DROP"
252 .to_string(),
253 })
254 }
255 }
256 Token::Keyword(Keyword::Truncate) => {
257 let truncate_stmt = self.parse_truncate_table_statement()?;
258 Ok(vibesql_ast::Statement::TruncateTable(truncate_stmt))
259 }
260 Token::Keyword(Keyword::Alter) => {
261 if self.peek_next_keyword(Keyword::Table) {
262 let alter_stmt = self.parse_alter_table_statement()?;
263 Ok(vibesql_ast::Statement::AlterTable(alter_stmt))
264 } else if self.peek_next_keyword(Keyword::Sequence) {
265 let alter_stmt = self.parse_alter_sequence_statement()?;
266 Ok(vibesql_ast::Statement::AlterSequence(alter_stmt))
267 } else if self.peek_next_keyword(Keyword::Trigger) {
268 let alter_stmt = self.parse_alter_trigger_statement()?;
269 Ok(vibesql_ast::Statement::AlterTrigger(alter_stmt))
270 } else {
271 Err(ParseError {
272 message: "Expected TABLE, SEQUENCE, or TRIGGER after ALTER".to_string(),
273 })
274 }
275 }
276 Token::Keyword(Keyword::Reindex) => {
277 let reindex_stmt = self.parse_reindex_statement()?;
278 Ok(vibesql_ast::Statement::Reindex(reindex_stmt))
279 }
280 Token::Keyword(Keyword::Analyze) => {
281 let analyze_stmt = self.parse_analyze_statement()?;
282 Ok(vibesql_ast::Statement::Analyze(analyze_stmt))
283 }
284 Token::Keyword(Keyword::Explain) => {
285 let explain_stmt = self.parse_explain_statement()?;
286 Ok(vibesql_ast::Statement::Explain(explain_stmt))
287 }
288 Token::Keyword(Keyword::Begin) | Token::Keyword(Keyword::Start) => {
289 let begin_stmt = self.parse_begin_statement()?;
290 Ok(vibesql_ast::Statement::BeginTransaction(begin_stmt))
291 }
292 Token::Keyword(Keyword::Commit) => {
293 let commit_stmt = self.parse_commit_statement()?;
294 Ok(vibesql_ast::Statement::Commit(commit_stmt))
295 }
296 Token::Keyword(Keyword::Rollback) => {
297 let saved_position = self.position;
299 self.advance(); if self.peek_keyword(Keyword::To) {
301 self.position = saved_position;
303 let rollback_to_stmt = self.parse_rollback_to_savepoint_statement()?;
304 Ok(vibesql_ast::Statement::RollbackToSavepoint(rollback_to_stmt))
305 } else {
306 self.position = saved_position;
308 let rollback_stmt = self.parse_rollback_statement()?;
309 Ok(vibesql_ast::Statement::Rollback(rollback_stmt))
310 }
311 }
312 Token::Keyword(Keyword::Savepoint) => {
313 let savepoint_stmt = self.parse_savepoint_statement()?;
314 Ok(vibesql_ast::Statement::Savepoint(savepoint_stmt))
315 }
316 Token::Keyword(Keyword::Release) => {
317 let release_stmt = self.parse_release_savepoint_statement()?;
318 Ok(vibesql_ast::Statement::ReleaseSavepoint(release_stmt))
319 }
320 Token::Keyword(Keyword::Set) => {
321 if self.peek_next_keyword(Keyword::Schema) {
323 let set_stmt = self.parse_set_schema_statement()?;
324 Ok(vibesql_ast::Statement::SetSchema(set_stmt))
325 } else if self.peek_next_keyword(Keyword::Catalog) {
326 let set_stmt = schema::parse_set_catalog(self)?;
327 Ok(vibesql_ast::Statement::SetCatalog(set_stmt))
328 } else if self.peek_next_keyword(Keyword::Names) {
329 let set_stmt = schema::parse_set_names(self)?;
330 Ok(vibesql_ast::Statement::SetNames(set_stmt))
331 } else if self.peek_next_keyword(Keyword::Time) {
332 let set_stmt = schema::parse_set_time_zone(self)?;
333 Ok(vibesql_ast::Statement::SetTimeZone(set_stmt))
334 } else if self.peek_next_keyword(Keyword::Transaction) {
335 let set_stmt = self.parse_set_transaction_statement()?;
336 Ok(vibesql_ast::Statement::SetTransaction(set_stmt))
337 } else if self.peek_next_keyword(Keyword::Local) {
338 let set_stmt = self.parse_set_transaction_statement()?;
340 Ok(vibesql_ast::Statement::SetTransaction(set_stmt))
341 } else {
342 let set_stmt = schema::parse_set_variable(self)?;
344 Ok(vibesql_ast::Statement::SetVariable(set_stmt))
345 }
346 }
347 Token::Keyword(Keyword::Grant) => {
348 let grant_stmt = self.parse_grant_statement()?;
349 Ok(vibesql_ast::Statement::Grant(grant_stmt))
350 }
351 Token::Keyword(Keyword::Revoke) => {
352 let revoke_stmt = self.parse_revoke_statement()?;
353 Ok(vibesql_ast::Statement::Revoke(revoke_stmt))
354 }
355 Token::Keyword(Keyword::Declare) => {
356 let declare_cursor_stmt = self.parse_declare_cursor_statement()?;
357 Ok(vibesql_ast::Statement::DeclareCursor(declare_cursor_stmt))
358 }
359 Token::Keyword(Keyword::Open) => {
360 let open_cursor_stmt = self.parse_open_cursor_statement()?;
361 Ok(vibesql_ast::Statement::OpenCursor(open_cursor_stmt))
362 }
363 Token::Keyword(Keyword::Fetch) => {
364 let fetch_stmt = self.parse_fetch_statement()?;
365 Ok(vibesql_ast::Statement::Fetch(fetch_stmt))
366 }
367 Token::Keyword(Keyword::Close) => {
368 let close_cursor_stmt = self.parse_close_cursor_statement()?;
369 Ok(vibesql_ast::Statement::CloseCursor(close_cursor_stmt))
370 }
371 Token::Keyword(Keyword::Call) => {
372 let call_stmt = self.parse_call_statement()?;
373 Ok(vibesql_ast::Statement::Call(call_stmt))
374 }
375 Token::Keyword(Keyword::Show) => self.parse_show_statement(),
376 Token::Keyword(Keyword::Describe) => {
377 let describe_stmt = self.parse_describe_statement()?;
378 Ok(vibesql_ast::Statement::Describe(describe_stmt))
379 }
380 Token::Keyword(Keyword::Prepare) => {
381 let prepare_stmt = self.parse_prepare_statement()?;
382 Ok(vibesql_ast::Statement::Prepare(prepare_stmt))
383 }
384 Token::Keyword(Keyword::Execute) => {
385 let execute_stmt = self.parse_execute_statement()?;
386 Ok(vibesql_ast::Statement::Execute(execute_stmt))
387 }
388 Token::Keyword(Keyword::Deallocate) => {
389 let deallocate_stmt = self.parse_deallocate_statement()?;
390 Ok(vibesql_ast::Statement::Deallocate(deallocate_stmt))
391 }
392 _ => {
393 Err(ParseError { message: format!("Expected statement, found {:?}", self.peek()) })
394 }
395 }
396 }
397
398 pub fn parse_begin_statement(&mut self) -> Result<vibesql_ast::BeginStmt, ParseError> {
400 transaction::parse_begin_statement(self)
401 }
402
403 pub fn parse_commit_statement(&mut self) -> Result<vibesql_ast::CommitStmt, ParseError> {
405 transaction::parse_commit_statement(self)
406 }
407
408 pub fn parse_rollback_statement(&mut self) -> Result<vibesql_ast::RollbackStmt, ParseError> {
410 transaction::parse_rollback_statement(self)
411 }
412
413 pub fn parse_alter_table_statement(
415 &mut self,
416 ) -> Result<vibesql_ast::AlterTableStmt, ParseError> {
417 alter::parse_alter_table(self)
418 }
419
420 pub fn parse_savepoint_statement(&mut self) -> Result<vibesql_ast::SavepointStmt, ParseError> {
422 transaction::parse_savepoint_statement(self)
423 }
424
425 pub fn parse_rollback_to_savepoint_statement(
427 &mut self,
428 ) -> Result<vibesql_ast::RollbackToSavepointStmt, ParseError> {
429 transaction::parse_rollback_to_savepoint_statement(self)
430 }
431
432 pub fn parse_release_savepoint_statement(
434 &mut self,
435 ) -> Result<vibesql_ast::ReleaseSavepointStmt, ParseError> {
436 transaction::parse_release_savepoint_statement(self)
437 }
438
439 pub fn parse_create_schema_statement(
441 &mut self,
442 ) -> Result<vibesql_ast::CreateSchemaStmt, ParseError> {
443 schema::parse_create_schema(self)
444 }
445
446 pub fn parse_drop_schema_statement(
448 &mut self,
449 ) -> Result<vibesql_ast::DropSchemaStmt, ParseError> {
450 schema::parse_drop_schema(self)
451 }
452
453 pub fn parse_set_schema_statement(&mut self) -> Result<vibesql_ast::SetSchemaStmt, ParseError> {
455 schema::parse_set_schema(self)
456 }
457
458 pub fn parse_grant_statement(&mut self) -> Result<vibesql_ast::GrantStmt, ParseError> {
460 grant::parse_grant(self)
461 }
462
463 pub fn parse_revoke_statement(&mut self) -> Result<vibesql_ast::RevokeStmt, ParseError> {
465 revoke::parse_revoke(self)
466 }
467
468 pub fn parse_create_role_statement(
470 &mut self,
471 ) -> Result<vibesql_ast::CreateRoleStmt, ParseError> {
472 role::parse_create_role(self)
473 }
474
475 pub fn parse_drop_role_statement(&mut self) -> Result<vibesql_ast::DropRoleStmt, ParseError> {
477 role::parse_drop_role(self)
478 }
479
480 pub fn parse_create_domain_statement(
486 &mut self,
487 ) -> Result<vibesql_ast::CreateDomainStmt, ParseError> {
488 domain::parse_create_domain(self)
489 }
490
491 pub fn parse_drop_domain_statement(
493 &mut self,
494 ) -> Result<vibesql_ast::DropDomainStmt, ParseError> {
495 domain::parse_drop_domain(self)
496 }
497
498 pub fn parse_create_sequence_statement(
500 &mut self,
501 ) -> Result<vibesql_ast::CreateSequenceStmt, ParseError> {
502 advanced_objects::parse_create_sequence(self)
503 }
504
505 pub fn parse_drop_sequence_statement(
507 &mut self,
508 ) -> Result<vibesql_ast::DropSequenceStmt, ParseError> {
509 advanced_objects::parse_drop_sequence(self)
510 }
511
512 pub fn parse_alter_sequence_statement(
514 &mut self,
515 ) -> Result<vibesql_ast::AlterSequenceStmt, ParseError> {
516 advanced_objects::parse_alter_sequence(self)
517 }
518
519 pub fn parse_create_type_statement(
521 &mut self,
522 ) -> Result<vibesql_ast::CreateTypeStmt, ParseError> {
523 advanced_objects::parse_create_type(self)
524 }
525
526 pub fn parse_set_transaction_statement(
528 &mut self,
529 ) -> Result<vibesql_ast::SetTransactionStmt, ParseError> {
530 self.expect_keyword(Keyword::Set)?;
532
533 let local = self.try_consume_keyword(Keyword::Local);
535
536 self.expect_keyword(Keyword::Transaction)?;
538
539 let mut isolation_level = None;
541 let mut access_mode = None;
542
543 loop {
544 if self.try_consume_keyword(Keyword::Serializable) {
545 isolation_level = Some(vibesql_ast::IsolationLevel::Serializable);
546 } else if self.try_consume_keyword(Keyword::Read) {
547 if self.try_consume_keyword(Keyword::Only) {
548 access_mode = Some(vibesql_ast::TransactionAccessMode::ReadOnly);
549 } else if self.try_consume_keyword(Keyword::Write) {
550 access_mode = Some(vibesql_ast::TransactionAccessMode::ReadWrite);
551 } else {
552 return Err(ParseError {
553 message: "Expected ONLY or WRITE after READ".to_string(),
554 });
555 }
556 } else if self.try_consume_keyword(Keyword::Isolation) {
557 self.expect_keyword(Keyword::Level)?;
558 if self.try_consume_keyword(Keyword::Serializable) {
559 isolation_level = Some(vibesql_ast::IsolationLevel::Serializable);
560 } else {
561 return Err(ParseError {
562 message: "Expected SERIALIZABLE after ISOLATION LEVEL".to_string(),
563 });
564 }
565 } else {
566 break;
567 }
568
569 if !self.try_consume(&Token::Comma) {
571 break;
572 }
573 }
574
575 Ok(vibesql_ast::SetTransactionStmt { local, isolation_level, access_mode })
576 }
577
578 pub fn parse_drop_type_statement(&mut self) -> Result<vibesql_ast::DropTypeStmt, ParseError> {
580 advanced_objects::parse_drop_type(self)
581 }
582
583 pub fn parse_create_collation_statement(
585 &mut self,
586 ) -> Result<vibesql_ast::CreateCollationStmt, ParseError> {
587 advanced_objects::parse_create_collation(self)
588 }
589
590 pub fn parse_drop_collation_statement(
592 &mut self,
593 ) -> Result<vibesql_ast::DropCollationStmt, ParseError> {
594 advanced_objects::parse_drop_collation(self)
595 }
596
597 pub fn parse_create_character_set_statement(
599 &mut self,
600 ) -> Result<vibesql_ast::CreateCharacterSetStmt, ParseError> {
601 advanced_objects::parse_create_character_set(self)
602 }
603
604 pub fn parse_drop_character_set_statement(
606 &mut self,
607 ) -> Result<vibesql_ast::DropCharacterSetStmt, ParseError> {
608 advanced_objects::parse_drop_character_set(self)
609 }
610
611 pub fn parse_create_translation_statement(
613 &mut self,
614 ) -> Result<vibesql_ast::CreateTranslationStmt, ParseError> {
615 advanced_objects::parse_create_translation(self)
616 }
617
618 pub fn parse_drop_translation_statement(
620 &mut self,
621 ) -> Result<vibesql_ast::DropTranslationStmt, ParseError> {
622 advanced_objects::parse_drop_translation(self)
623 }
624
625 pub fn parse_create_assertion_statement(
627 &mut self,
628 ) -> Result<vibesql_ast::CreateAssertionStmt, ParseError> {
629 advanced_objects::parse_create_assertion(self)
630 }
631
632 pub fn parse_drop_assertion_statement(
634 &mut self,
635 ) -> Result<vibesql_ast::DropAssertionStmt, ParseError> {
636 advanced_objects::parse_drop_assertion(self)
637 }
638
639 pub fn parse_create_procedure_statement(
641 &mut self,
642 ) -> Result<vibesql_ast::CreateProcedureStmt, ParseError> {
643 self.advance(); self.advance(); self.parse_create_procedure()
646 }
647
648 pub fn parse_drop_procedure_statement(
650 &mut self,
651 ) -> Result<vibesql_ast::DropProcedureStmt, ParseError> {
652 self.advance(); self.advance(); self.parse_drop_procedure()
655 }
656
657 pub fn parse_create_function_statement(
659 &mut self,
660 ) -> Result<vibesql_ast::CreateFunctionStmt, ParseError> {
661 self.advance(); self.advance(); self.parse_create_function()
664 }
665
666 pub fn parse_drop_function_statement(
668 &mut self,
669 ) -> Result<vibesql_ast::DropFunctionStmt, ParseError> {
670 self.advance(); self.advance(); self.parse_drop_function()
673 }
674
675 pub fn parse_call_statement(&mut self) -> Result<vibesql_ast::CallStmt, ParseError> {
677 self.advance(); self.parse_call()
679 }
680}