def datetime_parser() -> ParseResults: # pylint: disable=too-many-locals ( # pylint: disable=invalid-name DATETIME, DATEADD, DATETRUNC, LASTDAY, HOLIDAY, YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, ) = map( CaselessKeyword, "datetime dateadd datetrunc lastday holiday " "year quarter month week day hour minute second".split(), ) lparen, rparen, comma = map(Suppress, "(),") int_operand = pyparsing_common.signed_integer().setName("int_operand") text_operand = quotedString.setName("text_operand").setParseAction( EvalText) # allow expression to be used recursively datetime_func = Forward().setName("datetime") dateadd_func = Forward().setName("dateadd") datetrunc_func = Forward().setName("datetrunc") lastday_func = Forward().setName("lastday") holiday_func = Forward().setName("holiday") date_expr = (datetime_func | dateadd_func | datetrunc_func | lastday_func | holiday_func) datetime_func <<= (DATETIME + lparen + text_operand + rparen).setParseAction(EvalDateTimeFunc) dateadd_func <<= ( DATEADD + lparen + Group(date_expr + comma + int_operand + comma + (YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND) + ppOptional(comma)) + rparen).setParseAction(EvalDateAddFunc) datetrunc_func <<= ( DATETRUNC + lparen + Group(date_expr + comma + (YEAR | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND) + ppOptional(comma)) + rparen).setParseAction(EvalDateTruncFunc) lastday_func <<= (LASTDAY + lparen + Group(date_expr + comma + (YEAR | MONTH | WEEK) + ppOptional(comma)) + rparen).setParseAction(EvalLastDayFunc) holiday_func <<= (HOLIDAY + lparen + Group(text_operand + ppOptional(comma) + ppOptional(date_expr) + ppOptional(comma) + ppOptional(text_operand) + ppOptional(comma)) + rparen).setParseAction(EvalHolidayFunc) return date_expr
def build(self): # ------------------------------------------ # C. building blocks # ------------------------------------------ self.termop = Regex( "|".join(self.neighbourhood_symbols), re.IGNORECASE).setParseAction(upcaseTokens).setName("termop") termword = Word(self.unicode_printables + self.separators + self.wildcards).setName("term") termword_termop = (termword + OneOrMore(self.termop + termword)) # ------------------------------------------ # D. triple # ------------------------------------------ index = Word(alphanums).setName("index") #index = Word(indexchars).setName("index") #SolrProximitySuffix = Suppress(Optional(Word('~') + Word(nums))) binop = oneOf(self.binop_symbols, caseless=True).setName("binop") term = ( # Attempt to parse {!complexphrase}text:"((aussto* OR eject* OR pusher*) AND (verriegel* OR lock* OR sperr*))"~6 ... # ... but failed. #Combine(quotedString.setParseAction(removeQuotes) + SolrProximitySuffix).setName("term") ^ # term is a quoted string, easy peasy quotedString.setName("term") ^ # term is just a termword, easy too termword.setName("term") ^ # term contains neighbourhood operators, so should have been wrapped in parenthesis Combine('(' + Suppress(ZeroOrMore(' ')) + termword_termop + Suppress(ZeroOrMore(' ')) + ')').setName("term") ^ # convenience/gracefulness: we also allow terms containing # neighbourhood operators without being wrapped in parenthesis Combine(termword_termop).setName("term")) # ------------------------------------------ # E. condition # ------------------------------------------ cqlStatement = Forward() # Parse regular cql condition notation 'index=term'. cqlConditionBase = Group( # a regular triple (index + binop + term).setResultsName("triple") | # a regular subquery ("(" + cqlStatement + ")").setResultsName("subquery")) # Parse value shortcut notations like 'index=(term)' or 'index=(term1 and term2 or term3)'. cqlConditionShortcut = Group( # a triple in value shortcut notation (contains only the single term) # "term + NotAny(binop)" helps giving proper error messages like # "ParseException: Expected term (at char 4)" for erroneous queries like "foo=" (term + NotAny(binop)).setResultsName("triple-short") | # a subquery containing values in shortcut notation (index + binop + "(" + cqlStatement + ")").setResultsName("subquery-short")) #cqlCondition = cqlConditionBase cqlCondition = cqlConditionBase | cqlConditionShortcut # ------------------------------------------ # F. statement # ------------------------------------------ cqlStatement << cqlCondition + ZeroOrMore(self.booleans_or + cqlStatement) # apply SQL comment format cqlComment = "--" + restOfLine cqlStatement.ignore(cqlComment) self.parser = cqlStatement
""" A program is a list of statements. Statements can be 'set' or 'select' statements. """ statement = Forward() SELECT, FROM, WHERE, SET, AS, CREATE, GRAPH, AT = map( CaselessKeyword, "select from where set as create graph at".split()) concept_name = Word( alphas, alphanums + ":_") ident = Word( "$" + alphas, alphanums + "_$" ).setName("identifier") columnName = delimitedList(ident, ".", combine=True).setName("column name") columnNameList = Group( delimitedList(columnName)) tableName = delimitedList(ident, ".", combine=True).setName("column name") tableName = quotedString.setName ("service name") tableNameList = Group(delimitedList(tableName)) SEMI,COLON,LPAR,RPAR,LBRACE,RBRACE,LBRACK,RBRACK,DOT,COMMA,EQ = map(Literal,";:(){}[].,=") arrow = Literal ("->") | \ Literal ("<-") | \ Group(Literal("-[") + concept_name + Literal("]->")) | \ Group(Literal("<-[") + concept_name + Literal("]-")) question_graph_element = ( concept_name + ZeroOrMore ( LineEnd () ) ) | \ Group ( concept_name + COLON + concept_name + ZeroOrMore ( LineEnd () ) ) question_graph_expression = question_graph_element + ZeroOrMore(arrow + question_graph_element)
Regex, nestedExpr, pyparsing_common as ppc) """ A program is a list of statements. Statements can be 'set' or 'select' statements. """ statement = Forward() SELECT, FROM, WHERE, SET, AS, CREATE, GRAPH, AT = map( CaselessKeyword, "select from where set as create graph at".split()) concept_name = Word(alphas, alphanums + ":_") ident = Word("$" + alphas, alphanums + "_$").setName("identifier") columnName = delimitedList(ident, ".", combine=True).setName("column name") columnNameList = Group(delimitedList(columnName)) tableName = delimitedList(ident, ".", combine=True).setName("column name") tableName = quotedString.setName("service name") tableNameList = Group(delimitedList(tableName)) SEMI, COLON, LPAR, RPAR, LBRACE, RBRACE, LBRACK, RBRACK, DOT, COMMA, EQ = map( Literal, ";:(){}[].,=") concept_value = quotedString.setName('concept value') concept_value_list = Group(LBRACK.suppress() + delimitedList(concept_value) + RBRACK.suppress()) arrow = \ Group(Literal("-[") + concept_name + Literal("]->")) | \ Group(Literal("<-[") + concept_name + Literal("]-")) | \ Literal ("->") | \ Literal ("<-") question_graph_element = (