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