def _tagsplit(cls, tag): if '$' not in tag: return [s_ast.Const(tag)] segs = tag.split('.') kids = [ s_ast.VarValue(kids=[s_ast.Const(seg[1:])]) if seg[0] == '$' else s_ast.Const(seg) for seg in segs ] return kids
def cmdargv(self): argv = [] while self.more(): self.ignore(whitespace) # if we hit a | or a } we're done if self.nextstr('|'): break if self.nextstr('}'): break if not self.nextstr('{'): valu = self.cmdvalu() argv.append(valu) continue start = self.offs query = self.subquery() text = self.text[start:self.offs] argv.append(text) return s_ast.Const(tuple(argv))
def casevalu(self): self.ignorespace() if self.nextstr('"'): text = self.quoted() self.ignorespace() self.nextmust(':') return s_ast.Const(text) text = self.noms(until=':').strip() if not text: self._raiseSyntaxError('empty case statement') self.nextmust(':') return s_ast.Const(text)
def casevalu(self, kids): assert len(kids) == 1 kid = kids[0] if kid.type == 'DOUBLEQUOTEDSTRING': return self._convert_child(kid) return s_ast.Const(kid.value[:-1]) # drop the trailing ':'
def cmpr(self): self.ignore(whitespace) if self.nextstr('*'): text = self.expect('=') if text is None: raise self._raiseSyntaxError('comparison with * but not =') return s_ast.Const(text) if self.nextchar() not in cmprset: self._raiseSyntaxError('expected valid comparison char') text = self.noms(cmprset) return s_ast.Const(text)
def cmdname(self): self.ignore(whitespace) name = self.noms(cmdset) if not name: self._raiseSyntaxError(f'expected cmd name') return s_ast.Const(name)
def vartokn(self): self.ignore(whitespace) name = self.noms(varchars) if not name: self._raiseSyntaxError('expected variable name') return s_ast.Const(name)
def stormcmdargs(self, kids): kids = self._convert_children(kids) argv = [] for kid in kids: if isinstance(kid, s_ast.SubQuery): argv.append(s_ast.Const(kid.text)) else: argv.append(self._convert_child(kid)) return s_ast.List(kids=argv)
def stormcmdargs(self, kids): kids = self._convert_children(kids) argv = [] for kid in kids: if isinstance(kid, s_ast.Const): newkid = kid.valu elif isinstance(kid, s_ast.SubQuery): newkid = kid.text else: assert False, 'Unexpected rule' # pragma: no cover argv.append(newkid) return s_ast.Const(tuple(argv))
def valu(self): self.ignore(whitespace) # a simple whitespace separated string nexc = self.nextchar() if nexc in alphanum or nexc in ('-', '?'): text = self.noms(until=mustquote) return s_ast.Const(text) if self.nextstr('('): kids = self.valulist() # TODO Value() ctor convention... return s_ast.List(None, kids=kids) if self.nextstr(':'): return self.relpropvalu() if self.nextstr('.'): return self.univpropvalu() if self.nextstr('#'): tag = self.tagname() return s_ast.TagPropValue(kids=(tag,)) if self.nextstr('$'): return self.varvalu() if self.nextstr('"'): text = self.quoted() return s_ast.Const(text) if self.nextstr("'"): text = self.singlequoted() return s_ast.Const(text) self._raiseSyntaxError('unrecognized value prefix')
def filtoper(self): self.ignore(whitespace) pref = self.nextchar() if pref not in ('+', '-'): self._raiseSyntaxError('expected: + or -') self.offs += 1 cond = self.cond() kids = ( s_ast.Const(pref), cond, ) return s_ast.FiltOper(kids=kids)
def massage_vartokn(x): return s_ast.Const('' if not x else (x[1:-1] if x[0] == "'" else ( unescape(x) if x[0] == '"' else x)))
def massage_vartokn(x): return s_ast.Const('' if not x else (x[1:-1] if x[0] == "'" else ( unescape(x) if x[0] == '"' else x))) # For AstConverter, one-to-one replacements from lark to synapse AST terminalClassMap = { 'ABSPROP': s_ast.AbsProp, 'ABSPROPNOUNIV': s_ast.AbsProp, 'ALLTAGS': lambda _: s_ast.TagMatch(''), 'BREAK': lambda _: s_ast.BreakOper(), 'CONTINUE': lambda _: s_ast.ContinueOper(), 'DEREFMATCHNOSEP': massage_vartokn, 'DOUBLEQUOTEDSTRING': lambda x: s_ast.Const(unescape( x)), # drop quotes and handle escape characters 'TRIPLEQUOTEDSTRING': lambda x: s_ast.Const(x[3:-3]), # drop the triple 's 'NUMBER': lambda x: s_ast.Const(s_ast.parseNumber(x)), 'HEXNUMBER': lambda x: s_ast.Const(s_ast.parseNumber(x)), 'BOOL': lambda x: s_ast.Bool(x == 'true'), 'SINGLEQUOTEDSTRING': lambda x: s_ast.Const(x[1:-1]), # drop quotes 'TAGMATCH': lambda x: s_ast.TagMatch(kids=AstConverter._tagsplit(x)), 'VARTOKN': massage_vartokn, } # For AstConverter, one-to-one replacements from lark to synapse AST ruleClassMap = { 'abspropcond': s_ast.AbsPropCond, 'arraycond': s_ast.ArrayCond,
# For AstConverter, one-to-one replacements from lark to synapse AST terminalClassMap = { 'ABSPROP': s_ast.AbsProp, 'ABSPROPNOUNIV': s_ast.AbsProp, 'ALLTAGS': lambda _: s_ast.TagMatch(''), 'BREAK': lambda _: s_ast.BreakOper(), 'CONTINUE': lambda _: s_ast.ContinueOper(), 'DOUBLEQUOTEDSTRING': lambda x: s_ast.Const(unescape(x) ), # drop quotes and handle escape characters 'NUMBER': lambda x: s_ast.Const(s_ast.parseNumber(x)), 'SINGLEQUOTEDSTRING': lambda x: s_ast.Const(x[1:-1]), # drop quotes 'TAGMATCH': lambda x: s_ast.TagMatch(kids=AstConverter._tagsplit(x)), 'VARTOKN': lambda x: s_ast.Const(x[1:-1] if len(x) and x[0] in ("'", '"') else x) } # For AstConverter, one-to-one replacements from lark to synapse AST ruleClassMap = { 'abspropcond': s_ast.AbsPropCond, 'andexpr':
def oper(self): ''' ''' self.ignore(whitespace) if not self.more(): self._raiseSyntaxError('unexpected end of query text') if self.nextstr('{'): return self.subquery() # some syntax elements prior to a prop/oper name... if self.nextstr('->'): return self.formpivot() if self.nextstr('-+>'): return self.formjoin() if self.nextstr('<-'): return self.formpivotin() if self.nextstr('<+-'): return self.formjoinin() if self.nextstr('##'): return self.lifttagtag() char = self.nextchar() # var list assignment # ($foo, $bar) = $baz if char == '(': varl = self.varlist() self.ignore(whitespace) self.nextmust('=') self.ignore(whitespace) valu = self.valu() return s_ast.VarListSetOper(kids=(varl, valu)) # $foo = valu var assignment if char == '$': varn = self.varname() self.ignore(whitespace) self.nextmust('=') self.ignore(whitespace) valu = self.valu() kids = (varn, valu) return s_ast.VarSetOper(kids=kids) if char in ('+', '-'): return self.filtoper() if char == '#': return self.liftbytag() # :foo:bar relative property if char == ':': prop = self.relprop() # :foo=10 here could be assignment... self.ignore(whitespace) if self.nextstr('->'): return self.proppivot(prop) if self.nextstr('-+>'): return self.propjoin(prop) if self.nextstrs('<-', '<+-'): self._raiseSyntaxError('Pivot in syntax does not currently support relative properties.') tokn = self.peek(varset) if tokn == 'for': return self.forloop() if tokn == 'switch': return self.switchcase() if tokn == 'break': self.offs += 5 return s_ast.BreakOper() if tokn == 'continue': self.offs += 8 return s_ast.ContinueOper() noff = self.offs name = self.noms(varset) if not name: self._raiseSyntaxError('unknown query syntax') if self.modelinfo.isprop(name): # before ignoring more whitespace, check for form#tag[=time] if self.nextstr('#'): tag = self.tagname() form = s_ast.Const(name) self.ignore(whitespace) kids = [form, tag] if self.nextchar() in cmprstart: kids.append(self.cmpr()) kids.append(self.valu()) return s_ast.LiftFormTag(kids=kids) self.ignore(whitespace) if self.nextchar() in cmprstart: cmpr = self.cmpr() valu = self.valu() kids = (s_ast.Const(name), cmpr, valu) return s_ast.LiftPropBy(kids=kids) # lift by prop only return s_ast.LiftProp(kids=(s_ast.Const(name),)) if name in self.stormcmds: argv = self.cmdargv() self.ignore(whitespace) # eat a trailing | from a command at the beginning if self.nextstr('|'): self.offs += 1 return s_ast.CmdOper(kids=(s_ast.Const(name), argv)) # rewind and noms until whitespace self.offs = noff tokn = self.noms(until=whitespace) ndefs = list(s_scrape.scrape(tokn)) if ndefs: return s_ast.LiftByScrape(ndefs) self.offs = noff raise s_exc.NoSuchProp(name=name)
s_ast.VarListSetOper, 'orexpr': s_ast.OrCond, 'query': s_ast.Query, 'relprop': s_ast.RelProp, 'relpropcond': s_ast.RelPropCond, 'relpropvalu': s_ast.RelPropValue, 'relpropvalue': s_ast.RelPropValue, 'stormcmd': lambda kids: s_ast.CmdOper(kids=kids if len(kids) == 2 else (kids[0], s_ast.Const(tuple()))), 'tagcond': s_ast.TagCond, 'tagpropvalue': s_ast.TagPropValue, 'tagvalucond': s_ast.TagValuCond, 'valuvar': s_ast.VarSetOper, 'varderef': s_ast.VarDeref, 'vareval': s_ast.VarEvalOper, 'varvalue': s_ast.VarValue, 'univprop':