) # from pyparsing import (ParseResults, ) # from pyparsing import (ParseException, ) from ._actions import ( valuelists_detection, quoted_valuelists_detection, expression_type_detection, expression_type_detection_in_nestedvalues, ) BASE_STRINGS = alphanums + "-" + "_" NETWORK_STRINGS = alphanums + "-" + "_" + '.' # 適時調整 BASE_WORDS = Word(BASE_STRINGS) QUOTED_WORDS = quotedString.addParseAction(removeQuotes) END_OF_WORDS = WordEnd(BASE_STRINGS) LineSeparator = Literal(';').suppress().setResultsName('separator_token') Comments = Optional(cppStyleComment.setResultsName('comment')) opener, closer = Literal('{'), Literal('}') # ex: {1.1.1.1; 2.2.2.2; ...} WORD_LIST = (opener.suppress() + delimitedList(Word(NETWORK_STRINGS), delim=';') + LineSeparator + closer.suppress()).setParseAction(valuelists_detection) QUOTED_WORD_LIST = ( opener.suppress() + delimitedList(QUOTED_WORDS, delim=';') + LineSeparator + closer.suppress()).setParseAction(quoted_valuelists_detection)
operation = t elif t == '-': # Next tokens needs to be negated negation = True else: # Append to query the token if negation: t = ~t if operation == 'or': query |= t else: query &= t return query NO_BRTS = printables.replace('(', '').replace(')', '') SINGLE = Word(NO_BRTS.replace('*', '')) WILDCARDS = Optional('*') + SINGLE + Optional('*') + WordEnd(wordChars=NO_BRTS) QUOTED = quotedString.setParseAction(removeQuotes) OPER_AND = CaselessLiteral('and') OPER_OR = CaselessLiteral('or') OPER_NOT = '-' TERM = Combine( Optional(Word(alphas).setResultsName('meta') + ':') + (QUOTED.setResultsName('query') | WILDCARDS.setResultsName('query'))) TERM.setParseAction(createQ) EXPRESSION = operatorPrecedence( TERM, [(OPER_NOT, 1, opAssoc.RIGHT), (OPER_OR, 2, opAssoc.LEFT), (Optional(OPER_AND, default='and'), 2, opAssoc.LEFT)]) EXPRESSION.setParseAction(unionQ)
OneOrMore, Optional, Or, Regex, replaceWith, upcaseTokens, Word, WordEnd, WordStart, ZeroOrMore, ) from data_lists import tlds, schemes alphanum_word_start = WordStart(wordChars=alphanums) alphanum_word_end = WordEnd(wordChars=alphanums) # the label definition ignores the fact that labels should not end in an hyphen label = Word(initChars=alphanums, bodyChars=alphanums + '-', max=63) domain_tld = Or(tlds) domain_name = ( alphanum_word_start + Combine( Combine(OneOrMore(label + ('.' + FollowedBy(Word(alphanums + '-')))))('domain_labels') + domain_tld('tld') ) + alphanum_word_end ).setParseAction(downcaseTokens) ipv4_section = ( Word(nums, asKeyword=True, max=3) .setParseAction(lambda x: str(int(x[0])))
def unqualified_identifier() -> Token: return (locatedExpr( WordStart(alphas) + Word(alphanums + "_") + WordEnd(alphanums + "_")).setParseAction(verify_identifier).setName("Identifier"))
class SearchParser(object): """The parser for bauble.search.MapperSearch """ numeric_value = Regex( r'[-]?\d+(\.\d*)?([eE]\d+)?' ).setParseAction(NumericToken)('number') unquoted_string = Word(alphanums + alphas8bit + '%.-_*;:') string_value = ( quotedString.setParseAction(removeQuotes) | unquoted_string ).setParseAction(StringToken)('string') none_token = Literal('None').setParseAction(NoneToken) empty_token = Literal('Empty').setParseAction(EmptyToken) value_list = Forward() typed_value = ( Literal("|") + unquoted_string + Literal("|") + value_list + Literal("|") ).setParseAction(TypedValueToken) value = ( typed_value | numeric_value | none_token | empty_token | string_value ).setParseAction(ValueToken)('value') value_list << Group( OneOrMore(value) ^ delimitedList(value) ).setParseAction(ValueListAction)('value_list') domain = Word(alphas, alphanums) binop = oneOf('= == != <> < <= > >= not like contains has ilike ' 'icontains ihas is') equals = Literal('=') star_value = Literal('*') domain_values = (value_list.copy())('domain_values') domain_expression = ( (domain + equals + star_value + stringEnd) | (domain + binop + domain_values + stringEnd) ).setParseAction(DomainExpressionAction)('domain_expression') caps = srange("[A-Z]") lowers = caps.lower() binomial_name = ( Word(caps, lowers) + Word(lowers) ).setParseAction(BinomialNameAction)('binomial_name') AND_ = WordStart() + (CaselessLiteral("AND") | Literal("&&")) + WordEnd() OR_ = WordStart() + (CaselessLiteral("OR") | Literal("||")) + WordEnd() NOT_ = WordStart() + (CaselessLiteral("NOT") | Literal('!')) + WordEnd() BETWEEN_ = WordStart() + CaselessLiteral("BETWEEN") + WordEnd() query_expression = Forward()('filter') identifier = Group(delimitedList(Word(alphas+'_', alphanums+'_'), '.')).setParseAction(IdentifierToken) ident_expression = ( Group(identifier + binop + value).setParseAction(IdentExpressionToken) | ( Literal('(') + query_expression + Literal(')') ).setParseAction(ParenthesisedQuery)) between_expression = Group( identifier + BETWEEN_ + value + AND_ + value ).setParseAction(BetweenExpressionAction) query_expression << infixNotation( (ident_expression | between_expression), [(NOT_, 1, opAssoc.RIGHT, SearchNotAction), (AND_, 2, opAssoc.LEFT, SearchAndAction), (OR_, 2, opAssoc.LEFT, SearchOrAction)]) query = (domain + Keyword('where', caseless=True).suppress() + Group(query_expression) + stringEnd).setParseAction(QueryAction) statement = (query('query') | domain_expression('domain') | binomial_name('binomial') | value_list('value_list') ).setParseAction(StatementAction)('statement') def parse_string(self, text): '''request pyparsing object to parse text `text` can be either a query, or a domain expression, or a list of values. the `self.statement` pyparsing object parses the input text and return a pyparsing.ParseResults object that represents the input ''' return self.statement.parseString(text)
return val1 for _eval in self.operator_eval: val2 = _eval(context) val1 = val1 and val2 if not val1: return val1 return val1 word_characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789' expr = Forward() # define the parser integer = Word(nums) real = Combine(Word(nums) + "." + Word(nums)) constant = oneOf('True False None yes no') + WordEnd(word_characters) # TODO: expand on variable regex simple_variable = Regex(r'([a-zA-Z0-9_]+)') variable = Regex(r'([a-zA-Z0-9\._]+)') explicit_variable = '$' + Regex(r'([a-zA-Z0-9\._]+)') current_scope = Literal('$$') triple_string = (QuotedString("'''", escChar=None, unquoteResults=False) | QuotedString('"""', escChar=None, unquoteResults=False)) string = (QuotedString('"', escChar='\\', unquoteResults=False) | QuotedString("'", escChar="\\", unquoteResults=False)) regexp = QuotedString('/', escChar=None) timespan = Combine(Word(nums) + oneOf('ms s m h d'))
def ddlWord(string): return WordStart(alphanums + "_") + CaselessLiteral(string) + WordEnd(alphanums + "_")
def identifier(cls) -> Token: return ((WordStart(alphas) + Word(alphanums + "_") + WordEnd(alphanums + "_") ).setParseAction(verify_identifier).setName("Identifier"))