mercurial/fileset.py
changeset 14511 30506b894359
parent 14509 4f695345979c
child 14513 85fe676c27e9
equal deleted inserted replaced
14510:eccbb9980ada 14511:30506b894359
       
     1 # fileset.py - file set queries for mercurial
       
     2 #
       
     3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 import parser, error
       
     9 from i18n import _
       
    10 
       
    11 elements = {
       
    12     "(": (20, ("group", 1, ")"), ("func", 1, ")")),
       
    13     "-": (5, ("negate", 19), ("minus", 5)),
       
    14     "not": (10, ("not", 10)),
       
    15     "!": (10, ("not", 10)),
       
    16     "and": (5, None, ("and", 5)),
       
    17     "&": (5, None, ("and", 5)),
       
    18     "or": (4, None, ("or", 4)),
       
    19     "|": (4, None, ("or", 4)),
       
    20     "+": (4, None, ("or", 4)),
       
    21     ",": (2, None, ("list", 2)),
       
    22     ")": (0, None, None),
       
    23     "symbol": (0, ("symbol",), None),
       
    24     "string": (0, ("string",), None),
       
    25     "end": (0, None, None),
       
    26 }
       
    27 
       
    28 keywords = set(['and', 'or', 'not'])
       
    29 
       
    30 def tokenize(program):
       
    31     pos, l = 0, len(program)
       
    32     while pos < l:
       
    33         c = program[pos]
       
    34         if c.isspace(): # skip inter-token whitespace
       
    35             pass
       
    36         elif c in "(),-|&+!": # handle simple operators
       
    37             yield (c, None, pos)
       
    38         elif (c in '"\'' or c == 'r' and
       
    39               program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
       
    40             if c == 'r':
       
    41                 pos += 1
       
    42                 c = program[pos]
       
    43                 decode = lambda x: x
       
    44             else:
       
    45                 decode = lambda x: x.decode('string-escape')
       
    46             pos += 1
       
    47             s = pos
       
    48             while pos < l: # find closing quote
       
    49                 d = program[pos]
       
    50                 if d == '\\': # skip over escaped characters
       
    51                     pos += 2
       
    52                     continue
       
    53                 if d == c:
       
    54                     yield ('string', decode(program[s:pos]), s)
       
    55                     break
       
    56                 pos += 1
       
    57             else:
       
    58                 raise error.ParseError(_("unterminated string"), s)
       
    59         elif c.isalnum() or c in '.*{}[]?' or ord(c) > 127: # gather up a symbol/keyword
       
    60             s = pos
       
    61             pos += 1
       
    62             while pos < l: # find end of symbol
       
    63                 d = program[pos]
       
    64                 if not (d.isalnum() or d in ".*{}[]?," or ord(d) > 127):
       
    65                     break
       
    66                 pos += 1
       
    67             sym = program[s:pos]
       
    68             if sym in keywords: # operator keywords
       
    69                 yield (sym, None, s)
       
    70             else:
       
    71                 yield ('symbol', sym, s)
       
    72             pos -= 1
       
    73         else:
       
    74             raise error.ParseError(_("syntax error"), pos)
       
    75         pos += 1
       
    76     yield ('end', None, pos)
       
    77 
       
    78 parse = parser.parser(tokenize, elements).parse
       
    79