]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blobdiff - parser/parser.py
Change grammar to support priority of operation
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
index 460a552e43691262d2fac6ba192c00c69fa783b2..4984f1862f4a4ef165dfc7ba05a3c263e2936056 100755 (executable)
@@ -17,7 +17,7 @@ from grako.parsing import graken, Parser
 from grako.util import re, RE_FLAGS, generic_main  # noqa
 
 
-__version__ = (2016, 7, 9, 18, 10, 4, 5)
+__version__ = (2016, 7, 10, 22, 31, 57, 6)
 
 __all__ = [
     'TagsParser',
@@ -58,42 +58,79 @@ class TagsParser(Parser):
 
     @graken()
     def _expression_(self):
-        with self._group():
-            with self._choice():
-                with self._option():
-                    self._expression_()
-                    self._and_op_()
-                    self._expression_()
-                with self._option():
-                    self._expression_()
-                    self._or_op_()
-                    self._expression_()
-                with self._option():
-                    self._not_op_()
-                    self._expression_()
-                with self._option():
-                    self._expression_parens_()
-                with self._option():
-                    self._name_()
-                self._error('no available options')
+        with self._choice():
+            with self._option():
+                self._expression1_()
+                with self._ifnot():
+                    with self._if():
+                        self._or_op_()
+            with self._option():
+                self._or_expression_()
+            self._error('no available options')
 
     @graken()
-    def _expression_parens_(self):
+    def _or_expression_(self):
+        self._expression1_()
+        self._or_op_()
+        self._expression_()
+
+    @graken()
+    def _and_expression_(self):
+        self._expression2_()
+        self._and_op_()
+        self._expression1_()
+
+    @graken()
+    def _not_expression_(self):
+        self._not_op_()
+        self._expression3_()
+
+    @graken()
+    def _parens_expression_(self):
         self._token('(')
         self._expression_()
         self._token(')')
 
     @graken()
-    def _name_(self):
-        self._pattern(r'[a-z][a-z0-9_]+')
+    def _expression1_(self):
+        with self._choice():
+            with self._option():
+                self._expression2_()
+                with self._ifnot():
+                    with self._if():
+                        self._and_op_()
+            with self._option():
+                self._and_expression_()
+            self._error('no available options')
 
     @graken()
-    def _and_op_(self):
+    def _expression2_(self):
         with self._choice():
             with self._option():
-                self._token('&')
+                with self._ifnot():
+                    with self._if():
+                        self._not_op_()
+                self._expression3_()
+            with self._option():
+                self._not_expression_()
+            self._error('no available options')
+
+    @graken()
+    def _expression3_(self):
+        with self._choice():
+            with self._option():
+                self._parens_expression_()
+            with self._option():
+                self._name_()
+            self._error('no available options')
+
+    @graken()
+    def _and_op_(self):
+        with self._choice():
             with self._option():
                 self._token('&&')
+            with self._option():
+                self._token('&')
             with self._option():
                 self._token('AND')
             with self._option():
@@ -103,10 +140,10 @@ class TagsParser(Parser):
     @graken()
     def _or_op_(self):
         with self._choice():
-            with self._option():
-                self._token('|')
             with self._option():
                 self._token('||')
+            with self._option():
+                self._token('|')
             with self._option():
                 self._token('OR')
             with self._option():
@@ -124,6 +161,10 @@ class TagsParser(Parser):
                 self._token('not')
             self._error('expecting one of: ! NOT not')
 
+    @graken()
+    def _name_(self):
+        self._pattern(r'[a-z][a-z0-9_]+')
+
 
 class TagsSemantics(object):
     def start(self, ast):
@@ -132,10 +173,25 @@ class TagsSemantics(object):
     def expression(self, ast):
         return ast
 
-    def expression_parens(self, ast):
+    def or_expression(self, ast):
         return ast
 
-    def name(self, ast):
+    def and_expression(self, ast):
+        return ast
+
+    def not_expression(self, ast):
+        return ast
+
+    def parens_expression(self, ast):
+        return ast
+
+    def expression1(self, ast):
+        return ast
+
+    def expression2(self, ast):
+        return ast
+
+    def expression3(self, ast):
         return ast
 
     def and_op(self, ast):
@@ -147,6 +203,9 @@ class TagsSemantics(object):
     def not_op(self, ast):
         return ast
 
+    def name(self, ast):
+        return ast
+
 
 def main(
         filename,