Mercurial > hg
changeset 34045:79681d8ee587
parser: add helper function to test if pattern matches parsed tree
This function will be used as follows:
match('ancestors(_) and not ancestors(_)', x)
See the next patch for details.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Wed, 17 Feb 2016 21:31:09 +0900 |
parents | b862e6fca7ac |
children | f23cbca9b277 |
files | mercurial/parser.py |
diffstat | 1 files changed, 53 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/parser.py Wed Feb 17 21:38:25 2016 +0900 +++ b/mercurial/parser.py Wed Feb 17 21:31:09 2016 +0900 @@ -312,6 +312,59 @@ raise error.ProgrammingError('too many replacements') return r +def _matchtree(pattern, tree, placeholder, incompletenodes, matches): + if pattern == tree: + return True + if not isinstance(pattern, tuple) or not isinstance(tree, tuple): + return False + if pattern == placeholder and tree[0] not in incompletenodes: + matches.append(tree) + return True + if len(pattern) != len(tree): + return False + return all(_matchtree(p, x, placeholder, incompletenodes, matches) + for p, x in zip(pattern, tree)) + +def matchtree(pattern, tree, placeholder=None, incompletenodes=()): + """If a tree matches the pattern, return a list of the tree and nodes + matched with the placeholder; Otherwise None + + >>> def f(pattern, tree): + ... m = matchtree(pattern, tree, _, {'keyvalue', 'list'}) + ... if m: + ... return m[1:] + + >>> _ = ('symbol', '_') + >>> f(('func', ('symbol', 'ancestors'), _), + ... ('func', ('symbol', 'ancestors'), ('symbol', '1'))) + [('symbol', '1')] + >>> f(('func', ('symbol', 'ancestors'), _), + ... ('func', ('symbol', 'ancestors'), None)) + >>> f(('range', ('dagrange', _, _), _), + ... ('range', + ... ('dagrange', ('symbol', '1'), ('symbol', '2')), + ... ('symbol', '3'))) + [('symbol', '1'), ('symbol', '2'), ('symbol', '3')] + + The placeholder does not match the specified incomplete nodes because + an incomplete node (e.g. argument list) cannot construct an expression. + + >>> f(('func', ('symbol', 'ancestors'), _), + ... ('func', ('symbol', 'ancestors'), + ... ('list', ('symbol', '1'), ('symbol', '2')))) + + The placeholder may be omitted, but which shouldn't match a None node. + + >>> _ = None + >>> f(('func', ('symbol', 'ancestors'), None), + ... ('func', ('symbol', 'ancestors'), ('symbol', '0'))) + """ + if placeholder is not None and not isinstance(placeholder, tuple): + raise error.ProgrammingError('placeholder must be a node tuple') + matches = [tree] + if _matchtree(pattern, tree, placeholder, incompletenodes, matches): + return matches + def parseerrordetail(inst): """Compose error message from specified ParseError object """