libsql_sqlite3_parser/parser/
mod.rs

1//! SQLite parser
2use log::error;
3
4pub mod ast;
5pub mod parse {
6    #![allow(unused_braces)]
7    #![allow(unused_comparisons)] // FIXME
8    #![allow(clippy::collapsible_if)]
9    #![allow(clippy::if_same_then_else)]
10    #![allow(clippy::absurd_extreme_comparisons)] // FIXME
11    #![allow(clippy::needless_return)]
12    #![allow(clippy::upper_case_acronyms)]
13    #![allow(clippy::manual_range_patterns)]
14    #![allow(unexpected_cfgs)]
15    include!(concat!(env!("OUT_DIR"), "/parse.rs"));
16}
17
18use crate::dialect::Token;
19use ast::{Cmd, ExplainKind, Name, Stmt};
20
21/// Parser error
22#[derive(Debug)]
23pub enum ParserError {
24    StackOverflow,
25    SyntaxError {
26        token_type: &'static str,
27        found: Option<String>,
28    },
29    UnexpectedEof,
30    Custom(String),
31}
32
33impl std::fmt::Display for ParserError {
34    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35        match self {
36            ParserError::StackOverflow => f.write_str("parser overflowed its stack"),
37            ParserError::SyntaxError { token_type, found } => {
38                write!(f, "near {}, \"{:?}\": syntax error", token_type, found)
39            }
40            ParserError::UnexpectedEof => f.write_str("unexpected end of input"),
41            ParserError::Custom(s) => f.write_str(s),
42        }
43    }
44}
45
46impl std::error::Error for ParserError {}
47
48/// Parser context
49pub struct Context<'input> {
50    input: &'input [u8],
51    explain: Option<ExplainKind>,
52    stmt: Option<Stmt>,
53    constraint_name: Option<Name>,      // transient
54    module_arg: Option<(usize, usize)>, // Complete text of a module argument
55    module_args: Option<Vec<String>>,   // CREATE VIRTUAL TABLE args
56    done: bool,
57    error: Option<ParserError>,
58}
59
60impl<'input> Context<'input> {
61    pub fn new(input: &'input [u8]) -> Context<'input> {
62        Context {
63            input,
64            explain: None,
65            stmt: None,
66            constraint_name: None,
67            module_arg: None,
68            module_args: None,
69            done: false,
70            error: None,
71        }
72    }
73
74    /// Consume parsed command
75    pub fn cmd(&mut self) -> Option<Cmd> {
76        if let Some(stmt) = self.stmt.take() {
77            match self.explain.take() {
78                Some(ExplainKind::Explain) => Some(Cmd::Explain(stmt)),
79                Some(ExplainKind::QueryPlan) => Some(Cmd::ExplainQueryPlan(stmt)),
80                None => Some(Cmd::Stmt(stmt)),
81            }
82        } else {
83            None
84        }
85    }
86
87    fn constraint_name(&mut self) -> Option<Name> {
88        self.constraint_name.take()
89    }
90    fn no_constraint_name(&self) -> bool {
91        self.constraint_name.is_none()
92    }
93
94    fn vtab_arg_init(&mut self) {
95        self.add_module_arg();
96        self.module_arg = None;
97    }
98    fn vtab_arg_extend(&mut self, any: Token) {
99        if let Some((_, ref mut n)) = self.module_arg {
100            *n = any.2
101        } else {
102            self.module_arg = Some((any.0, any.2))
103        }
104    }
105    fn add_module_arg(&mut self) {
106        if let Some((start, end)) = self.module_arg.take() {
107            if let Ok(arg) = std::str::from_utf8(&self.input[start..end]) {
108                self.module_args.get_or_insert(vec![]).push(arg.to_owned());
109            } // FIXME error handling
110        }
111    }
112    fn module_args(&mut self) -> Option<Vec<String>> {
113        self.add_module_arg();
114        self.module_args.take()
115    }
116
117    fn sqlite3_error_msg(&mut self, msg: &str) {
118        error!("parser error: {}", msg);
119    }
120
121    /// This routine is called after a single SQL statement has been parsed.
122    fn sqlite3_finish_coding(&mut self) {
123        self.done = true;
124    }
125
126    /// Return `true` if parser completes either successfully or with an error.
127    pub fn done(&self) -> bool {
128        self.done || self.error.is_some()
129    }
130
131    pub fn is_ok(&self) -> bool {
132        self.error.is_none()
133    }
134
135    /// Consume error generated by parser
136    pub fn error(&mut self) -> Option<ParserError> {
137        self.error.take()
138    }
139
140    pub fn reset(&mut self) {
141        self.explain = None;
142        self.stmt = None;
143        self.constraint_name = None;
144        self.module_arg = None;
145        self.module_args = None;
146        self.done = false;
147        self.error = None;
148    }
149}