1mod condition;
4mod dml;
5mod select;
6#[cfg(test)]
7mod tests;
8
9use wasm_dbms_api::prelude::SqlError;
10
11use crate::ast::Statement;
12use crate::lexer::{Keyword, Position, Spanned, Token, tokenize};
13
14pub(crate) const MAX_CONDITION_TERMS: usize = 256;
21
22const STATEMENT_START: &str =
23 "a statement (SELECT, INSERT, UPDATE, DELETE, BEGIN, COMMIT or ROLLBACK)";
24
25#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct ParsedStatement {
28 pub statement: Statement,
30 pub parameter_count: usize,
32}
33
34pub fn parse(sql: &str) -> Result<ParsedStatement, SqlError> {
59 let mut parser = Parser::new(sql)?;
60 let statement = parser.statement()?;
61 parser.finish()?;
62 Ok(ParsedStatement {
63 statement,
64 parameter_count: parser.parameters,
65 })
66}
67
68struct Parser {
70 tokens: Vec<Spanned>,
72 cursor: usize,
73 parameters: usize,
75 condition_terms: usize,
77}
78
79impl Parser {
80 fn new(sql: &str) -> Result<Self, SqlError> {
81 Ok(Self {
82 tokens: tokenize(sql)?,
83 cursor: 0,
84 parameters: 0,
85 condition_terms: 0,
86 })
87 }
88
89 fn peek_at(&self, offset: usize) -> &Token {
91 let index = (self.cursor + offset).min(self.tokens.len() - 1);
92 &self.tokens[index].token
93 }
94
95 fn peek(&self) -> &Token {
96 self.peek_at(0)
97 }
98
99 fn position(&self) -> Position {
101 self.tokens[self.cursor].position
102 }
103
104 fn advance(&mut self) {
106 if self.cursor < self.tokens.len() - 1 {
107 self.cursor += 1;
108 }
109 }
110
111 fn at_keyword(&self, keyword: Keyword) -> bool {
112 *self.peek() == Token::Keyword(keyword)
113 }
114
115 fn eat(&mut self, token: &Token) -> bool {
117 let found = self.peek() == token;
118 if found {
119 self.advance();
120 }
121 found
122 }
123
124 fn eat_keyword(&mut self, keyword: Keyword) -> bool {
125 self.eat(&Token::Keyword(keyword))
126 }
127
128 fn error(&self, msg: impl Into<String>) -> SqlError {
130 self.position().error(msg)
131 }
132
133 fn unexpected(&self, expected: &str) -> SqlError {
135 self.error(format!(
136 "expected {expected}, found {found}",
137 found = self.peek().describe()
138 ))
139 }
140
141 fn expect(&mut self, token: &Token, expected: &str) -> Result<(), SqlError> {
143 if self.eat(token) {
144 Ok(())
145 } else {
146 Err(self.unexpected(expected))
147 }
148 }
149
150 fn expect_keyword(&mut self, keyword: Keyword) -> Result<(), SqlError> {
151 let expected = format!("`{keyword}`", keyword = keyword.as_str());
152 self.expect(&Token::Keyword(keyword), &expected)
153 }
154
155 fn identifier(&mut self, expected: &str) -> Result<String, SqlError> {
157 match self.peek() {
158 Token::Identifier(name) => {
159 let name = name.clone();
160 self.advance();
161 Ok(name)
162 }
163 Token::Keyword(_) => Err(self.error(format!(
164 "expected {expected}, found {found} (reserved words must be double-quoted to be \
165 used as names)",
166 found = self.peek().describe()
167 ))),
168 _ => Err(self.unexpected(expected)),
169 }
170 }
171
172 fn next_parameter(&mut self) -> usize {
174 let index = self.parameters;
175 self.parameters += 1;
176 index
177 }
178
179 fn statement(&mut self) -> Result<Statement, SqlError> {
180 match self.peek() {
181 Token::Keyword(Keyword::Select) => self
182 .select()
183 .map(|select| Statement::Select(Box::new(select))),
184 Token::Keyword(Keyword::Insert) => self.insert().map(Statement::Insert),
185 Token::Keyword(Keyword::Update) => self.update().map(Statement::Update),
186 Token::Keyword(Keyword::Delete) => self.delete().map(Statement::Delete),
187 Token::Keyword(Keyword::Begin) => Ok(self.transaction(Statement::Begin)),
188 Token::Keyword(Keyword::Commit) => Ok(self.transaction(Statement::Commit)),
189 Token::Keyword(Keyword::Rollback) => Ok(self.transaction(Statement::Rollback)),
190 _ => Err(self.unexpected(STATEMENT_START)),
191 }
192 }
193
194 fn transaction(&mut self, statement: Statement) -> Statement {
196 self.advance();
197 self.eat_keyword(Keyword::Transaction);
198 statement
199 }
200
201 fn finish(&mut self) -> Result<(), SqlError> {
203 let terminated = self.eat(&Token::Semicolon);
204 match self.peek() {
205 Token::Eof => Ok(()),
206 _ if terminated => Err(self.error("multiple statements are not supported")),
207 _ => Err(self.unexpected("end of statement")),
208 }
209 }
210}