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