]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blob - parser/parser.py
dc562dd5043783f632499d180d283591ccf46ccf
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
1 import os
2 from parsimonious import Grammar, NodeVisitor
3
4
5 # cache
6 _grammar = None
7
8
9 def load_grammar():
10     global _grammar
11     parser_dir = os.path.dirname(__file__)
12     with open(os.path.join(parser_dir, 'grammar.ebnf'), 'rt') as grammar_file:
13         grammar_text = grammar_file.read()
14     _grammar = Grammar(grammar_text)
15
16
17 def parse(input):
18     if _grammar is None:
19         load_grammar()
20     return _grammar.parse(input)
21
22
23 def cleanup_children(visited_children):
24     children = [c for c in visited_children if c]
25     if len(children) == 1:
26         return children[0]
27     else:
28         return children
29
30
31 class Compiler(NodeVisitor):
32     def generic_visit(self, node, visited_children):
33         return cleanup_children(visited_children)
34
35     def visit_or_expression(self, node, visited_children):
36         return ('OR', visited_children[0], visited_children[2])
37
38     def visit_and_expression(self, node, visited_children):
39         return ('AND', visited_children[0], visited_children[2])
40
41     def visit_not_expression(self, node, visited_children):
42         return ('NOT', visited_children[2])
43
44     def visit_parens_expression(self, node, visited_children):
45         return ('PARENS', visited_children[2])
46
47     def visit_name(self, node, visited_children):
48         return ('NAME', node.text)
49
50
51 def compile(tree):
52     if isinstance(tree, str):
53         tree = parse(tree)
54     return Compiler().visit(tree)