def braced(char=anychar, left=lit('('), right=lit(')'), esc=lit('\\')): charseq = seq(but(right), char) if esc: escseq = seq(skip(esc), alter(right, esc)) charseq = alter(escseq, charseq) return wrap_parser('braced')( surround(pipe(star(charseq), join), left, right) )
def quoted(char=anychar, quot=charclass('\'"'), esc=lit('\\')): charseq = seq(but(state.check), char) if esc: escseq = seq(skip(esc), alter(quot, esc)) charseq = alter(escseq, charseq) return wrap_parser('quoted')( surround(pipe(star(charseq), join), state.push(quot), state.pop) )
def __gt__(self, other): ''' Self is enclosed into balanced pair of parsers: left <( parser )> right Both side parsers are considered optional automatically, as this parser doesn't have sense for non-optional border parsers, use (left - parser - right) syntax for arbitrary borders. ''' left, right = self.args_stack.pop(), other def left_parser(inp): token, rest = left(inp) if token is None: return [], inp self.state_stack.append(token) return token, rest def right_parser(inp): token, rest = right(inp) if token is None: return [], inp try: self.state_stack.pop() except IndexError: return [], inp return token, rest parser = compound.seq(left_parser, self.parser, right_parser) return Parser(parser)
def __mul__(self, other): ''' Repeat self other times (num of (min, max)) ''' if isinstance(other, tuple): min, max = other else: min, max = None, other parser = basic.fail if max == inf: if min is None: min = 0 if min == 0: parser = compound.star(self.parser) elif min == 1: parser = compound.plus(self.parser) elif min > 1: parser = compound.seq( compound.rep(self.parser, min), compound.star(self.parser)) else: if min is None: min = max elif min > max: min, max = max, min if min > -1 and max > 0: if min == 0 and max == 1: parser = tools.opt(self.parser) else: parser = compound.rep(self.parser, min, max) return Parser(parser)
def __mul__(self, other): ''' Repeat self other times (num of (min, max)) ''' if isinstance(other, tuple): min, max = other else: min, max = None, other parser = basic.fail if max == inf: if min is None: min = 0 if min == 0: parser = compound.star(self.parser) elif min == 1: parser = compound.plus(self.parser) elif min > 1: parser = compound.seq(compound.rep(self.parser, min), compound.star(self.parser)) else: if min is None: min = max elif min > max: min, max = max, min if min > -1 and max > 0: if min == 0 and max == 1: parser = tools.opt(self.parser) else: parser = compound.rep(self.parser, min, max) return Parser(parser)
def drop(self): ''' Drop last saved state, no check ''' return Parser(compound.seq(self.parser, state.state.drop))
def __rxor__(self, other): parser = compound.seq(tools.but(self.parser), _(other).parser) return Parser(parser)
def __xor__(self, other): ''' Match self, but not after other ''' parser = compound.seq(tools.but(_(other).parser), self.parser) return Parser(parser)
def __rsub__(self, other): parser = compound.seq(_(other).parser, self.parser) return Parser(parser)
def __sub__(self, other): ''' Match self, then match other ''' parser = compound.seq(self.parser, _(other).parser) return Parser(parser)
def indent(line): indent = skip(Indentation(True)) dedent = skip(Indentation(False)) keep = skip(Indentation(None)) return seq(indent, opt(line), star(seq(keep, line)), peek(dedent))
def st(self): ''' Check last saved state ''' return Parser(compound.seq(self.parser, state.state.check))
def surround(parser, left=lit('('), right=lit(')')): return wrap_parser('surround')( seq(skip(left), parser, skip(right)))
def commalist(parser, comma=lit(','), wsp=charclass('\t ')): delim = seq(star(wsp), comma, star(wsp)) return wrap_parser('commalist')( seq(parser, star(seq(skip(delim), parser))))
def pop(self): ''' Pop last saved state and check it ''' return Parser(compound.seq(self.parser, state.state.pop))
def word(w, border='\t '): from greencss.lexer.parsers.compound import seq, star border = star(charclass(border)) return wrap_parser('word', w)( seq(border, lit(w), border) )