diff --git a/examples/acme_parser.rs b/examples/acme_parser.rs index 950e7e19..a6f94a1e 100644 --- a/examples/acme_parser.rs +++ b/examples/acme_parser.rs @@ -32,9 +32,13 @@ struct AcmeTokenizer { } /// The ACME tokenizer looks for the factorial operator `!!` but delegates everything else -impl SQLTokenizer for AcmeTokenizer { +impl SQLTokenizer for AcmeTokenizer { - fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { + fn peek_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { + unimplemented!() + } + + fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { match chars.peek() { Some(&ch) => match ch { '!' => { diff --git a/src/ansi/parser.rs b/src/ansi/parser.rs index adace1f7..e2580519 100644 --- a/src/ansi/parser.rs +++ b/src/ansi/parser.rs @@ -6,18 +6,30 @@ use std::str::Chars; use super::super::tokenizer::*; use super::super::parser::*; -pub struct ANSISQLParser { - +pub struct ANSISQLParser<'a, TokenType> { + chars: Peekable>, + tokenizer: SQLTokenizer } -impl SQLParser for ANSISQLParser - where S: Debug + PartialEq { +impl<'a, TokenType, ExprType> SQLParser for ANSISQLParser<'a, TokenType> + where TokenType: Debug + PartialEq, ExprType: Debug + PartialEq { - fn parse_prefix(&mut self) -> Result>, ParserError> { - unimplemented!() + fn parse_prefix(&mut self) -> Result>, ParserError> { + + match self.tokenizer.peek_token(&mut self.chars)? { + Some(SQLToken::Keyword(ref k)) => match k.to_uppercase().as_ref() { + "INSERT" => unimplemented!(), + "UPDATE" => unimplemented!(), + "DELETE" => unimplemented!(), + "SELECT" => unimplemented!(), + "CREATE" => unimplemented!(), + _ => unimplemented!() + }, + _ => unimplemented!() + } } - fn parse_infix(&mut self, left: SQLExpr) -> Result>>, ParserError> { + fn parse_infix(&mut self, left: SQLExpr) -> Result>>, ParserError> { unimplemented!() } } diff --git a/src/ansi/tokenizer.rs b/src/ansi/tokenizer.rs index 39ed0d9d..81d88eda 100644 --- a/src/ansi/tokenizer.rs +++ b/src/ansi/tokenizer.rs @@ -7,10 +7,14 @@ use super::super::tokenizer::*; pub struct ANSISQLTokenizer {} -impl SQLTokenizer for ANSISQLTokenizer - where S: Debug + PartialEq { +impl SQLTokenizer for ANSISQLTokenizer + where TokenType: Debug + PartialEq { - fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { + fn peek_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { + unimplemented!() + } + + fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError> { match chars.next() { Some(ch) => match ch { ' ' | '\t' | '\n' => Ok(Some(SQLToken::Whitespace(ch))), diff --git a/src/parser.rs b/src/parser.rs index 96c3679d..2c32f01f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -70,48 +70,47 @@ pub enum SQLOperator { /// SQL Expressions #[derive(Debug)] -pub enum SQLExpr { +pub enum SQLExpr { /// Identifier e.g. table name or column name Identifier(String), /// Literal value Literal(String), /// Binary expression e.g. `1 + 2` or `fname LIKE "A%"` - Binary(Box>, SQLOperator, Box>), + Binary(Box>, SQLOperator, Box>), /// Function invocation with function name and list of argument expressions - FunctionCall(String, Vec>), + FunctionCall(String, Vec>), Insert, Update, Delete, Select, CreateTable, /// Custom expression (vendor-specific) - Custom(T) + Custom(ExprType) } #[derive(Debug)] -pub enum ParserError - where S: Debug + PartialEq { - - WrongToken { expected: Vec>, actual: SQLToken, line: usize, col: usize }, - Custom(PE) +pub enum ParserError + where TokenType: Debug + PartialEq { + WrongToken { expected: Vec>, actual: SQLToken, line: usize, col: usize }, + Custom(String) } -impl From> for ParserError - where S: Debug + PartialEq { +impl From> for ParserError + where TokenType: Debug + PartialEq { - fn from(_: TokenizerError) -> Self { + fn from(_: TokenizerError) -> Self { unimplemented!() } } -pub trait SQLParser - where S: Debug + PartialEq { +pub trait SQLParser + where TokenType: Debug + PartialEq, ExprType: Debug + PartialEq { /// parse the prefix and stop once an infix operator is reached - fn parse_prefix(&mut self) -> Result>, ParserError> ; + fn parse_prefix(&mut self) -> Result>, ParserError> ; /// parse the next infix expression, returning None if the precedence has changed - fn parse_infix(&mut self, left: SQLExpr) -> Result>>, ParserError>; + fn parse_infix(&mut self, left: SQLExpr) -> Result>>, ParserError>; } // diff --git a/src/tokenizer.rs b/src/tokenizer.rs index dfb1a39f..067f41b4 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -47,21 +47,24 @@ pub enum SQLToken { Custom(T) } -pub trait SQLTokenizer - where S: Debug + PartialEq { +pub trait SQLTokenizer + where TokenType: Debug + PartialEq { + + /// return a reference to the next token but do not advance the index + fn peek_token(&self, chars: &mut Peekable) -> Result>, TokenizerError>; /// return a reference to the next token and advance the index - fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError>; + fn next_token(&self, chars: &mut Peekable) -> Result>, TokenizerError>; } -pub fn tokenize(sql: &str, tokenizer: &mut SQLTokenizer) -> Result>, TokenizerError> - where S: Debug + PartialEq +pub fn tokenize(sql: &str, tokenizer: &mut SQLTokenizer) -> Result>, TokenizerError> + where TokenType: Debug + PartialEq { let mut peekable = sql.chars().peekable(); - let mut tokens : Vec> = vec![]; + let mut tokens : Vec> = vec![]; loop { match tokenizer.next_token(&mut peekable)? {