closes #72295: add some missing operators stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 02 Aug 2011 16:22:16 +0200
branchstable
changeset 653 4990981c1826
parent 652 540cf0442346
child 654 7decc7f6c23f
closes #72295: add some missing operators * & (bitwise AND), * | (bitwise OR), * # (bitwise XOR), * << (bitwise left shift), * >> (bitwise right shift) * % (modulo), * ^ (power),
ChangeLog
nodes.py
parser.g
parser.py
--- a/ChangeLog	Fri Jul 29 15:10:49 2011 +0200
+++ b/ChangeLog	Tue Aug 02 16:22:16 2011 +0200
@@ -3,6 +3,15 @@
 
 	--
     * fix Comparison.as_string to considerer its optional attribute
+    * add some missing operators (#72295):
+
+      * % (modulo),
+      * ^ (power),
+      * & (bitwise AND),
+      * | (bitwise OR),
+      * # (bitwise XOR),
+      * << (bitwise left shift),
+      * >> (bitwise right shift)
 
 2011-07-27  --  0.29.1
     * #70264: remove_group_var renamed into remove_group_term and fixed
--- a/nodes.py	Fri Jul 29 15:10:49 2011 +0200
+++ b/nodes.py	Tue Aug 02 16:22:16 2011 +0200
@@ -483,7 +483,7 @@
         self.optional= value
 
 
-OPERATORS = frozenset(('=', '!=', '<', '<=', '>=', '>', 'ILIKE', 'LIKE', 'REGEXP'))
+CMP_OPERATORS = frozenset(('=', '!=', '<', '<=', '>=', '>', 'ILIKE', 'LIKE', 'REGEXP'))
 
 class Comparison(HSMixin, Node):
     """handle comparisons:
@@ -496,7 +496,7 @@
         Node.__init__(self)
         if operator == '~=':
             operator = 'ILIKE'
-        assert operator in OPERATORS, operator
+        assert operator in CMP_OPERATORS, operator
         self.operator = operator.encode()
         self.optional = optional
         if value is not None:
--- a/parser.g	Fri Jul 29 15:10:49 2011 +0200
+++ b/parser.g	Tue Aug 02 16:22:16 2011 +0200
@@ -71,7 +71,7 @@
     token DISTINCT:    r'(?i)DISTINCT'
     token WITH:        r'(?i)WITH'
     token WHERE:       r'(?i)WHERE'
-    token BEING:          r'(?i)BEING'
+    token BEING:       r'(?i)BEING'
     token OR:          r'(?i)OR'
     token AND:         r'(?i)AND'
     token NOT:         r'(?i)NOT'
@@ -89,8 +89,9 @@
     token NULL:        r'(?i)NULL'
     token EXISTS:      r'(?i)EXISTS'
     token CMP_OP:      r'(?i)<=|<|>=|>|!=|=|~=|LIKE|ILIKE|REGEXP'
-    token ADD_OP:      r'\+|-'
-    token MUL_OP:      r'\*|/'
+    token ADD_OP:      r'\+|-|\||#'
+    token MUL_OP:      r'\*|/|%|&'
+    token POW_OP:      r'\^|>>|<<'
     token FUNCTION:    r'[A-Za-z_]+\s*(?=\()'
     token R_TYPE:      r'[a-z_][a-z0-9_]*'
     token E_TYPE:      r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*'
@@ -317,8 +318,12 @@
                     )*                     {{ return node }}
 
 
-rule expr_mul<<S>>: expr_base<<S>>          {{ node = expr_base }}
-                    ( MUL_OP expr_base<<S>> {{ node = MathExpression( MUL_OP, node, expr_base) }}
+rule expr_mul<<S>>: expr_pow<<S>>          {{ node = expr_pow }}
+                    ( MUL_OP expr_pow<<S>> {{ node = MathExpression( MUL_OP, node, expr_pow) }}
+                    )*                     {{ return node }}
+
+rule expr_pow<<S>>: expr_base<<S>>          {{ node = expr_base }}
+                    ( POW_OP expr_base<<S>> {{ node = MathExpression( MUL_OP, node, expr_base) }}
                     )*                      {{ return node }}
 
 
--- a/parser.py	Fri Jul 29 15:10:49 2011 +0200
+++ b/parser.py	Tue Aug 02 16:22:16 2011 +0200
@@ -96,8 +96,9 @@
         ('NULL', re.compile('(?i)NULL')),
         ('EXISTS', re.compile('(?i)EXISTS')),
         ('CMP_OP', re.compile('(?i)<=|<|>=|>|!=|=|~=|LIKE|ILIKE|REGEXP')),
-        ('ADD_OP', re.compile('\\+|-')),
-        ('MUL_OP', re.compile('\\*|/')),
+        ('ADD_OP', re.compile('\\+|-|\\||#')),
+        ('MUL_OP', re.compile('\\*|/|%|&')),
+        ('POW_OP', re.compile('\\^|>>|<<')),
         ('FUNCTION', re.compile('[A-Za-z_]+\\s*(?=\\()')),
         ('R_TYPE', re.compile('[a-z_][a-z0-9_]*')),
         ('E_TYPE', re.compile('[A-Z][A-Za-z0-9]*[a-z]+[0-9]*')),
@@ -551,7 +552,7 @@
         _context = self.Context(_parent, self._scanner, 'decl_vars', [R])
         E_TYPE = self._scan('E_TYPE', context=_context)
         var = self.var(R, _context)
-        while self._peek("','", 'R_TYPE', 'QMARK', 'WHERE', '":"', 'CMP_OP', "'IN'", 'HAVING', "';'", 'MUL_OP', 'BEING', 'WITH', 'GROUPBY', 'ORDERBY', 'ADD_OP', 'LIMIT', 'OFFSET', 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'AND', 'OR', context=_context) == "','":
+        while self._peek("','", 'R_TYPE', 'QMARK', 'WHERE', '":"', 'CMP_OP', "'IN'", 'HAVING', "';'", 'POW_OP', 'BEING', 'WITH', 'GROUPBY', 'ORDERBY', 'MUL_OP', 'LIMIT', 'OFFSET', 'ADD_OP', 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'AND', 'OR', context=_context) == "','":
             R.add_main_variable(E_TYPE, var)
             self._scan("','", context=_context)
             E_TYPE = self._scan('E_TYPE', context=_context)
@@ -598,10 +599,20 @@
 
     def expr_mul(self, S, _parent=None):
         _context = self.Context(_parent, self._scanner, 'expr_mul', [S])
+        expr_pow = self.expr_pow(S, _context)
+        node = expr_pow
+        while self._peek('MUL_OP', 'ADD_OP', 'QMARK', 'r"\\)"', "','", 'SORT_DESC', 'SORT_ASC', 'CMP_OP', 'R_TYPE', "'IN'", 'GROUPBY', 'ORDERBY', 'WHERE', 'LIMIT', 'OFFSET', 'HAVING', "';'", 'WITH', 'AND', 'OR', context=_context) == 'MUL_OP':
+            MUL_OP = self._scan('MUL_OP', context=_context)
+            expr_pow = self.expr_pow(S, _context)
+            node = MathExpression( MUL_OP, node, expr_pow)
+        return node
+
+    def expr_pow(self, S, _parent=None):
+        _context = self.Context(_parent, self._scanner, 'expr_pow', [S])
         expr_base = self.expr_base(S, _context)
         node = expr_base
-        while self._peek('MUL_OP', 'ADD_OP', 'QMARK', 'r"\\)"', "','", 'SORT_DESC', 'SORT_ASC', 'CMP_OP', 'R_TYPE', "'IN'", 'GROUPBY', 'ORDERBY', 'WHERE', 'LIMIT', 'OFFSET', 'HAVING', "';'", 'WITH', 'AND', 'OR', context=_context) == 'MUL_OP':
-            MUL_OP = self._scan('MUL_OP', context=_context)
+        while self._peek('POW_OP', 'MUL_OP', 'ADD_OP', 'QMARK', 'r"\\)"', "','", 'SORT_DESC', 'SORT_ASC', 'CMP_OP', 'R_TYPE', "'IN'", 'GROUPBY', 'ORDERBY', 'WHERE', 'LIMIT', 'OFFSET', 'HAVING', "';'", 'WITH', 'AND', 'OR', context=_context) == 'POW_OP':
+            POW_OP = self._scan('POW_OP', context=_context)
             expr_base = self.expr_base(S, _context)
             node = MathExpression( MUL_OP, node, expr_base)
         return node