pub mod lexer;
use std::iter::Peekable;
use anyhow::{Context, Result};
use create_table::CreateTableError;
use lexer::{Lexer, LexerError, Spanned, Token};
use thiserror::Error;
use crate::ast::{Column, Expr, Statement};
mod create_table;
mod delete;
mod expr;
mod insert;
mod primitive;
mod select;
mod update;
pub struct Parser<'a> {
lexer: Peekable<Lexer<'a>>,
}
#[derive(Debug, Error)]
pub enum ParserError {
#[error("unexpected token {0:?}")]
Unexpected(Token),
#[error("unexpected keyword {0}")]
UnexpectedKeyword(String),
#[error("unexpected end of input")]
UnexpectedEOF,
#[error("unexpected end of edge")]
UnexpectedEndOfEdge,
#[error("edge must have at least one expression in its list")]
EdgeNoExpressions,
#[error("lexer error: {0:?}")]
LexerError(Spanned<LexerError>),
#[error("create table error: {0}")]
CreateTable(CreateTableError),
}
impl<'a> Parser<'a> {
pub fn make_parse_list<T, F: Fn(&mut Self) -> Result<T, ParserError>>(
&mut self,
f: F,
) -> Result<Vec<T>, ParserError> {
let mut list = Vec::new();
if let Ok(m) = f(self) {
list.push(m);
loop {
if self.peek().map(|t| t == Token::Comma).unwrap_or_default() {
let _ = self.lexer.next().unwrap();
} else {
break;
}
list.push(f(self)?)
}
}
Ok(list)
}
pub fn new(lexer: Lexer<'a>) -> Parser<'a> {
Parser {
lexer: lexer.peekable(),
}
}
fn parse_statement(&mut self) -> Result<Statement, ParserError> {
match self.peek_symbol()?.as_str() {
"CREATE" => Ok(Statement::CreateTable(self.parse_create_table_statement()?)),
"DROP" => {
self.try_consume_keyword("DROP")?;
self.try_consume_keyword("TABLE")?;
let table = self.try_consume_symbol()?;
self.try_consume_semi()?;
Ok(Statement::DropTable(table))
}
"SELECT" => self.parse_select_statement(),
"DELETE" => self.parse_delete_statement(),
"UPDATE" => self.parse_update_statement(),
"INSERT" => self.parse_insert_statement(),
token => Err(ParserError::UnexpectedKeyword(token.to_string())),
}
}
fn parse_statement_or_eof(&mut self) -> Result<Option<Statement>, ParserError> {
if self.lexer.peek().is_some() {
Ok(Some(self.parse_statement()?))
} else {
Ok(None)
}
}
pub fn parse_program(&mut self) -> Result<Vec<Statement>> {
let mut program = Vec::new();
while let Some(st) = self
.parse_statement_or_eof()
.context("failed parsing input")?
{
program.push(st);
}
Ok(program)
}
}
fn rename_default_table(e: &Expr, default_table: &str) -> Expr {
match e {
Expr::Binding(_) => e.clone(),
Expr::Literal(_) => e.clone(),
Expr::Unary(bin_op, rhs) => {
Expr::Unary(*bin_op, Box::new(rename_default_table(&rhs, default_table)))
}
Expr::Bin(lhs, bin_op, rhs) => Expr::Bin(
Box::new(rename_default_table(&lhs, default_table)),
*bin_op,
Box::new(rename_default_table(&rhs, default_table)),
),
Expr::Column(Column(fake_table, column)) => Expr::Column(Column(
if fake_table == "" {
default_table.to_string()
} else {
fake_table.to_string()
},
column.to_string(),
)),
Expr::Edge(lhs, mapping, rhs, e) => Expr::Edge(
lhs.iter()
.map(|e| rename_default_table(e, default_table))
.collect(),
mapping.clone(),
rhs.as_ref().map(|rhs| {
rhs.iter()
.map(|e| rename_default_table(e, default_table))
.collect()
}),
Box::new(rename_default_table(e, default_table)),
),
}
}