Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 28871:6d6201fc5aae
parser: move alias declaration parser to common rule-set class
The original _parsealiasdecl() function is split into common _builddecl()
and revset-specific _parsealiasdecl(). And the original _parsealiasdecl()
call is temporarily replaced by rules._builddecl(), which should be eliminated
later.
The doctests are mostly ported by using the dummy parse(), but the test for
'foo bar' is kept in _parsealiasdecl() as it checks if "pos != len(decl)" is
working. Also, 'foo($1)' test is added to make sure the alias tokenizer can
handle '$1' symbol, which is the only reason why we need _parsealiasdecl().
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Mon, 29 Feb 2016 17:54:03 +0900 |
parents | 475dad3432fd |
children | 5f31d2248745 |
comparison
equal
deleted
inserted
replaced
28870:475dad3432fd | 28871:6d6201fc5aae |
---|---|
2235 syminitletters=_aliassyminitletters) | 2235 syminitletters=_aliassyminitletters) |
2236 | 2236 |
2237 def _parsealiasdecl(decl): | 2237 def _parsealiasdecl(decl): |
2238 """Parse alias declaration ``decl`` | 2238 """Parse alias declaration ``decl`` |
2239 | 2239 |
2240 This returns ``(name, tree, args, errorstr)`` tuple: | 2240 >>> _parsealiasdecl('foo($1)') |
2241 | 2241 ('func', ('symbol', 'foo'), ('symbol', '$1')) |
2242 - ``name``: of declared alias (may be ``decl`` itself at error) | |
2243 - ``tree``: parse result (or ``None`` at error) | |
2244 - ``args``: list of alias argument names (or None for symbol declaration) | |
2245 - ``errorstr``: detail about detected error (or None) | |
2246 | |
2247 >>> _parsealiasdecl('foo') | |
2248 ('foo', ('symbol', 'foo'), None, None) | |
2249 >>> _parsealiasdecl('$foo') | |
2250 ('$foo', None, None, "'$' not for alias arguments") | |
2251 >>> _parsealiasdecl('foo::bar') | |
2252 ('foo::bar', None, None, 'invalid format') | |
2253 >>> _parsealiasdecl('foo bar') | 2242 >>> _parsealiasdecl('foo bar') |
2254 ('foo bar', None, None, 'at 4: invalid token') | 2243 Traceback (most recent call last): |
2255 >>> _parsealiasdecl('foo()') | 2244 ... |
2256 ('foo', ('func', ('symbol', 'foo')), [], None) | 2245 ParseError: ('invalid token', 4) |
2257 >>> _parsealiasdecl('$foo()') | |
2258 ('$foo()', None, None, "'$' not for alias arguments") | |
2259 >>> _parsealiasdecl('foo($1, $2)') | |
2260 ('foo', ('func', ('symbol', 'foo')), ['$1', '$2'], None) | |
2261 >>> _parsealiasdecl('foo(bar_bar, baz.baz)') | |
2262 ('foo', ('func', ('symbol', 'foo')), ['bar_bar', 'baz.baz'], None) | |
2263 >>> _parsealiasdecl('foo($1, $2, nested($1, $2))') | |
2264 ('foo($1, $2, nested($1, $2))', None, None, 'invalid argument list') | |
2265 >>> _parsealiasdecl('foo(bar($1, $2))') | |
2266 ('foo(bar($1, $2))', None, None, 'invalid argument list') | |
2267 >>> _parsealiasdecl('foo("string")') | |
2268 ('foo("string")', None, None, 'invalid argument list') | |
2269 >>> _parsealiasdecl('foo($1, $2') | |
2270 ('foo($1, $2', None, None, 'at 10: unexpected token: end') | |
2271 >>> _parsealiasdecl('foo("string') | |
2272 ('foo("string', None, None, 'at 5: unterminated string') | |
2273 >>> _parsealiasdecl('foo($1, $2, $1)') | |
2274 ('foo', None, None, 'argument names collide with each other') | |
2275 """ | 2246 """ |
2276 p = parser.parser(elements) | 2247 p = parser.parser(elements) |
2277 try: | 2248 tree, pos = p.parse(_tokenizealias(decl)) |
2278 tree, pos = p.parse(_tokenizealias(decl)) | 2249 if pos != len(decl): |
2279 if (pos != len(decl)): | 2250 raise error.ParseError(_('invalid token'), pos) |
2280 raise error.ParseError(_('invalid token'), pos) | 2251 return parser.simplifyinfixops(tree, ('list',)) |
2281 tree = parser.simplifyinfixops(tree, ('list',)) | |
2282 except error.ParseError as inst: | |
2283 return (decl, None, None, parser.parseerrordetail(inst)) | |
2284 | |
2285 if True: # XXX to be removed | |
2286 if tree[0] == 'symbol': | |
2287 # "name = ...." style | |
2288 name = tree[1] | |
2289 if name.startswith('$'): | |
2290 return (decl, None, None, _("'$' not for alias arguments")) | |
2291 return (name, tree, None, None) | |
2292 | |
2293 if tree[0] == 'func' and tree[1][0] == 'symbol': | |
2294 # "name(arg, ....) = ...." style | |
2295 name = tree[1][1] | |
2296 if name.startswith('$'): | |
2297 return (decl, None, None, _("'$' not for alias arguments")) | |
2298 args = [] | |
2299 for arg in getlist(tree[2]): | |
2300 if arg[0] != 'symbol': | |
2301 return (decl, None, None, _("invalid argument list")) | |
2302 args.append(arg[1]) | |
2303 if len(args) != len(set(args)): | |
2304 return (name, None, None, | |
2305 _("argument names collide with each other")) | |
2306 return (name, tree[:2], args, None) | |
2307 | |
2308 return (decl, None, None, _("invalid format")) | |
2309 | 2252 |
2310 def _relabelaliasargs(tree, args): | 2253 def _relabelaliasargs(tree, args): |
2311 if not isinstance(tree, tuple): | 2254 if not isinstance(tree, tuple): |
2312 return tree | 2255 return tree |
2313 op = tree[0] | 2256 op = tree[0] |
2367 return _relabelaliasargs(tree, args) | 2310 return _relabelaliasargs(tree, args) |
2368 | 2311 |
2369 class _aliasrules(parser.basealiasrules): | 2312 class _aliasrules(parser.basealiasrules): |
2370 """Parsing and expansion rule set of revset aliases""" | 2313 """Parsing and expansion rule set of revset aliases""" |
2371 _section = _('revset alias') | 2314 _section = _('revset alias') |
2315 _parsedecl = staticmethod(_parsealiasdecl) | |
2372 _getlist = staticmethod(getlist) | 2316 _getlist = staticmethod(getlist) |
2373 | 2317 |
2374 class revsetalias(object): | 2318 class revsetalias(object): |
2375 # whether own `error` information is already shown or not. | 2319 # whether own `error` information is already shown or not. |
2376 # this avoids showing same warning multiple times at each `findaliases`. | 2320 # this avoids showing same warning multiple times at each `findaliases`. |
2380 '''Aliases like: | 2324 '''Aliases like: |
2381 | 2325 |
2382 h = heads(default) | 2326 h = heads(default) |
2383 b($1) = ancestors($1) - ancestors(default) | 2327 b($1) = ancestors($1) - ancestors(default) |
2384 ''' | 2328 ''' |
2385 self.name, self.tree, self.args, self.error = _parsealiasdecl(name) | 2329 r = _aliasrules._builddecl(name) |
2330 self.name, self.tree, self.args, self.error = r | |
2386 if self.error: | 2331 if self.error: |
2387 self.error = _('failed to parse the declaration of revset alias' | 2332 self.error = _('failed to parse the declaration of revset alias' |
2388 ' "%s": %s') % (self.name, self.error) | 2333 ' "%s": %s') % (self.name, self.error) |
2389 return | 2334 return |
2390 | 2335 |