-# Parse query
-
-from ply import lex, yacc
-
-literals = '()'
-
-tokens = ('NAME', 'AND_OP', 'OR_OP', 'NOT_OP', 'SP1')
-
-t_NAME = '[a-z][a-z0-9_]*'
-
-t_AND_OP = '&'
-
-t_OR_OP = r'\|'
-
-t_NOT_OP = '!'
-
-t_SP1 = '[ \t]+'
-
-def t_error(t):
- """Avoid warnings on stderr"""
-
-lexer = lex.lex()
-
-def p_expression_name(p):
- """expression : NAME"""
- p[0] = ('NAME', p[1])
-
-def p_expression_and_and(p):
- """expression : expression SP0 AND_OP AND_OP SP0 expression"""
- p[0] = ('AND', p[1], p[6])
-
-def p_expression_and(p):
- """expression : expression SP0 AND_OP SP0 expression"""
- p[0] = ('AND', p[1], p[5])
-
-def p_expression_and_word(p):
- """expression : l_expression and_word r_expression"""
- p[0] = ('AND', p[1], p[3])
-
-def p_expression_not(p):
- """expression : NOT_OP SP0 expression"""
- p[0] = ('NOT', p[3])
-
-def p_expression_or_or(p):
- """expression : expression SP0 OR_OP OR_OP SP0 expression"""
- p[0] = ('OR', p[1], p[6])
-
-def p_expression_or(p):
- """expression : expression SP0 OR_OP SP0 expression"""
- p[0] = ('OR', p[1], p[5])
-
-def p_expression_in_parens(p):
- """expression : expression_parens"""
- p[0] = p[1]
-
-def p_l_expression(p):
- """l_expression : expression_parens
- | expression SP1
- """
- if len(p) == 2:
- p[0] = p[1]
- elif len(p) == 3:
- p[0] = p[1]
- else:
- raise ValueError(p)
-
-def p_r_expression(p):
- """r_expression : expression_parens
- | SP1 expression
- """
- if len(p) == 2:
- p[0] = p[1]
- elif len(p) == 3:
- p[0] = p[2]
- else:
- raise ValueError(p)
-
-def p_expression_parens(p):
- """expression_parens : '(' SP0 expression SP0 ')'"""
- p[0] = ('PARENS', p[3])
-
-def p_and_word(p):
- """and_word : NAME"""
- if p[1] in ('AND', 'and'):
- p[0] = p[1]
- else:
- raise SyntaxError
-
-def p_SP0(p):
- """SP0 : SP1
- | empty
- """
-
-def p_empty(p):
- """empty :"""
-
-def p_error(p):
- """Avoid warnings on stderr"""
- yacc.restart()
-
-precedence = (
- ('left', 'OR_OP'),
- ('left', 'AND_OP'),
- ('right', 'NOT_OP'),
-)
-
-parser = yacc.yacc()
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# CAVEAT UTILITOR
+#
+# This file was automatically generated by Grako.
+#
+# https://pypi.python.org/pypi/grako/
+#
+# Any changes you make to it will be overwritten the next time
+# the file is generated.
+
+
+from __future__ import print_function, division, absolute_import, unicode_literals
+
+from grako.parsing import graken, Parser
+from grako.util import re, RE_FLAGS, generic_main # noqa
+
+
+__version__ = (2016, 7, 11, 18, 15, 20, 0)
+
+__all__ = [
+ 'TagsParser',
+ 'TagsSemantics',
+ 'main'
+]
+
+KEYWORDS = set([])
+
+
+class TagsParser(Parser):
+ def __init__(self,
+ whitespace=None,
+ nameguard=None,
+ comments_re=None,
+ eol_comments_re=None,
+ ignorecase=None,
+ left_recursion=True,
+ keywords=KEYWORDS,
+ namechars='',
+ **kwargs):
+ super(TagsParser, self).__init__(
+ whitespace=whitespace,
+ nameguard=nameguard,
+ comments_re=comments_re,
+ eol_comments_re=eol_comments_re,
+ ignorecase=ignorecase,
+ left_recursion=left_recursion,
+ keywords=keywords,
+ namechars=namechars,
+ **kwargs
+ )
+
+ @graken()
+ def _start_(self):
+ self._expression_()
+ self._check_eof()
+
+ @graken()
+ def _expression_(self):
+ with self._choice():
+ with self._option():
+ self._expression1_()
+ with self._ifnot():
+ self._or_op_()
+ with self._option():
+ self._or_expression_()
+ self._error('no available options')
+
+ @graken()
+ def _or_expression_(self):
+ self._expression1_()
+ self._or_op_()
+ self._expression_()
+
+ @graken()
+ def _and_expression_(self):
+ self._expression2_()
+ self._and_op_()
+ self._expression1_()
+
+ @graken()
+ def _not_expression_(self):
+ self._not_op_()
+ self._expression3_()
+
+ @graken()
+ def _parens_expression_(self):
+ self._token('(')
+ self._expression_()
+ self._token(')')
+
+ @graken()
+ def _expression1_(self):
+ with self._choice():
+ with self._option():
+ self._expression2_()
+ with self._ifnot():
+ self._and_op_()
+ with self._option():
+ self._and_expression_()
+ self._error('no available options')
+
+ @graken()
+ def _expression2_(self):
+ with self._choice():
+ with self._option():
+ with self._ifnot():
+ self._not_op_()
+ self._expression3_()
+ with self._option():
+ self._not_expression_()
+ self._error('no available options')
+
+ @graken()
+ def _expression3_(self):
+ with self._choice():
+ with self._option():
+ self._parens_expression_()
+ with self._option():
+ self._name_()
+ self._error('no available options')
+
+ @graken()
+ def _and_op_(self):
+ with self._choice():
+ with self._option():
+ self._token('&&')
+ with self._option():
+ self._token('&')
+ with self._option():
+ self._token('AND')
+ with self._option():
+ self._token('and')
+ self._error('expecting one of: & && AND and')
+
+ @graken()
+ def _or_op_(self):
+ with self._choice():
+ with self._option():
+ self._token('||')
+ with self._option():
+ self._token('|')
+ with self._option():
+ self._token('OR')
+ with self._option():
+ self._token('or')
+ self._error('expecting one of: OR or | ||')
+
+ @graken()
+ def _not_op_(self):
+ with self._choice():
+ with self._option():
+ self._token('!')
+ with self._option():
+ self._token('NOT')
+ with self._option():
+ self._token('not')
+ self._error('expecting one of: ! NOT not')
+
+ @graken()
+ def _name_(self):
+ self._pattern(r'[a-z][a-z0-9_]+')
+
+
+class TagsSemantics(object):
+ def start(self, ast):
+ return ast
+
+ def expression(self, ast):
+ return ast
+
+ def or_expression(self, ast):
+ return ast
+
+ def and_expression(self, ast):
+ return ast
+
+ def not_expression(self, ast):
+ return ast
+
+ def parens_expression(self, ast):
+ return ast
+
+ def expression1(self, ast):
+ return ast
+
+ def expression2(self, ast):
+ return ast
+
+ def expression3(self, ast):
+ return ast
+
+ def and_op(self, ast):
+ return ast
+
+ def or_op(self, ast):
+ return ast
+
+ def not_op(self, ast):
+ return ast
+
+ def name(self, ast):
+ return ast
+
+
+def main(
+ filename,
+ startrule,
+ trace=False,
+ whitespace=None,
+ nameguard=None,
+ comments_re=None,
+ eol_comments_re=None,
+ ignorecase=None,
+ left_recursion=True,
+ **kwargs):
+
+ with open(filename) as f:
+ text = f.read()
+ whitespace = whitespace or None
+ parser = TagsParser(parseinfo=False)
+ ast = parser.parse(
+ text,
+ startrule,
+ filename=filename,
+ trace=trace,
+ whitespace=whitespace,
+ nameguard=nameguard,
+ ignorecase=ignorecase,
+ **kwargs)
+ return ast
+
+if __name__ == '__main__':
+ import json
+ ast = generic_main(main, TagsParser, name='Tags')
+ print('AST:')
+ print(ast)
+ print()
+ print('JSON:')
+ print(json.dumps(ast, indent=2))
+ print()