class String(MathematicaObject, str): grammar = Literal('"'), re.compile(r'([^\"]*)'), Literal('"') head = "String" @property def body(self): return [str(self[:])] def __repr__(self): return '"{}"'.format(str(self[:]))
class Value(UnaryRule): """Generic rule for all kinds of phrases recognized. Serves as an encapsulation of the listed rules. """ grammar = attr('op', [(optional(omit(Literal("="))), RangeOp), GreaterEqualOp, LessEqualOp, GreaterThanOp, LessThanOp, (optional(omit(Literal("="))), [ ComplexValue, ParenthesizedSimpleValues, SimpleValueBooleanQuery, SimpleValue ])])
class ParenthesizedSimpleValues(UnaryRule): """Parses parenthesized simple values along with boolean operations on them.""" grammar = omit(Literal("(")), [ SimpleValueBooleanQuery, SimpleValueNegation, SimpleValue ], omit(Literal(")")) @classmethod def parse(cls, parser, text, pos): """Using our own parse to enable the flag below.""" try: parser._parsing_parenthesized_simple_values_expression = True remaining_text, recognized_tokens = parser.parse(text, cls.grammar) return remaining_text, recognized_tokens except SyntaxError as e: return text, e finally: parser._parsing_parenthesized_simple_values_expression = False
class LessEqualOp(UnaryRule): """Less than or Equal to operator. Supports queries like date <= 10-2000 or author-count 100-. """ grammar = [ (omit(Literal("<=")), attr('op', SimpleValue)), # Accept a number or numbers that are separated with (/ or -) followed by a "-" which should be # followed by \s or ) or end of input so that you don't accept a value like 1-e. (attr('op', re.compile(r"\d+([/-]\d+)*(?=-)")), omit(re.compile(r'-(?=\s|\)|$)'))), ]
class LessEqualOp(UnaryRule): """Less than or Equal to operator. Supports queries like date <= 10-2000 or author-count 100-. """ grammar = [ (omit(Literal("<=")), attr('op', SimpleValue)), # Accept a number or anything that doesn't contain {whitespace, (, ), :} followed by a "-" which should be # followed by \s or ) or end of input so that you don't accept a value that is 1-e. (attr('op', re.compile(r"\d+")), omit(re.compile(r'-(?=\s|\)|$)'))), (attr('op', re.compile(r"[^\s():]+(?=( -|-))")), omit(re.compile(r'\+(?=\s|\)|$)'))), ]
class RangeOp(BinaryRule): """Range operator mixing any type of values. E.g. muon decay year:1983->1992 author:"Ellis, J"->"Ellis, Qqq" author:"Ellis, J"->Ellis, M The non symmetrical type of values will be handled at a later phase. """ grammar = \ attr('left', [ComplexValue, SimpleRangeValue]), \ omit(Literal("->")), \ attr('right', [ComplexValue, SimpleRangeValue])
class OrQuery(UnaryRule): grammar = [ ( omit(Or), [ (omit(Whitespace), attr('op', SimpleQuery)), (omit(_), attr('op', ParenthesizedQuery)), ], ), ( omit(Literal('|')), attr('op', SimpleQuery), ), ]
class AndQuery(UnaryRule): grammar = [ ( omit(And), [ (omit(Whitespace), attr('op', NotQuery)), (omit(Whitespace), attr('op', SimpleQuery)), (omit(_), attr('op', ParenthesizedQuery)), ], ), ( omit(Literal('+')), attr('op', SimpleQuery), ), ]
SpiresQuery.grammar = attr('children', ( [ SpiresParenthesizedQuery, SpiresSimpleQuery, ], maybe_some((omit(_), [ SpiresNotQuery, SpiresAndQuery, SpiresOrQuery, ])), )) SpiresKeywordQuery.grammar = [ ( attr('left', NestableKeyword), omit(_, Literal(':'), _), attr('right', [SpiresParenthesizedQuery, SpiresSimpleQuery, ValueQuery]), ), ( attr('left', NestableKeyword), omit(Whitespace), attr('right', [SpiresParenthesizedQuery, SpiresSimpleQuery, SpiresValueQuery]), ), (attr('left', KeywordRule), omit(_, Literal(':'), _), attr('right', Value)), (attr('left', SpiresKeywordRule), omit(_, Literal(':'), _), attr('right', Value)), (attr('left', SpiresKeywordRule), omit(Whitespace), attr('right', [
class DoubleQuotedString(LeafRule): grammar = Literal('"'), attr('value', re.compile(r'([^"]|\\.)*')), \ Literal('"')
class SingleQuotedString(LeafRule): grammar = Literal("'"), attr('value', re.compile(r"([^']|\\.)*")), \ Literal("'")
class Or(object): grammar = omit([ re.compile(r"or", re.I), Literal('|'), ])
class AndOperator(EmptyLeafRule): grammar = [Literal('and'), Literal('&&')]
class NotKeywordValue(LeafRule): pass class KeywordQuery(BinaryRule): pass class EmptyQueryRule(LeafRule): grammar = attr('value', re.compile(r'\s*')) KeywordQuery.grammar = [ (attr('left', KeywordRule), omit(_, Literal(':'), _), attr('right', NestedKeywordsRule)), (attr('left', KeywordRule), omit(Literal(':'), _), attr('right', Value)), (attr('left', KeywordRule), omit(Literal(':'), _), attr('right', Query)), ] class SimpleQuery(UnaryRule): grammar = attr('op', [KeywordQuery, ValueQuery]) class ParenthesizedQuery(UnaryRule): grammar = ( omit(Literal('('), _), attr('op', Query), omit(_, Literal(')')),
class LowerEqualQuery(UnaryRule): grammar = [ (omit(Literal('<='), _), attr('op', SpiresValue)), (attr('op', Number), omit(re.compile(r'\-(?=\s|\)|$)'))), ]
class Not(object): grammar = omit([ omit(re.compile(r"AND\s+NOT")), re.compile(r"NOT"), Literal('-'), ])
class SlashQuotedString(LeafRule): grammar = Literal('/'), attr('value', re.compile(r"([^/]|\\.)*")), \ Literal('/')
class And(object): grammar = omit([ re.compile(r"AND"), Literal('+'), ])
class List(MExpression): head = MSymbol("List") grammar = ( Literal("{"), optional(attr("body", csl(MExpression))), Literal("}") )
body = None class List(MExpression): head = MSymbol("List") grammar = ( Literal("{"), optional(attr("body", csl(MExpression))), Literal("}") ) # Since MExpression is recursive, we need to define the class, # then the grammar. Moreover, since it depends on List and other # such things, we need to put it last. MExpression.grammar = [ ( attr("head", MSymbol), Literal("["), optional(attr("body", csl(MExpression))), Literal("]") ), attr("head", MSymbol), List, atom ] ## TESTING ########################################################### if __name__ == "__main__": print parse("ab`c", MExpression) print parse('12', MExpression) print parse('"a"', MExpression) print parse("List", MExpression) print parse("List[]", MExpression)
class GreaterQuery(UnaryRule): grammar = (omit([Literal('>'), re.compile('after', re.I)], _), attr('op', SpiresValue))
class Whitespace(object): grammar = maybe_some([Literal(' '), Literal('\n'), Literal('\t')])
class LowerQuery(UnaryRule): grammar = (omit([Literal('<'), re.compile('before', re.I)], _), attr('op', SpiresValue))
class Not(object): grammar = omit([ omit(re.compile(r"and\s+not", re.I)), re.compile(r"not", re.I), Literal('-'), ])
class SpiresParenthesizedQuery(UnaryRule): grammar = ( omit(Literal('('), _), attr('op', SpiresQuery), omit(_, Literal(')')), )
class And(object): grammar = omit([ re.compile(r"and", re.I), Literal('+'), ])
class RangeOp(BinaryRule): grammar = (attr('left', RangeValue), Literal('->'), attr('right', RangeValue))
class ValueQuery(UnaryRule): grammar = attr('op', Value) class Query(ListRule): pass class KeywordQuery(BinaryRule): pass KeywordQuery.grammar = [ ( attr('left', KeywordRule), omit(_, Literal(':'), _), attr('right', KeywordQuery) ), ( attr('left', KeywordRule), omit(_, Literal(':'), _), attr('right', Value) ), ( attr('left', KeywordRule), omit(_, Literal(':'), _), attr('right', Query) ), ]
class ParenthesizedQuery(UnaryRule): """Parenthesized query for denoting precedence.""" grammar = omit(Literal('(')), attr('op', Statement), omit(Literal(')'))
class IncludeStatement(UnaryRule): grammar = '{', _, Keyword('include'), _, Literal( 'file='), Expression, _, '}'