Patchwork [2,of,7,V2] parser: add stub class that will host alias parsing and expansion

mail settings
Submitter Yuya Nishihara
Date April 2, 2016, 8:30 a.m.
Message ID <cc42f3a9895fe3d2922e.1459585817@mimosa>
Download mbox | patch
Permalink /patch/14249/
State Superseded
Headers show


Yuya Nishihara - April 2, 2016, 8:30 a.m.
# HG changeset patch
# User Yuya Nishihara <>
# Date 1456734174 -32400
#      Mon Feb 29 17:22:54 2016 +0900
# Node ID cc42f3a9895fe3d2922e07d44483051a4b7b90da
# Parent  e2db714a290c5ae731b542011a33961bd631968a
parser: add stub class that will host alias parsing and expansion

This class will keep syntax rules that are necessary to parse and expand
aliases. The implementations will be extracted from the revset module. In
order to make the porting easier, this class keeps parsedecl and parsedefn
separately, which will be unified later. Also, getlist and funcnode will
be refactored by future patches for better handling of the template aliases.

The following public functions will be added:, defn) -> aliasobj
    parse decl and defn into an object that keeps alias name, arguments
    and replacement tree.
  rules.buildmap(aliasitems) -> aliasdict
    helper to build() a dict of alias objects from a list of (decl, defn)
  rules.expand(aliasdict, tree) -> tree
    expand aliases in tree recursively

Because these functions aren't introduced by this series, there would remain
a couple of wrapper functions in the revset module. These ugly wrappers
should be eliminated by the next series.

I could design the aliasrules class as an abstract base class, but I decided
not to. If it was an abstract class, its instance would have no state at all
since all customization would be made statically. So there would be weaker
motivation to make it a class. I'm not a big fan of using class as sugar, so
I didn't.

  class revsetaliasrules(aliasrules):
      def __init__(self):
          # no variable

      def _getlist(self, tree):
          return getlist(tree)

      def _parsedecl(self, decl):
          return _parse(decl)


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -228,3 +228,29 @@  def parseerrordetail(inst):
         return _('at %s: %s') % (inst.args[1], inst.args[0])
         return inst.args[0]
+class aliasrules(object):
+    """Parsing and expansion rule set of aliases
+    This is a helper for fileset/revset/template aliases. It supports alias
+    expansion of symbol and funciton-call styles::
+        # decl = defn
+        h = heads(default)
+        b($1) = ancestors($1) - ancestors(default)
+    - ``section`` is typically a config section name, which will be included
+      in error messages
+    - ``parsedecl(spec)`` parses an alias name and arguments
+    - ``parsedefn(spec)`` parses an alias definition
+    - ``getlist(tree)`` extracts a list of arguments from parsed tree
+    """
+    def __init__(self, section, parsedecl, parsedefn, getlist,
+                 symbolnode='symbol', funcnode='func'):
+        self._section = section
+        self._parsedecl = parsedecl
+        self._parsedefn = parsedefn
+        self._getlist = getlist
+        self._symbolnode = symbolnode
+        self._funcnode = funcnode