mod alter_table;
mod common;
mod create_table;
mod datatypes;
mod helpers;
mod statements;
mod stream;
use serde_json::{json, Value};
use crate::lexer::{tokenize, Token};
use stream::Stream;
#[derive(Debug, Clone)]
pub struct ParseError {
pub line: usize,
}
pub fn parse_statement(input: &str) -> Result<Value, ParseError> {
let tokens = tokenize(input).map_err(|e| ParseError { line: e.line })?;
let mut s = Stream::new(&tokens);
s.ws0();
let inner = match dispatch(&mut s) {
Some(v) => v,
None => {
return Err(ParseError {
line: line_at(&tokens, s.furthest()),
})
}
};
s.ws0();
if !s.at_end() {
return Err(ParseError {
line: line_at(&tokens, s.furthest()),
});
}
Ok(json!({ "id": "P_DDS", "def": inner }))
}
fn dispatch(s: &mut Stream) -> Option<Value> {
let rules: &[fn(&mut Stream) -> Option<Value>] = &[
statements::p_create_db,
create_table::p_create_table,
statements::p_create_index,
statements::p_alter_db,
alter_table::p_alter_table,
statements::p_drop_db,
statements::p_drop_table,
statements::p_drop_index,
statements::p_rename_table,
statements::p_set,
statements::p_use_db,
];
for rule in rules {
let save = s.pos();
if let Some(v) = rule(s) {
return Some(v);
}
s.set(save);
}
None
}
fn line_at(tokens: &[Token], pos: usize) -> usize {
let mut line = 1;
for t in tokens.iter().take(pos) {
line += t.value.matches('\n').count();
}
line
}