mercurial/filesetlang.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43089 c59eb1560c44
--- 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'))