##// END OF EJS Templates
revset: raise ParseError exceptions
Matt Mackall -
r11289:4215ce51 default
parent child Browse files
Show More
@@ -15,6 +15,8 b''
15 # an action is a tree node name, a tree label, and an optional match
15 # an action is a tree node name, a tree label, and an optional match
16 # __call__(program) parses program into a labelled tree
16 # __call__(program) parses program into a labelled tree
17
17
18 import error
19
18 class parser(object):
20 class parser(object):
19 def __init__(self, tokenizer, elements, methods=None):
21 def __init__(self, tokenizer, elements, methods=None):
20 self._tokenizer = tokenizer
22 self._tokenizer = tokenizer
@@ -31,14 +33,15 b' class parser(object):'
31 def _match(self, m):
33 def _match(self, m):
32 'make sure the tokenizer matches an end condition'
34 'make sure the tokenizer matches an end condition'
33 if self.current[0] != m:
35 if self.current[0] != m:
34 raise SyntaxError(self.current)
36 raise error.ParseError("unexpected token: %s" % self.current[2],
37 pos)
35 self._advance()
38 self._advance()
36 def _parse(self, bind=0):
39 def _parse(self, bind=0):
37 token, value = self._advance()
40 token, value, pos = self._advance()
38 # handle prefix rules on current token
41 # handle prefix rules on current token
39 prefix = self._elements[token][1]
42 prefix = self._elements[token][1]
40 if not prefix:
43 if not prefix:
41 raise SyntaxError("not a prefix: %s" % token)
44 raise error.ParseError("not a prefix: %s" % token, pos)
42 if len(prefix) == 1:
45 if len(prefix) == 1:
43 expr = (prefix[0], value)
46 expr = (prefix[0], value)
44 else:
47 else:
@@ -51,7 +54,7 b' class parser(object):'
51 self._match(prefix[2])
54 self._match(prefix[2])
52 # gather tokens until we meet a lower binding strength
55 # gather tokens until we meet a lower binding strength
53 while bind < self._elements[self.current[0]][0]:
56 while bind < self._elements[self.current[0]][0]:
54 token, value = self._advance()
57 token, value, pos = self._advance()
55 e = self._elements[token]
58 e = self._elements[token]
56 # check for suffix - next token isn't a valid prefix
59 # check for suffix - next token isn't a valid prefix
57 if len(e) == 4 and not self._elements[self.current[0]][1]:
60 if len(e) == 4 and not self._elements[self.current[0]][1]:
@@ -65,7 +68,7 b' class parser(object):'
65 expr = (infix[0], expr, (None))
68 expr = (infix[0], expr, (None))
66 else:
69 else:
67 if not infix[0]:
70 if not infix[0]:
68 raise SyntaxError("not an infix")
71 raise error.ParseError("not an infix: %s" % token, pos)
69 expr = (infix[0], expr, self._parse(infix[1]))
72 expr = (infix[0], expr, self._parse(infix[1]))
70 if len(infix) == 3:
73 if len(infix) == 3:
71 self._match(infix[2])
74 self._match(infix[2])
@@ -6,7 +6,7 b''
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 re
8 import re
9 import parser, util, hg
9 import parser, util, hg, error
10 import match as _match
10 import match as _match
11
11
12 elements = {
12 elements = {
@@ -40,13 +40,13 b' def tokenize(program):'
40 if c.isspace(): # skip inter-token whitespace
40 if c.isspace(): # skip inter-token whitespace
41 pass
41 pass
42 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
42 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
43 yield ('::', None)
43 yield ('::', None, pos)
44 pos += 1 # skip ahead
44 pos += 1 # skip ahead
45 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
45 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
46 yield ('..', None)
46 yield ('..', None, pos)
47 pos += 1 # skip ahead
47 pos += 1 # skip ahead
48 elif c in "():,-|&+!": # handle simple operators
48 elif c in "():,-|&+!": # handle simple operators
49 yield (c, None)
49 yield (c, None, pos)
50 elif c in '"\'': # handle quoted strings
50 elif c in '"\'': # handle quoted strings
51 pos += 1
51 pos += 1
52 s = pos
52 s = pos
@@ -56,11 +56,11 b' def tokenize(program):'
56 pos += 2
56 pos += 2
57 continue
57 continue
58 if d == c:
58 if d == c:
59 yield ('string', program[s:pos].decode('string-escape'))
59 yield ('string', program[s:pos].decode('string-escape'), s)
60 break
60 break
61 pos += 1
61 pos += 1
62 else:
62 else:
63 raise "unterminated string"
63 raise error.ParseError("unterminated string", s)
64 elif c.isalnum() or c in '.': # gather up a symbol/keyword
64 elif c.isalnum() or c in '.': # gather up a symbol/keyword
65 s = pos
65 s = pos
66 pos += 1
66 pos += 1
@@ -74,21 +74,21 b' def tokenize(program):'
74 pos += 1
74 pos += 1
75 sym = program[s:pos]
75 sym = program[s:pos]
76 if sym in keywords: # operator keywords
76 if sym in keywords: # operator keywords
77 yield (sym, None)
77 yield (sym, None, s)
78 else:
78 else:
79 yield ('symbol', sym)
79 yield ('symbol', sym, s)
80 pos -= 1
80 pos -= 1
81 else:
81 else:
82 raise "syntax error at %d" % pos
82 raise error.ParseError("syntax error", pos)
83 pos += 1
83 pos += 1
84 yield ('end', None)
84 yield ('end', None, pos)
85
85
86 # helpers
86 # helpers
87
87
88 def getstring(x, err):
88 def getstring(x, err):
89 if x[0] == 'string' or x[0] == 'symbol':
89 if x[0] == 'string' or x[0] == 'symbol':
90 return x[1]
90 return x[1]
91 raise err
91 raise error.ParseError(err)
92
92
93 def getlist(x):
93 def getlist(x):
94 if not x:
94 if not x:
@@ -100,12 +100,12 b' def getlist(x):'
100 def getpair(x, err):
100 def getpair(x, err):
101 l = getlist(x)
101 l = getlist(x)
102 if len(l) != 2:
102 if len(l) != 2:
103 raise err
103 raise error.ParseError(err)
104 return l
104 return l
105
105
106 def getset(repo, subset, x):
106 def getset(repo, subset, x):
107 if not x:
107 if not x:
108 raise "missing argument"
108 raise error.ParseError("missing argument")
109 return methods[x[0]](repo, subset, *x[1:])
109 return methods[x[0]](repo, subset, *x[1:])
110
110
111 # operator methods
111 # operator methods
@@ -124,7 +124,7 b' def stringset(repo, subset, x):'
124
124
125 def symbolset(repo, subset, x):
125 def symbolset(repo, subset, x):
126 if x in symbols:
126 if x in symbols:
127 raise "can't use %s here" % x
127 raise error.ParseError("can't use %s here" % x)
128 return stringset(repo, subset, x)
128 return stringset(repo, subset, x)
129
129
130 def rangeset(repo, subset, x, y):
130 def rangeset(repo, subset, x, y):
@@ -147,12 +147,12 b' def notset(repo, subset, x):'
147 return [r for r in subset if r not in s]
147 return [r for r in subset if r not in s]
148
148
149 def listset(repo, subset, a, b):
149 def listset(repo, subset, a, b):
150 raise "can't use a list in this context"
150 raise error.ParseError("can't use a list in this context")
151
151
152 def func(repo, subset, a, b):
152 def func(repo, subset, a, b):
153 if a[0] == 'symbol' and a[1] in symbols:
153 if a[0] == 'symbol' and a[1] in symbols:
154 return symbols[a[1]](repo, subset, b)
154 return symbols[a[1]](repo, subset, b)
155 raise "that's not a function: %s" % a[1]
155 raise error.ParseError("not a function: %s" % a[1])
156
156
157 # functions
157 # functions
158
158
@@ -190,7 +190,7 b' def limit(repo, subset, x):'
190 try:
190 try:
191 lim = int(getstring(l[1], "limit wants a number"))
191 lim = int(getstring(l[1], "limit wants a number"))
192 except ValueError:
192 except ValueError:
193 raise "wants a number"
193 raise error.ParseError("limit expects a number")
194 return getset(repo, subset, l[0])[:lim]
194 return getset(repo, subset, l[0])[:lim]
195
195
196 def children(repo, subset, x):
196 def children(repo, subset, x):
@@ -216,7 +216,7 b' def ancestor(repo, subset, x):'
216 a = getset(repo, subset, l[0])
216 a = getset(repo, subset, l[0])
217 b = getset(repo, subset, l[1])
217 b = getset(repo, subset, l[1])
218 if len(a) > 1 or len(b) > 1:
218 if len(a) > 1 or len(b) > 1:
219 raise "arguments to ancestor must be single revisions"
219 raise error.ParseError("ancestor args must be single revisions")
220 return [repo[a[0]].ancestor(repo[b[0]]).rev()]
220 return [repo[a[0]].ancestor(repo[b[0]]).rev()]
221
221
222 def ancestors(repo, subset, x):
222 def ancestors(repo, subset, x):
@@ -231,7 +231,7 b' def descendants(repo, subset, x):'
231
231
232 def follow(repo, subset, x):
232 def follow(repo, subset, x):
233 if x:
233 if x:
234 raise "follow takes no args"
234 raise error.ParseError("follow takes no args")
235 p = repo['.'].rev()
235 p = repo['.'].rev()
236 s = set(repo.changelog.ancestors(p)) | set([p])
236 s = set(repo.changelog.ancestors(p)) | set([p])
237 return [r for r in subset if r in s]
237 return [r for r in subset if r in s]
@@ -336,7 +336,7 b' def removes(repo, subset, x):'
336
336
337 def merge(repo, subset, x):
337 def merge(repo, subset, x):
338 if x:
338 if x:
339 raise "merge takes no args"
339 raise error.ParseError("merge takes no args")
340 cl = repo.changelog
340 cl = repo.changelog
341 return [r for r in subset if cl.parentrevs(r)[1] != -1]
341 return [r for r in subset if cl.parentrevs(r)[1] != -1]
342
342
@@ -390,7 +390,7 b' def sort(repo, subset, x):'
390 elif k == '-date':
390 elif k == '-date':
391 e.append(-c.date()[0])
391 e.append(-c.date()[0])
392 else:
392 else:
393 raise "unknown sort key %r" % k
393 raise error.ParseError("unknown sort key %r" % k)
394 e.append(r)
394 e.append(r)
395 l.append(e)
395 l.append(e)
396 l.sort()
396 l.sort()
General Comments 0
You need to be logged in to leave comments. Login now