Patchwork [1,of,5] parser: add helper function that constructs parsed tree from template

login
register
mail settings
Submitter Yuya Nishihara
Date Aug. 31, 2017, 2:42 p.m.
Message ID <1d58bfbb617075b997d4.1504190530@mimosa>
Download mbox | patch
Permalink /patch/23534/
State Accepted
Headers show

Comments

Yuya Nishihara - Aug. 31, 2017, 2:42 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1455712204 -32400
#      Wed Feb 17 21:30:04 2016 +0900
# Node ID 1d58bfbb617075b997d4b0a41924fcaee648b32f
# Parent  31a2eb0f74e59327c0e1b49ee848c126993a29dc
parser: add helper function that constructs parsed tree from template

This function will be used as follows:

  build('only(_, _)', x, y)

See the next patch for details.

Patch

diff --git a/mercurial/parser.py b/mercurial/parser.py
--- a/mercurial/parser.py
+++ b/mercurial/parser.py
@@ -285,6 +285,33 @@  def simplifyinfixops(tree, targetnodes):
     simplified.append(op)
     return tuple(reversed(simplified))
 
+def _buildtree(template, placeholder, replstack):
+    if template == placeholder:
+        return replstack.pop()
+    if not isinstance(template, tuple):
+        return template
+    return tuple(_buildtree(x, placeholder, replstack) for x in template)
+
+def buildtree(template, placeholder, *repls):
+    """Create new tree by substituting placeholders by replacements
+
+    >>> _ = ('symbol', '_')
+    >>> def f(template, *repls):
+    ...     return buildtree(template, _, *repls)
+    >>> f(('func', ('symbol', 'only'), ('list', _, _)),
+    ...   ('symbol', '1'), ('symbol', '2'))
+    ('func', ('symbol', 'only'), ('list', ('symbol', '1'), ('symbol', '2')))
+    >>> f(('and', _, ('not', _)), ('symbol', '1'), ('symbol', '2'))
+    ('and', ('symbol', '1'), ('not', ('symbol', '2')))
+    """
+    if not isinstance(placeholder, tuple):
+        raise error.ProgrammingError('placeholder must be a node tuple')
+    replstack = list(reversed(repls))
+    r = _buildtree(template, placeholder, replstack)
+    if replstack:
+        raise error.ProgrammingError('too many replacements')
+    return r
+
 def parseerrordetail(inst):
     """Compose error message from specified ParseError object
     """