]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blobdiff - parser/parser.py
Docs(TODO): Try Pyleri
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
old mode 100644 (file)
new mode 100755 (executable)
index dc562dd..dbd0549
@@ -1,5 +1,32 @@
+#! /usr/bin/env python
+
 import os
-from parsimonious import Grammar, NodeVisitor
+from lark import Lark, Transformer
+
+
+class TagsTransformer(Transformer):
+    def and_expression(self, items):
+        left = items[0]
+        right = items[2]
+        if len(items) > 3:
+            right = self.and_expression(items[2:])
+        return ('AND', left, right)
+
+    def or_expression(self, items):
+        left = items[0]
+        right = items[2]
+        if len(items) > 3:
+            right = self.or_expression(items[2:])
+        return ('OR', left, right)
+
+    def not_expression(self, items):
+        return ('NOT', items[1])
+
+    def expression_parens(self, items):
+        return ('PARENS', items[0])
+
+    def name(self, name):
+        return ('NAME', name[0].value)
 
 
 # cache
@@ -11,44 +38,29 @@ def load_grammar():
     parser_dir = os.path.dirname(__file__)
     with open(os.path.join(parser_dir, 'grammar.ebnf'), 'rt') as grammar_file:
         grammar_text = grammar_file.read()
-    _grammar = Grammar(grammar_text)
+    grammar_lines = [line for line in grammar_text.splitlines()
+                     if not line.startswith('#')]
+    grammar_text = '\n'.join(grammar_lines)
+    _grammar = Lark(grammar_text)
 
 
 def parse(input):
     if _grammar is None:
         load_grammar()
-    return _grammar.parse(input)
-
-
-def cleanup_children(visited_children):
-    children = [c for c in visited_children if c]
-    if len(children) == 1:
-        return children[0]
-    else:
-        return children
-
-
-class Compiler(NodeVisitor):
-    def generic_visit(self, node, visited_children):
-        return cleanup_children(visited_children)
-
-    def visit_or_expression(self, node, visited_children):
-        return ('OR', visited_children[0], visited_children[2])
-
-    def visit_and_expression(self, node, visited_children):
-        return ('AND', visited_children[0], visited_children[2])
-
-    def visit_not_expression(self, node, visited_children):
-        return ('NOT', visited_children[2])
-
-    def visit_parens_expression(self, node, visited_children):
-        return ('PARENS', visited_children[2])
-
-    def visit_name(self, node, visited_children):
-        return ('NAME', node.text)
-
-
-def compile(tree):
-    if isinstance(tree, str):
-        tree = parse(tree)
-    return Compiler().visit(tree)
+    tree = _grammar.parse(input)
+    return TagsTransformer().transform(tree)
+
+
+if __name__ == '__main__':
+    print '----------'
+    print parse('test')
+    print parse('!test')
+    print parse('not test')
+    print parse('foo or bar')
+    print parse('foo && bar')
+    print parse('foo && bar && baz')
+    print parse('!foo && bar && baz')
+    print parse('(test)')
+    print parse('(foo || bar)')
+    print parse('(foo and !bar)')
+    print '----------'