Repository: flink
Updated Branches:
  refs/heads/master f150f9877 -> ef1598498


[FLINK-4241] [table] Cryptic expression parser exceptions

This closes #2529.


Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/ef159849
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/ef159849
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/ef159849

Branch: refs/heads/master
Commit: ef15984988e883ced5311b332e5e5d8521c9573f
Parents: f150f98
Author: twalthr <twal...@apache.org>
Authored: Wed Sep 21 17:12:31 2016 +0200
Committer: twalthr <twal...@apache.org>
Committed: Mon Sep 26 19:06:43 2016 +0200

----------------------------------------------------------------------
 docs/dev/table_api.md                           |  2 +-
 .../table/expressions/ExpressionParser.scala    | 56 ++++++++++++--------
 2 files changed, 34 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flink/blob/ef159849/docs/dev/table_api.md
----------------------------------------------------------------------
diff --git a/docs/dev/table_api.md b/docs/dev/table_api.md
index bb083ff..1d03b38 100644
--- a/docs/dev/table_api.md
+++ b/docs/dev/table_api.md
@@ -953,7 +953,7 @@ alias = logic | ( logic , "AS" , fieldReference ) ;
 
 logic = comparison , [ ( "&&" | "||" ) , comparison ] ;
 
-comparison = term , [ ( "=" | "===" | "!=" | "!==" | ">" | ">=" | "<" | "<=" ) 
, term ] ;
+comparison = term , [ ( "=" | "==" | "===" | "!=" | "!==" | ">" | ">=" | "<" | 
"<=" ) , term ] ;
 
 term = product , [ ( "+" | "-" ) , product ] ;
 

http://git-wip-us.apache.org/repos/asf/flink/blob/ef159849/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/ExpressionParser.scala
----------------------------------------------------------------------
diff --git 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/ExpressionParser.scala
 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/ExpressionParser.scala
index ae027e9..4707adf 100644
--- 
a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/ExpressionParser.scala
+++ 
b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/ExpressionParser.scala
@@ -154,9 +154,7 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
   }
 
   lazy val literalExpr: PackratParser[Expression] =
-    numberLiteral |
-      stringLiteralFlink | singleQuoteStringLiteral |
-      boolLiteral | nullLiteral
+    numberLiteral | stringLiteralFlink | singleQuoteStringLiteral | 
boolLiteral | nullLiteral
 
   lazy val fieldReference: PackratParser[NamedExpression] = (STAR | ident) ^^ {
     sym => UnresolvedFieldReference(sym)
@@ -334,7 +332,8 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
 
   // suffix/prefix composite
 
-  lazy val composite: PackratParser[Expression] = suffixed | prefixed | atom
+  lazy val composite: PackratParser[Expression] = suffixed | prefixed | atom |
+    failure("Composite expression expected.")
 
   // unary ops
 
@@ -342,22 +341,25 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
 
   lazy val unaryMinus: PackratParser[Expression] = "-" ~> composite ^^ { e => 
UnaryMinus(e) }
 
-  lazy val unary = composite | unaryNot | unaryMinus
+  lazy val unary = composite | unaryNot | unaryMinus |
+    failure("Unary expression expected.")
 
   // arithmetic
 
   lazy val product = unary * (
     "*" ^^^ { (a:Expression, b:Expression) => Mul(a,b) } |
-      "/" ^^^ { (a:Expression, b:Expression) => Div(a,b) } |
-      "%" ^^^ { (a:Expression, b:Expression) => Mod(a,b) } )
+    "/" ^^^ { (a:Expression, b:Expression) => Div(a,b) } |
+    "%" ^^^ { (a:Expression, b:Expression) => Mod(a,b) } ) |
+    failure("Product expected.")
 
   lazy val term = product * (
     "+" ^^^ { (a:Expression, b:Expression) => Plus(a,b) } |
-     "-" ^^^ { (a:Expression, b:Expression) => Minus(a,b) } )
+    "-" ^^^ { (a:Expression, b:Expression) => Minus(a,b) } ) |
+    failure("Term expected.")
 
   // Comparison
 
-  lazy val equalTo: PackratParser[Expression] = term ~ ("===" | "=") ~ term ^^ 
{
+  lazy val equalTo: PackratParser[Expression] = term ~ ("===" | "==" | "=") ~ 
term ^^ {
     case l ~ _ ~ r => EqualTo(l, r)
   }
 
@@ -382,23 +384,26 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
   }
 
   lazy val comparison: PackratParser[Expression] =
-      equalTo | notEqualTo |
-      greaterThan | greaterThanOrEqual |
-      lessThan | lessThanOrEqual | term
+    equalTo | notEqualTo |
+    greaterThan | greaterThanOrEqual |
+    lessThan | lessThanOrEqual | term |
+    failure("Comparison expected.")
 
   // logic
 
   lazy val logic = comparison * (
     "&&" ^^^ { (a:Expression, b:Expression) => And(a,b) } |
-      "||" ^^^ { (a:Expression, b:Expression) => Or(a,b) } )
+    "||" ^^^ { (a:Expression, b:Expression) => Or(a,b) } ) |
+    failure("Logic expected.")
 
   // alias
 
   lazy val alias: PackratParser[Expression] = logic ~ AS ~ fieldReference ^^ {
-    case e ~ _ ~ name => Alias(e, name.name)
-  } | logic
+      case e ~ _ ~ name => Alias(e, name.name)
+    } | logic
 
-  lazy val expression: PackratParser[Expression] = alias
+  lazy val expression: PackratParser[Expression] = alias |
+    failure("Invalid expression.")
 
   lazy val expressionList: Parser[List[Expression]] = rep1sep(expression, ",")
 
@@ -406,11 +411,8 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
     parseAll(expressionList, expression) match {
       case Success(lst, _) => lst
 
-      case Failure(msg, _) => throw ExpressionParserException(
-        "Could not parse expression: " + msg)
-
-      case Error(msg, _) => throw ExpressionParserException(
-        "Could not parse expression: " + msg)
+      case NoSuccess(msg, next) =>
+        throwError(msg, next)
     }
   }
 
@@ -418,8 +420,16 @@ object ExpressionParser extends JavaTokenParsers with 
PackratParsers {
     parseAll(expression, exprString) match {
       case Success(lst, _) => lst
 
-      case fail =>
-        throw ExpressionParserException("Could not parse expression: " + 
fail.toString)
+      case NoSuccess(msg, next) =>
+        throwError(msg, next)
     }
   }
+
+  private def throwError(msg: String, next: Input): Nothing = {
+    val improvedMsg = msg.replace("string matching regex `\\z'", "End of 
expression")
+
+    throw ExpressionParserException(
+      s"""Could not parse expression at column ${next.pos.column}: $improvedMsg
+        |${next.pos.longString}""".stripMargin)
+  }
 }

Reply via email to