def boolean_expr(atom): """Creates a boolean expression grammar out of an expression `atom`. A boolean expression can contain the following operators, ordered by binding power: * negation: ``!term`` * conjunction: ``term & term`` * disjunction: ``term | term`` and can have parentheses for grouping. """ ops = [ (suppressed_literal(u"!"), 1, pyparsing.opAssoc.RIGHT, lambda s, l, t: ast.Negation(t[0][0])), (suppressed_literal(u"&"), 2, pyparsing.opAssoc.LEFT, lambda s, l, t: ast.Conjunction(t.asList()[0])), (suppressed_literal(u"|"), 2, pyparsing.opAssoc.LEFT, lambda s, l, t: ast.Disjunction(t.asList()[0]))] return pyparsing.operatorPrecedence(atom, ops)
def _distribute(top_conjunction): """Applies the law of distributivity to a conjunction that has disjunctions. Example: ``(d1 | d2) & d3 => (d1 & d3) | (d2 & d3)`` The function also applies associatity laws, it will never produce nested expressions with the same operators. """ disj, terms = split_children(top_conjunction, ast.Disjunction) terms = [ ast.Conjunction(t + combination) for t in [terms] for combination in outer_product(disj) ] for t in terms: t.apply_associativity() return ast.Disjunction(terms)
def handle_node_variable_def(self, child_node): """Replaces a node variable definition with a reference, and stores it. If the variable has already been defined, the node descriptions are merged. """ assert child_node.variable.type == ast.VariableTypes.NodeIdentifier node_variable = NodeVariable.from_node(child_node.variable) self.node_vars[child_node.variable.name] = node_variable if node_variable in self.node_defs: self.node_defs[node_variable] = ast.NodeDescription( ast.Conjunction([ self.node_defs[node_variable].expression, child_node.expression.expression ])) else: self.node_defs[node_variable] = child_node.expression return self.REPLACE( create_varref(child_node.variable.name, container_type=child_node.variable.container))
def tsql_grammar(): """Defines the expression for the complete TigerSearch query language. A query term is either a node operand, a node relation constraint or node predicate. An expression can be a single term or a conjunction of terms. Toplevel disjunctions are not currently not supported, toplevel disjunction is not supported, because it can always be represented by negations in the relations and node descriptions. The returned expression must match the whole input string. :AST Node: `TsqlExpression` :Example: ``#a:[cat="NP"] & root(#a) and #a > [word="safe"]`` """ atom = (node_predicate() | node_relation_constraint() | NODE_OPERAND) expr = pyparsing.Group(atom + pyparsing.OneOrMore(suppressed_literal(u"&") + atom) ).setParseAction(lambda s, l, t: ast.Conjunction(t.asList()[0])) | atom expr.setParseAction(single_value_holder(ast.TsqlExpression)) return expr + pyparsing.StringEnd()
def finish(self): return self._factory.from_ast( ast.TsqlExpression( ast.Conjunction(self._nodes + self._predicates + self._constraints)))