Only use parse_expr() when we expect an expression (0/4)

Before this commit there was a single `parse_expr(u8)` method, which
was called both

1) from within the expression parser (to parse subexpression consisting
   of operators with higher priority than the current one), and

2) from the top-down parser both

   a) to parse true expressions (such as an item of the SELECT list or
      the condition after WHERE or after ON), and 
   b) to parse sequences which are not exactly "expressions".


This starts cleaning this up by renaming the `parse_expr(u8)` method to
`parse_subexpr()` and using it only for (1) - i.e. usually providing a
non-zero precedence parameter.

The non-intuitively called `parse()` method is renamed to `parse_expr()`,
which became available and is used for (2a).


While reviewing the existing callers of `parse_expr`, four points to
follow up on were identified (marked "TBD (#)" in the commit):

1) Do not lose parens (e.g. `(1+2)*3`) when roundtripping
   String->AST->String by using SQLNested.
2) Incorrect precedence of the NOT unary
3) `parse_table_factor` accepts any expression where a SELECT subquery
   is expected.
4) parse_delete uses parse_expr() to retrieve a table name

These are dealt with in the commits to follow.
This commit is contained in:
Nickolay Ponomarev 2019-01-29 18:34:34 +03:00
parent 707c58ad57
commit b57c60a78c
4 changed files with 23 additions and 23 deletions

View file

