--- 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'))