Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/parser.py @ 28875:2e9f5453ab5a
parser: unify parser function of alias declaration and definition
We no longer have to keep them separately.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Tue, 29 Mar 2016 00:08:25 +0900 |
parents | 2ca3b7c563f3 |
children | 0c135f37c6f8 |
comparison
equal
deleted
inserted
replaced
28874:552eabef663b | 28875:2e9f5453ab5a |
---|---|
249 | 249 |
250 def __new__(cls): | 250 def __new__(cls): |
251 raise TypeError("'%s' is not instantiatable" % cls.__name__) | 251 raise TypeError("'%s' is not instantiatable" % cls.__name__) |
252 | 252 |
253 @staticmethod | 253 @staticmethod |
254 def _parsedecl(spec): | 254 def _parse(spec): |
255 """Parse an alias name and arguments""" | 255 """Parse an alias name, arguments and definition""" |
256 raise NotImplementedError | |
257 | |
258 @staticmethod | |
259 def _parsedefn(spec): | |
260 """Parse an alias definition""" | |
261 raise NotImplementedError | 256 raise NotImplementedError |
262 | 257 |
263 @staticmethod | 258 @staticmethod |
264 def _getlist(tree): | 259 def _getlist(tree): |
265 """Extract a list of arguments from parsed tree""" | 260 """Extract a list of arguments from parsed tree""" |
268 @classmethod | 263 @classmethod |
269 def _builddecl(cls, decl): | 264 def _builddecl(cls, decl): |
270 """Parse an alias declaration into ``(name, tree, args, errorstr)`` | 265 """Parse an alias declaration into ``(name, tree, args, errorstr)`` |
271 | 266 |
272 This function analyzes the parsed tree. The parsing rule is provided | 267 This function analyzes the parsed tree. The parsing rule is provided |
273 by ``_parsedecl()``. | 268 by ``_parse()``. |
274 | 269 |
275 - ``name``: of declared alias (may be ``decl`` itself at error) | 270 - ``name``: of declared alias (may be ``decl`` itself at error) |
276 - ``tree``: parse result (or ``None`` at error) | 271 - ``tree``: parse result (or ``None`` at error) |
277 - ``args``: list of argument names (or None for symbol declaration) | 272 - ``args``: list of argument names (or None for symbol declaration) |
278 - ``errorstr``: detail about detected error (or None) | 273 - ``errorstr``: detail about detected error (or None) |
309 ... return [] | 304 ... return [] |
310 ... if tree[0] == 'list': | 305 ... if tree[0] == 'list': |
311 ... return list(tree[1:]) | 306 ... return list(tree[1:]) |
312 ... return [tree] | 307 ... return [tree] |
313 >>> class aliasrules(basealiasrules): | 308 >>> class aliasrules(basealiasrules): |
314 ... _parsedecl = staticmethod(parse) | 309 ... _parse = staticmethod(parse) |
315 ... _getlist = staticmethod(getlist) | 310 ... _getlist = staticmethod(getlist) |
316 >>> builddecl = aliasrules._builddecl | 311 >>> builddecl = aliasrules._builddecl |
317 >>> builddecl('foo') | 312 >>> builddecl('foo') |
318 ('foo', ('symbol', 'foo'), None, None) | 313 ('foo', ('symbol', 'foo'), None, None) |
319 >>> builddecl('$foo') | 314 >>> builddecl('$foo') |
340 ('foo("bar', None, None, 'at 5: unterminated string') | 335 ('foo("bar', None, None, 'at 5: unterminated string') |
341 >>> builddecl('foo($1, $2, $1)') | 336 >>> builddecl('foo($1, $2, $1)') |
342 ('foo', None, None, 'argument names collide with each other') | 337 ('foo', None, None, 'argument names collide with each other') |
343 """ | 338 """ |
344 try: | 339 try: |
345 tree = cls._parsedecl(decl) | 340 tree = cls._parse(decl) |
346 except error.ParseError as inst: | 341 except error.ParseError as inst: |
347 return (decl, None, None, parseerrordetail(inst)) | 342 return (decl, None, None, parseerrordetail(inst)) |
348 | 343 |
349 if tree[0] == cls._symbolnode: | 344 if tree[0] == cls._symbolnode: |
350 # "name = ...." style | 345 # "name = ...." style |
390 @classmethod | 385 @classmethod |
391 def _builddefn(cls, defn, args): | 386 def _builddefn(cls, defn, args): |
392 """Parse an alias definition into a tree and marks substitutions | 387 """Parse an alias definition into a tree and marks substitutions |
393 | 388 |
394 This function marks alias argument references as ``_aliasarg``. The | 389 This function marks alias argument references as ``_aliasarg``. The |
395 parsing rule is provided by ``_parsedefn()``. | 390 parsing rule is provided by ``_parse()``. |
396 | 391 |
397 ``args`` is a list of alias argument names, or None if the alias | 392 ``args`` is a list of alias argument names, or None if the alias |
398 is declared as a symbol. | 393 is declared as a symbol. |
399 | 394 |
400 >>> parsemap = { | 395 >>> parsemap = { |
402 ... '$1 or $bar': ('or', ('symbol', '$1'), ('symbol', '$bar')), | 397 ... '$1 or $bar': ('or', ('symbol', '$1'), ('symbol', '$bar')), |
403 ... '$10 or baz': ('or', ('symbol', '$10'), ('symbol', 'baz')), | 398 ... '$10 or baz': ('or', ('symbol', '$10'), ('symbol', 'baz')), |
404 ... '"$1" or "foo"': ('or', ('string', '$1'), ('string', 'foo')), | 399 ... '"$1" or "foo"': ('or', ('string', '$1'), ('string', 'foo')), |
405 ... } | 400 ... } |
406 >>> class aliasrules(basealiasrules): | 401 >>> class aliasrules(basealiasrules): |
407 ... _parsedefn = staticmethod(parsemap.__getitem__) | 402 ... _parse = staticmethod(parsemap.__getitem__) |
408 ... _getlist = staticmethod(lambda x: []) | 403 ... _getlist = staticmethod(lambda x: []) |
409 >>> builddefn = aliasrules._builddefn | 404 >>> builddefn = aliasrules._builddefn |
410 >>> def pprint(tree): | 405 >>> def pprint(tree): |
411 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol')) | 406 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol')) |
412 >>> args = ['$1', '$2', 'foo'] | 407 >>> args = ['$1', '$2', 'foo'] |
427 >>> pprint(builddefn('"$1" or "foo"', args)) | 422 >>> pprint(builddefn('"$1" or "foo"', args)) |
428 (or | 423 (or |
429 ('string', '$1') | 424 ('string', '$1') |
430 ('string', 'foo')) | 425 ('string', 'foo')) |
431 """ | 426 """ |
432 tree = cls._parsedefn(defn) | 427 tree = cls._parse(defn) |
433 if args: | 428 if args: |
434 args = set(args) | 429 args = set(args) |
435 else: | 430 else: |
436 args = set() | 431 args = set() |
437 return cls._relabelargs(tree, args) | 432 return cls._relabelargs(tree, args) |