@ -109,12 +109,12 @@ impl Parser {
} }
/// Parse a new expression /// Parse a new expression
pub fn parse(&mut self) -> Result<ASTNode, ParserError> { pub fn parse_expr(&mut self) -> Result<ASTNode, ParserError> {
self.parse_expr(0) self.parse_subexpr(0)
} }
/// Parse tokens until the precedence changes /// Parse tokens until the precedence changes
pub fn parse_expr(&mut self, precedence: u8) -> Result<ASTNode, ParserError> { pub fn parse_subexpr(&mut self, precedence: u8) -> Result<ASTNode, ParserError> {
debug!("parsing expr"); debug!("parsing expr");
let mut expr = self.parse_prefix()?; let mut expr = self.parse_prefix()?;
debug!("prefix: {:?}", expr); debug!("prefix: {:?}", expr);
@ -167,7 +167,7 @@ impl Parser {
"CAST" => self.parse_cast_expression(), "CAST" => self.parse_cast_expression(),
"NOT" => Ok(ASTNode::SQLUnary { "NOT" => Ok(ASTNode::SQLUnary {
operator: SQLOperator::Not, operator: SQLOperator::Not,
expr: Box::new(self.parse_expr(0)?), expr: Box::new(self.parse_subexpr(0)?), // TBD (2)
}), }),
_ => match self.peek_token() { _ => match self.peek_token() {
Some(Token::LParen) => self.parse_function(&w.value), Some(Token::LParen) => self.parse_function(&w.value),
@ -194,7 +194,7 @@ impl Parser {
self.parse_sql_value() self.parse_sql_value()
} }
Token::LParen => { Token::LParen => {
let expr = self.parse(); let expr = self.parse_expr(); // TBD (1)
self.expect_token(&Token::RParen)?; self.expect_token(&Token::RParen)?;
expr expr
} }
@ -230,11 +230,11 @@ impl Parser {
let mut results = vec![]; let mut results = vec![];
let mut else_result = None; let mut else_result = None;
loop { loop {
conditions.push(self.parse_expr(0)?); conditions.push(self.parse_expr()?);
self.expect_keyword("THEN")?; self.expect_keyword("THEN")?;
results.push(self.parse_expr(0)?); results.push(self.parse_expr()?);
if self.parse_keywords(vec!["ELSE"]) { if self.parse_keywords(vec!["ELSE"]) {
else_result = Some(Box::new(self.parse_expr(0)?)); else_result = Some(Box::new(self.parse_expr()?));
if self.parse_keywords(vec!["END"]) { if self.parse_keywords(vec!["END"]) {
break; break;
} else { } else {
@ -261,7 +261,7 @@ impl Parser {
/// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)` /// Parse a SQL CAST function e.g. `CAST(expr AS FLOAT)`
pub fn parse_cast_expression(&mut self) -> Result<ASTNode, ParserError> { pub fn parse_cast_expression(&mut self) -> Result<ASTNode, ParserError> {
self.expect_token(&Token::LParen)?; self.expect_token(&Token::LParen)?;
let expr = self.parse_expr(0)?; let expr = self.parse_expr()?;
self.expect_keyword("AS")?; self.expect_keyword("AS")?;
let data_type = self.parse_data_type()?; let data_type = self.parse_data_type()?;
self.expect_token(&Token::RParen)?; self.expect_token(&Token::RParen)?;
@ -298,7 +298,7 @@ impl Parser {
Ok(ASTNode::SQLBinaryExpr { Ok(ASTNode::SQLBinaryExpr {
left: Box::new(expr), left: Box::new(expr),
op: SQLOperator::NotLike, op: SQLOperator::NotLike,
right: Box::new(self.parse_expr(precedence)?), right: Box::new(self.parse_subexpr(precedence)?),
}) })
} else { } else {
parser_err!("Invalid tokens after NOT") parser_err!("Invalid tokens after NOT")
@ -322,12 +322,12 @@ impl Parser {
| Token::Div => Ok(ASTNode::SQLBinaryExpr { | Token::Div => Ok(ASTNode::SQLBinaryExpr {
left: Box::new(expr), left: Box::new(expr),
op: self.to_sql_operator(&tok)?, op: self.to_sql_operator(&tok)?,
right: Box::new(self.parse_expr(precedence)?), right: Box::new(self.parse_subexpr(precedence)?),
}), }),
_ => parser_err!(format!("No infix parser for token {:?}", tok)), _ => parser_err!(format!("No infix parser for token {:?}", tok)),
}, },
// This is not supposed to happen, because of the precedence check // This is not supposed to happen, because of the precedence check
// in parse_expr. // in parse_subexpr.
None => parser_err!("Unexpected EOF in parse_infix"), None => parser_err!("Unexpected EOF in parse_infix"),
} }
} }
@ -1106,13 +1106,13 @@ impl Parser {
pub fn parse_delete(&mut self) -> Result<SQLStatement, ParserError> { pub fn parse_delete(&mut self) -> Result<SQLStatement, ParserError> {
let relation: Option<Box<ASTNode>> = if self.parse_keyword("FROM") { let relation: Option<Box<ASTNode>> = if self.parse_keyword("FROM") {
Some(Box::new(self.parse_expr(0)?)) Some(Box::new(self.parse_subexpr(0)?)) /* TBD (4) */
} else { } else {
None None
}; };
let selection = if self.parse_keyword("WHERE") { let selection = if self.parse_keyword("WHERE") {
Some(Box::new(self.parse_expr(0)?)) Some(Box::new(self.parse_expr()?))
} else { } else {
None None
}; };
@ -1136,7 +1136,7 @@ impl Parser {
}; };
let selection = if self.parse_keyword("WHERE") { let selection = if self.parse_keyword("WHERE") {
let expr = self.parse_expr(0)?; let expr = self.parse_expr()?;
Some(Box::new(expr)) Some(Box::new(expr))
} else { } else {
None None
@ -1149,7 +1149,7 @@ impl Parser {
}; };
let having = if self.parse_keyword("HAVING") { let having = if self.parse_keyword("HAVING") {
Some(Box::new(self.parse_expr(0)?)) Some(Box::new(self.parse_expr()?))
} else { } else {
None None
}; };
@ -1182,7 +1182,7 @@ impl Parser {
pub fn parse_table_factor(&mut self) -> Result<ASTNode, ParserError> { pub fn parse_table_factor(&mut self) -> Result<ASTNode, ParserError> {
let relation = if self.consume_token(&Token::LParen) { let relation = if self.consume_token(&Token::LParen) {
self.prev_token(); self.prev_token();
self.parse_expr(0)? self.parse_subexpr(0)? /* TBD (3) */
} else { } else {
self.parse_compound_identifier(&Token::Period)? self.parse_compound_identifier(&Token::Period)?
}; };
@ -1197,7 +1197,7 @@ impl Parser {
if natural { if natural {
Ok(JoinConstraint::Natural) Ok(JoinConstraint::Natural)
} else if self.parse_keyword("ON") { } else if self.parse_keyword("ON") {
let constraint = self.parse_expr(0)?; let constraint = self.parse_expr()?;
Ok(JoinConstraint::On(constraint)) Ok(JoinConstraint::On(constraint))
} else if self.parse_keyword("USING") { } else if self.parse_keyword("USING") {
self.expect_token(&Token::LParen)?; self.expect_token(&Token::LParen)?;
@ -1338,7 +1338,7 @@ impl Parser {
pub fn parse_expr_list(&mut self) -> Result<Vec<ASTNode>, ParserError> { pub fn parse_expr_list(&mut self) -> Result<Vec<ASTNode>, ParserError> {
let mut expr_list: Vec<ASTNode> = vec![]; let mut expr_list: Vec<ASTNode> = vec![];
loop { loop {
expr_list.push(self.parse_expr(0)?); expr_list.push(self.parse_expr()?);
if let Some(t) = self.peek_token() { if let Some(t) = self.peek_token() {
if t == Token::Comma { if t == Token::Comma {
self.next_token(); self.next_token();
@ -1357,7 +1357,7 @@ impl Parser {
pub fn parse_order_by_expr_list(&mut self) -> Result<Vec<SQLOrderByExpr>, ParserError> { pub fn parse_order_by_expr_list(&mut self) -> Result<Vec<SQLOrderByExpr>, ParserError> {
let mut expr_list: Vec<SQLOrderByExpr> = vec![]; let mut expr_list: Vec<SQLOrderByExpr> = vec![];
loop { loop {
let expr = self.parse_expr(0)?; let expr = self.parse_expr()?;
let asc = if self.parse_keyword("ASC") { let asc = if self.parse_keyword("ASC") {
Some(true) Some(true)

View file

@ -23,6 +23,6 @@ fn parse_sql_expr(sql: &str) -> ASTNode {
let mut tokenizer = Tokenizer::new(&dialect, &sql); let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let mut parser = Parser::new(tokens); let mut parser = Parser::new(tokens);
let ast = parser.parse().unwrap(); let ast = parser.parse_expr().unwrap();
ast ast
} }

View file

@ -734,6 +734,6 @@ fn parse_sql_expr_with(dialect: &Dialect, sql: &str) -> ASTNode {
let mut tokenizer = Tokenizer::new(dialect, &sql); let mut tokenizer = Tokenizer::new(dialect, &sql);
let tokens = tokenizer.tokenize().unwrap(); let tokens = tokenizer.tokenize().unwrap();
let mut parser = Parser::new(tokens); let mut parser = Parser::new(tokens);
let ast = parser.parse().unwrap(); let ast = parser.parse_expr().unwrap();
ast ast
} }

View file

@ -389,7 +389,7 @@ fn parse_sql_statements(sql: &str) -> Result<Vec<SQLStatement>, ParserError> {
fn parse_sql_expr(sql: &str) -> ASTNode { fn parse_sql_expr(sql: &str) -> ASTNode {
debug!("sql: {}", sql); debug!("sql: {}", sql);
let mut parser = parser(sql); let mut parser = parser(sql);
let ast = parser.parse().unwrap(); let ast = parser.parse_expr().unwrap();
ast ast
} }