-#! /usr/bin/env python
+#! /usr/bin/env python3
+# coding: koi8-r
import os
-from parsley import makeGrammar
+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
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 = makeGrammar(grammar_text, {}, 'Tags')
+ 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(input).expression()
+ tree = _grammar.parse(input)
+ return TagsTransformer().transform(tree)
if __name__ == '__main__':
- print parse('test')
- print parse('!test')
- print parse('not test')
- print parse('foo or bar')
- print parse('foo && bar')
- print parse('(test)')
- print parse('(foo || bar)')
- print parse('(foo and !bar)')
+ 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(parse(u'(Тест или тест)'))
+ print('----------')