fix rule order so 'HAVING (X op Y)' is now parseable while 'HAVING (1+2) op Y' isn't anymore parseable... At some point we should consider more advanced parsing system than yapps.
--- a/parser.g Thu Jun 10 10:41:54 2010 +0200
+++ b/parser.g Thu Jun 10 11:37:57 2010 +0200
@@ -268,8 +268,16 @@
rule exprs_not<<S>>: NOT balanced_expr<<S>> {{ return Not(balanced_expr) }}
| balanced_expr<<S>> {{ return balanced_expr }}
-rule balanced_expr<<S>>: expr_add<<S>> expr_op<<S>> {{ expr_op.insert(0, expr_add); return expr_op }}
- | r"\(" logical_expr<<S>> r"\)" {{ return logical_expr }}
+#// XXX ambiguity, expr_add may also have '(' as first token. Hence
+#// put "(" logical_expr<<S>> ")" rule first. We can then parse:
+#//
+#// Any T2 WHERE T1 relation T2 HAVING (1 < COUNT(T1));
+#//
+#// but not
+#//
+#// Any T2 WHERE T1 relation T2 HAVING (1+2) < COUNT(T1);
+rule balanced_expr<<S>>: r"\(" logical_expr<<S>> r"\)" {{ return logical_expr }}
+ | expr_add<<S>> expr_op<<S>> {{ expr_op.insert(0, expr_add); return expr_op }}
# // cant use expr<<S>> without introducing some ambiguities
rule expr_op<<S>>: CMP_OP expr_add<<S>> {{ return Comparison(CMP_OP.upper(), expr_add) }}
--- a/parser.py Thu Jun 10 10:41:54 2010 +0200
+++ b/parser.py Thu Jun 10 11:37:57 2010 +0200
@@ -519,9 +519,17 @@
def balanced_expr(self, S, _parent=None):
_context = self.Context(_parent, self._scanner, 'balanced_expr', [S])
_token = self._peek('r"\\("', 'NULL', 'DATE', 'DATETIME', 'TRUE', 'FALSE', 'FLOAT', 'INT', 'STRING', 'SUBSTITUTE', 'VARIABLE', 'E_TYPE', 'FUNCTION', context=_context)
- expr_add = self.expr_add(S, _context)
- expr_op = self.expr_op(S, _context)
- expr_op.insert(0, expr_add); return expr_op
+ if _token == 'r"\\("':
+ self._scan('r"\\("', context=_context)
+ logical_expr = self.logical_expr(S, _context)
+ self._scan('r"\\)"', context=_context)
+ return logical_expr
+ elif 1:
+ expr_add = self.expr_add(S, _context)
+ expr_op = self.expr_op(S, _context)
+ expr_op.insert(0, expr_add); return expr_op
+ else:
+ raise runtime.SyntaxError(_token[0], 'Could not match balanced_expr')
def expr_op(self, S, _parent=None):
_context = self.Context(_parent, self._scanner, 'expr_op', [S])
--- a/test/unittest_parser.py Thu Jun 10 10:41:54 2010 +0200
+++ b/test/unittest_parser.py Thu Jun 10 11:37:57 2010 +0200
@@ -133,6 +133,21 @@
' GROUPBY T2'
' WHERE T1 relation T2'
' HAVING 1 < COUNT(T1) OR COUNT(T1) IN (3,4);',
+
+ 'Any T2'
+ ' GROUPBY T2'
+ ' WHERE T1 relation T2'
+ ' HAVING (COUNT(T1) IN (1,2)) OR (COUNT(T1) IN (3,4));',
+
+ 'Any T2'
+ ' GROUPBY T2'
+ ' WHERE T1 relation T2'
+ ' HAVING (1 < COUNT(T1) OR COUNT(T1) IN (3,4));',
+
+ 'Any T2'
+ ' GROUPBY T2'
+ ' WHERE T1 relation T2'
+ ' HAVING 1+2 < COUNT(T1);',
)
class ParserHercule(TestCase):