]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blob - parser/parser.py
da5c6e512f024849b8ed3c8b31518f5b86d35ab3
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
1 #! /usr/bin/env python3
2 # coding: koi8-r
3
4 import os
5 from lark import Lark, Transformer
6
7
8 class TagsTransformer(Transformer):
9     def and_expression(self, items):
10         left = items[0]
11         right = items[2]
12         if len(items) > 3:
13             right = self.and_expression(items[2:])
14         return ('AND', left, right)
15
16     def or_expression(self, items):
17         left = items[0]
18         right = items[2]
19         if len(items) > 3:
20             right = self.or_expression(items[2:])
21         return ('OR', left, right)
22
23     def not_expression(self, items):
24         return ('NOT', items[1])
25
26     def expression_parens(self, items):
27         return ('PARENS', items[0])
28
29     def name(self, name):
30         return ('NAME', name[0].value)
31
32
33 # cache
34 _grammar = None
35
36
37 def load_grammar():
38     global _grammar
39     parser_dir = os.path.dirname(__file__)
40     with open(os.path.join(parser_dir, 'grammar.ebnf'), 'rt') as grammar_file:
41         grammar_text = grammar_file.read()
42     grammar_lines = [line for line in grammar_text.splitlines()
43                      if not line.startswith('#')]
44     grammar_text = '\n'.join(grammar_lines)
45     _grammar = Lark(grammar_text)
46
47
48 def parse(input):
49     if _grammar is None:
50         load_grammar()
51     tree = _grammar.parse(input)
52     return TagsTransformer().transform(tree)
53
54
55 if __name__ == '__main__':
56     print('----------')
57     print(parse('test'))
58     print(parse('!test'))
59     print(parse('not test'))
60     print(parse('foo or bar'))
61     print(parse('foo && bar'))
62     print(parse('Foo && bar && baz'))
63     print(parse('!foo && bar && baz'))
64     print(parse('(test)'))
65     print(parse('(foo || bar)'))
66     print(parse('(foo and !bar)'))
67     print(parse(u'(Тест или тест)'))
68     print('----------')