diff -r 2372284d9457 -r 687b865b95ad mercurial/filesetlang.py --- a/mercurial/filesetlang.py Sun Oct 06 09:45:02 2019 -0400 +++ b/mercurial/filesetlang.py Sun Oct 06 09:48:39 2019 -0400 @@ -23,28 +23,28 @@ elements = { # token-type: binding-strength, primary, prefix, infix, suffix - "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), - ":": (15, None, None, ("kindpat", 15), None), - "-": (5, None, ("negate", 19), ("minus", 5), None), - "not": (10, None, ("not", 10), None, None), - "!": (10, None, ("not", 10), None, None), - "and": (5, None, None, ("and", 5), None), - "&": (5, None, None, ("and", 5), None), - "or": (4, None, None, ("or", 4), None), - "|": (4, None, None, ("or", 4), None), - "+": (4, None, None, ("or", 4), None), - ",": (2, None, None, ("list", 2), None), - ")": (0, None, None, None, None), - "symbol": (0, "symbol", None, None, None), - "string": (0, "string", None, None, None), - "end": (0, None, None, None, None), + b"(": (20, None, (b"group", 1, b")"), (b"func", 1, b")"), None), + b":": (15, None, None, (b"kindpat", 15), None), + b"-": (5, None, (b"negate", 19), (b"minus", 5), None), + b"not": (10, None, (b"not", 10), None, None), + b"!": (10, None, (b"not", 10), None, None), + b"and": (5, None, None, (b"and", 5), None), + b"&": (5, None, None, (b"and", 5), None), + b"or": (4, None, None, (b"or", 4), None), + b"|": (4, None, None, (b"or", 4), None), + b"+": (4, None, None, (b"or", 4), None), + b",": (2, None, None, (b"list", 2), None), + b")": (0, None, None, None, None), + b"symbol": (0, b"symbol", None, None, None), + b"string": (0, b"string", None, None, None), + b"end": (0, None, None, None, None), } -keywords = {'and', 'or', 'not'} +keywords = {b'and', b'or', b'not'} symbols = {} -globchars = ".*{}[]?/\\_" +globchars = b".*{}[]?/\\_" def tokenize(program): @@ -54,12 +54,14 @@ c = program[pos] if c.isspace(): # skip inter-token whitespace pass - elif c in "(),-:|&+!": # handle simple operators + elif c in b"(),-:|&+!": # handle simple operators yield (c, None, pos) elif ( - c in '"\'' or c == 'r' and program[pos : pos + 2] in ("r'", 'r"') + c in b'"\'' + or c == b'r' + and program[pos : pos + 2] in (b"r'", b'r"') ): # handle quoted strings - if c == 'r': + if c == b'r': pos += 1 c = program[pos] decode = lambda x: x @@ -69,15 +71,15 @@ s = pos while pos < l: # find closing quote d = program[pos] - if d == '\\': # skip over escaped characters + if d == b'\\': # skip over escaped characters pos += 2 continue if d == c: - yield ('string', decode(program[s:pos]), s) + yield (b'string', decode(program[s:pos]), s) break pos += 1 else: - raise error.ParseError(_("unterminated string"), s) + raise error.ParseError(_(b"unterminated string"), s) elif c.isalnum() or c in globchars or ord(c) > 127: # gather up a symbol/keyword s = pos @@ -91,30 +93,30 @@ if sym in keywords: # operator keywords yield (sym, None, s) else: - yield ('symbol', sym, s) + yield (b'symbol', sym, s) pos -= 1 else: - raise error.ParseError(_("syntax error"), pos) + raise error.ParseError(_(b"syntax error"), pos) pos += 1 - yield ('end', None, pos) + yield (b'end', None, pos) def parse(expr): p = parser.parser(elements) tree, pos = p.parse(tokenize(expr)) if pos != len(expr): - raise error.ParseError(_("invalid token"), pos) - return parser.simplifyinfixops(tree, {'list', 'or'}) + raise error.ParseError(_(b"invalid token"), pos) + return parser.simplifyinfixops(tree, {b'list', b'or'}) def getsymbol(x): - if x and x[0] == 'symbol': + if x and x[0] == b'symbol': return x[1] - raise error.ParseError(_('not a symbol')) + raise error.ParseError(_(b'not a symbol')) def getstring(x, err): - if x and (x[0] == 'string' or x[0] == 'symbol'): + if x and (x[0] == b'string' or x[0] == b'symbol'): return x[1] raise error.ParseError(err) @@ -123,12 +125,12 @@ kind = getsymbol(x) pat = getstring(y, err) if kind not in allkinds: - raise error.ParseError(_("invalid pattern kind: %s") % kind) - return '%s:%s' % (kind, pat) + raise error.ParseError(_(b"invalid pattern kind: %s") % kind) + return b'%s:%s' % (kind, pat) def getpattern(x, allkinds, err): - if x and x[0] == 'kindpat': + if x and x[0] == b'kindpat': return getkindpat(x[1], x[2], allkinds, err) return getstring(x, err) @@ -136,7 +138,7 @@ def getlist(x): if not x: return [] - if x[0] == 'list': + if x[0] == b'list': return list(x[1:]) return [x] @@ -153,33 +155,33 @@ return x op = x[0] - if op in {'string', 'symbol'}: + if op in {b'string', b'symbol'}: return x - if op == 'kindpat': + if op == b'kindpat': getsymbol(x[1]) # kind must be a symbol t = _analyze(x[2]) return (op, x[1], t) - if op == 'group': + if op == b'group': return _analyze(x[1]) - if op == 'negate': - raise error.ParseError(_("can't use negate operator in this context")) - if op == 'not': + if op == b'negate': + raise error.ParseError(_(b"can't use negate operator in this context")) + if op == b'not': t = _analyze(x[1]) return (op, t) - if op == 'and': + if op == b'and': ta = _analyze(x[1]) tb = _analyze(x[2]) return (op, ta, tb) - if op == 'minus': - return _analyze(('and', x[1], ('not', x[2]))) - if op in {'list', 'or'}: + if op == b'minus': + return _analyze((b'and', x[1], (b'not', x[2]))) + if op in {b'list', b'or'}: ts = tuple(_analyze(y) for y in x[1:]) return (op,) + ts - if op == 'func': + if op == b'func': getsymbol(x[1]) # function name must be a symbol ta = _analyze(x[2]) return (op, x[1], ta) - raise error.ProgrammingError('invalid operator %r' % op) + raise error.ProgrammingError(b'invalid operator %r' % op) def _insertstatushints(x): @@ -195,35 +197,35 @@ return (), x op = x[0] - if op in {'string', 'symbol', 'kindpat'}: + if op in {b'string', b'symbol', b'kindpat'}: return (), x - if op == 'not': + if op == b'not': h, t = _insertstatushints(x[1]) return h, (op, t) - if op == 'and': + if op == b'and': ha, ta = _insertstatushints(x[1]) hb, tb = _insertstatushints(x[2]) hr = ha + hb if ha and hb: - return hr, ('withstatus', (op, ta, tb), ('string', ' '.join(hr))) + return hr, (b'withstatus', (op, ta, tb), (b'string', b' '.join(hr))) return hr, (op, ta, tb) - if op == 'or': + if op == b'or': hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) hr = sum(hs, ()) if sum(bool(h) for h in hs) > 1: - return hr, ('withstatus', (op,) + ts, ('string', ' '.join(hr))) + return hr, (b'withstatus', (op,) + ts, (b'string', b' '.join(hr))) return hr, (op,) + ts - if op == 'list': + if op == b'list': hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) return sum(hs, ()), (op,) + ts - if op == 'func': + if op == b'func': f = getsymbol(x[1]) # don't propagate 'ha' crossing a function boundary ha, ta = _insertstatushints(x[2]) if getattr(symbols.get(f), '_callstatus', False): - return (f,), ('withstatus', (op, x[1], ta), ('string', f)) + return (f,), (b'withstatus', (op, x[1], ta), (b'string', f)) return (), (op, x[1], ta) - raise error.ProgrammingError('invalid operator %r' % op) + raise error.ProgrammingError(b'invalid operator %r' % op) def _mergestatushints(x, instatus): @@ -235,29 +237,29 @@ return x op = x[0] - if op == 'withstatus': + if op == b'withstatus': if instatus: # drop redundant hint node return _mergestatushints(x[1], instatus) t = _mergestatushints(x[1], instatus=True) return (op, t, x[2]) - if op in {'string', 'symbol', 'kindpat'}: + if op in {b'string', b'symbol', b'kindpat'}: return x - if op == 'not': + if op == b'not': t = _mergestatushints(x[1], instatus) return (op, t) - if op == 'and': + if op == b'and': ta = _mergestatushints(x[1], instatus) tb = _mergestatushints(x[2], instatus) return (op, ta, tb) - if op in {'list', 'or'}: + if op in {b'list', b'or'}: ts = tuple(_mergestatushints(y, instatus) for y in x[1:]) return (op,) + ts - if op == 'func': + if op == b'func': # don't propagate 'instatus' crossing a function boundary ta = _mergestatushints(x[2], instatus=False) return (op, x[1], ta) - raise error.ProgrammingError('invalid operator %r' % op) + raise error.ProgrammingError(b'invalid operator %r' % op) def analyze(x): @@ -273,8 +275,8 @@ def _optimizeandops(op, ta, tb): - if tb is not None and tb[0] == 'not': - return ('minus', ta, tb[1]) + if tb is not None and tb[0] == b'not': + return (b'minus', ta, tb[1]) return (op, ta, tb) @@ -283,14 +285,14 @@ ws, ts, ss = [], [], [] for x in xs: w, t = _optimize(x) - if t is not None and t[0] in {'string', 'symbol', 'kindpat'}: + if t is not None and t[0] in {b'string', b'symbol', b'kindpat'}: ss.append(t) continue ws.append(w) ts.append(t) if ss: ws.append(WEIGHT_CHECK_FILENAME) - ts.append(('patterns',) + tuple(ss)) + ts.append((b'patterns',) + tuple(ss)) return ws, ts @@ -299,25 +301,25 @@ return 0, x op = x[0] - if op == 'withstatus': + if op == b'withstatus': w, t = _optimize(x[1]) return w, (op, t, x[2]) - if op in {'string', 'symbol'}: + if op in {b'string', b'symbol'}: return WEIGHT_CHECK_FILENAME, x - if op == 'kindpat': + if op == b'kindpat': w, t = _optimize(x[2]) return w, (op, x[1], t) - if op == 'not': + if op == b'not': w, t = _optimize(x[1]) return w, (op, t) - if op == 'and': + if op == b'and': wa, ta = _optimize(x[1]) wb, tb = _optimize(x[2]) if wa <= wb: return wa, _optimizeandops(op, ta, tb) else: return wb, _optimizeandops(op, tb, ta) - if op == 'or': + if op == b'or': ws, ts = _optimizeunion(x[1:]) if len(ts) == 1: return ws[0], ts[0] # 'or' operation is fully optimized out @@ -325,15 +327,15 @@ it[1] for it in sorted(enumerate(ts), key=lambda it: ws[it[0]]) ) return max(ws), (op,) + ts - if op == 'list': + if op == b'list': ws, ts = zip(*(_optimize(y) for y in x[1:])) return sum(ws), (op,) + ts - if op == 'func': + if op == b'func': f = getsymbol(x[1]) w = getattr(symbols.get(f), '_weight', 1) wa, ta = _optimize(x[2]) return w + wa, (op, x[1], ta) - raise error.ProgrammingError('invalid operator %r' % op) + raise error.ProgrammingError(b'invalid operator %r' % op) def optimize(x): @@ -346,4 +348,4 @@ def prettyformat(tree): - return parser.prettyformat(tree, ('string', 'symbol')) + return parser.prettyformat(tree, (b'string', b'symbol'))