revset: raise ParseError exceptions
authorMatt Mackall <mpm@selenic.com>
Fri, 04 Jun 2010 20:57:52 -0500
changeset 11289 4215ce511134
parent 11288 2123aad24d56
child 11290 8c6c7f6347a3
revset: raise ParseError exceptions
mercurial/parser.py
mercurial/revset.py
--- a/mercurial/parser.py	Fri Jun 04 20:57:26 2010 -0500
+++ b/mercurial/parser.py	Fri Jun 04 20:57:52 2010 -0500
@@ -15,6 +15,8 @@
 # an action is a tree node name, a tree label, and an optional match
 # __call__(program) parses program into a labelled tree
 
+import error
+
 class parser(object):
     def __init__(self, tokenizer, elements, methods=None):
         self._tokenizer = tokenizer
@@ -31,14 +33,15 @@
     def _match(self, m):
         'make sure the tokenizer matches an end condition'
         if self.current[0] != m:
-            raise SyntaxError(self.current)
+            raise error.ParseError("unexpected token: %s" % self.current[2],
+                                   pos)
         self._advance()
     def _parse(self, bind=0):
-        token, value = self._advance()
+        token, value, pos = self._advance()
         # handle prefix rules on current token
         prefix = self._elements[token][1]
         if not prefix:
-            raise SyntaxError("not a prefix: %s" % token)
+            raise error.ParseError("not a prefix: %s" % token, pos)
         if len(prefix) == 1:
             expr = (prefix[0], value)
         else:
@@ -51,7 +54,7 @@
                     self._match(prefix[2])
         # gather tokens until we meet a lower binding strength
         while bind < self._elements[self.current[0]][0]:
-            token, value = self._advance()
+            token, value, pos = self._advance()
             e = self._elements[token]
             # check for suffix - next token isn't a valid prefix
             if len(e) == 4 and not self._elements[self.current[0]][1]:
@@ -65,7 +68,7 @@
                     expr = (infix[0], expr, (None))
                 else:
                     if not infix[0]:
-                        raise SyntaxError("not an infix")
+                        raise error.ParseError("not an infix: %s" % token, pos)
                     expr = (infix[0], expr, self._parse(infix[1]))
                     if len(infix) == 3:
                         self._match(infix[2])
--- a/mercurial/revset.py	Fri Jun 04 20:57:26 2010 -0500
+++ b/mercurial/revset.py	Fri Jun 04 20:57:52 2010 -0500
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 import re
-import parser, util, hg
+import parser, util, hg, error
 import match as _match
 
 elements = {
@@ -40,13 +40,13 @@
         if c.isspace(): # skip inter-token whitespace
             pass
         elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
-            yield ('::', None)
+            yield ('::', None, pos)
             pos += 1 # skip ahead
         elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
-            yield ('..', None)
+            yield ('..', None, pos)
             pos += 1 # skip ahead
         elif c in "():,-|&+!": # handle simple operators
-            yield (c, None)
+            yield (c, None, pos)
         elif c in '"\'': # handle quoted strings
             pos += 1
             s = pos
@@ -56,11 +56,11 @@
                     pos += 2
                     continue
                 if d == c:
-                    yield ('string', program[s:pos].decode('string-escape'))
+                    yield ('string', program[s:pos].decode('string-escape'), s)
                     break
                 pos += 1
             else:
-                raise "unterminated string"
+                raise error.ParseError("unterminated string", s)
         elif c.isalnum() or c in '.': # gather up a symbol/keyword
             s = pos
             pos += 1
@@ -74,21 +74,21 @@
                 pos += 1
             sym = program[s:pos]
             if sym in keywords: # operator keywords
-                yield (sym, None)
+                yield (sym, None, s)
             else:
-                yield ('symbol', sym)
+                yield ('symbol', sym, s)
             pos -= 1
         else:
-            raise "syntax error at %d" % pos
+            raise error.ParseError("syntax error", pos)
         pos += 1
-    yield ('end', None)
+    yield ('end', None, pos)
 
 # helpers
 
 def getstring(x, err):
     if x[0] == 'string' or x[0] == 'symbol':
         return x[1]
-    raise err
+    raise error.ParseError(err)
 
 def getlist(x):
     if not x:
@@ -100,12 +100,12 @@
 def getpair(x, err):
     l = getlist(x)
     if len(l) != 2:
-        raise err
+        raise error.ParseError(err)
     return l
 
 def getset(repo, subset, x):
     if not x:
-        raise "missing argument"
+        raise error.ParseError("missing argument")
     return methods[x[0]](repo, subset, *x[1:])
 
 # operator methods
@@ -124,7 +124,7 @@
 
 def symbolset(repo, subset, x):
     if x in symbols:
-        raise "can't use %s here" % x
+        raise error.ParseError("can't use %s here" % x)
     return stringset(repo, subset, x)
 
 def rangeset(repo, subset, x, y):
@@ -147,12 +147,12 @@
     return [r for r in subset if r not in s]
 
 def listset(repo, subset, a, b):
-    raise "can't use a list in this context"
+    raise error.ParseError("can't use a list in this context")
 
 def func(repo, subset, a, b):
     if a[0] == 'symbol' and a[1] in symbols:
         return symbols[a[1]](repo, subset, b)
-    raise "that's not a function: %s" % a[1]
+    raise error.ParseError("not a function: %s" % a[1])
 
 # functions
 
@@ -190,7 +190,7 @@
     try:
         lim = int(getstring(l[1], "limit wants a number"))
     except ValueError:
-        raise "wants a number"
+        raise error.ParseError("limit expects a number")
     return getset(repo, subset, l[0])[:lim]
 
 def children(repo, subset, x):
@@ -216,7 +216,7 @@
     a = getset(repo, subset, l[0])
     b = getset(repo, subset, l[1])
     if len(a) > 1 or len(b) > 1:
-        raise "arguments to ancestor must be single revisions"
+        raise error.ParseError("ancestor args must be single revisions")
     return [repo[a[0]].ancestor(repo[b[0]]).rev()]
 
 def ancestors(repo, subset, x):
@@ -231,7 +231,7 @@
 
 def follow(repo, subset, x):
     if x:
-        raise "follow takes no args"
+        raise error.ParseError("follow takes no args")
     p = repo['.'].rev()
     s = set(repo.changelog.ancestors(p)) | set([p])
     return [r for r in subset if r in s]
@@ -336,7 +336,7 @@
 
 def merge(repo, subset, x):
     if x:
-        raise "merge takes no args"
+        raise error.ParseError("merge takes no args")
     cl = repo.changelog
     return [r for r in subset if cl.parentrevs(r)[1] != -1]
 
@@ -390,7 +390,7 @@
             elif k == '-date':
                 e.append(-c.date()[0])
             else:
-                raise "unknown sort key %r" % k
+                raise error.ParseError("unknown sort key %r" % k)
         e.append(r)
         l.append(e)
     l.sort()