use crate::ast::{SelectStatement, Statement};
use super::{lexer::Token, rename_default_table, Parser, ParserError};
impl<'a> Parser<'a> {
pub fn try_consume_int(&mut self) -> Result<u64, ParserError> {
match self.peek()? {
Token::Int(i) => {
let _ = self.lexer.next().unwrap();
Ok(i.parse().unwrap())
}
token => Err(ParserError::Unexpected(token)),
}
}
pub fn try_consume_mapping(&mut self) -> Result<(String, String), ParserError> {
let table = self.try_consume_symbol()?;
Ok((
if let Ok(()) = self.try_consume_keyword("AS") {
self.try_consume_symbol()?.to_string()
} else {
table.to_string()
},
table.to_string(),
))
}
fn parse_table_list(&mut self) -> Result<Vec<(String, String)>, ParserError> {
self.make_parse_list(Self::try_consume_mapping)
}
pub(crate) fn parse_select_statement(&mut self) -> Result<Statement, ParserError> {
let explain = self.try_consume_keyword("EXPLAIN").is_ok();
self.try_consume_keyword("SELECT")?;
let exprs = self.parse_expr_list()?;
self.try_consume_keyword("FROM")?;
let table_mappings = self.parse_table_list()?;
let cond = if let Ok(_) = self.try_consume_keyword("WHERE") {
Some(rename_default_table(
&self.parse_expr()?,
&table_mappings[0].0,
))
} else {
None
};
let version = if let Ok(_) = self.try_consume_keyword("VERSION") {
Some(self.try_consume_int()?)
} else {
None
};
self.try_consume_semi()?;
Ok(Statement::Select(SelectStatement {
explain,
expr: exprs
.into_iter()
.map(|e| rename_default_table(&e, &table_mappings[0].0))
.collect(),
cond,
table_mappings,
version,
}))
}
}