X-Git-Url: https://git.phdru.name/?a=blobdiff_plain;f=parser%2Fparser.py;h=dbd054964820852fd530b4cfab0f1da2c8e79e30;hb=2e7b7f0cd4c51eb465780317446a81401eb71faa;hp=dc562dd5043783f632499d180d283591ccf46ccf;hpb=fcd51c190450165c3315ed7e4f77bc1415db3d48;p=phdru.name%2Fcgi-bin%2Fblog-ru%2Fsearch-tags.git diff --git a/parser/parser.py b/parser/parser.py old mode 100644 new mode 100755 index dc562dd..dbd0549 --- a/parser/parser.py +++ b/parser/parser.py @@ -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 '----------'