Because a suffix action never takes subsequent tokens, it should have
no binding strength nor closing character. I've tried if this value could
be used to resolve infix/suffix ambiguity of x^:y, but it appears not. So
I decided to resend this patch.
This provides a customization point for templater. In templater, there are
two ways to call a unary function: func(x) and x|func. They are processed
differently in templater due to historical reasons, but they should be
handled in the same way while expanding aliases. In short, x|func should be
processed as syntactic sugar for func(x).
_funcnode and _getlist() are replaced by _trygetfunc().
Since _getalias() explicitly tests the type and name of the pattern tree, we
don't need to compare "a.tree == tree" for 'symbol', and "a.tree == tree[:2]"
for 'func', where tree is either ('symbol', name) or ('func', ('symbol', name)).
This change helps implementing better handling of template aliases. See the
subsequent patches for details.
The alias.tree field is removed as it is no longer used.
They will be commonly used by revset and templater. It isn't easy to understand
how _expand() works, so I'll add comments by a follow-up patch.
The local variable 'alias' is renamed to 'a' to avoid shadowing the global
'alias' class.
It was odd that the revsetalias did the whole parsing stuff in __init__().
Instead, this patch adds a factory function to the aliasrules class, and
makes the alias (= revsetalias) class a plain-old value object.
The original _parsealiasdefn() function is split into common _builddefn()
and revset-specific _parsealiasdefn(). revset._relabelaliasargs() is removed
as it is no longer used.
The doctests are ported by using the dummy parse().
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().
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:
aliasrules.build(decl, defn) -> aliasobj
parse decl and defn into an object that keeps alias name, arguments
and replacement tree.
aliasrules.buildmap(aliasitems) -> aliasdict
helper to build() a dict of alias objects from a list of (decl, defn)
aliasrules.expand(aliasdict, tree) -> tree
expand aliases in tree recursively
Because these functions aren't introduced by this series, there would remain
a few wrapper functions in the revset module. These ugly wrappers should be
eliminated by the next series.
This class is considered an inheritable namespace, which will host only
class/static methods. That's because it won't have no object-scope variables.
I'm not a big fan of using class as a syntax sugar, but I admit it can improve
code readability at some level. So let's give it a try.
If no infix action is defined, a suffix action isn't ambiguous, so it should
be taken no matter if the next token can be an operand. This is exactly the
same flow as prefix/primary handling.
This change has no effect now because all suffix tokens have infix actions.
If both actions are defined, a primary-expression action is accepted only if
the next token never starts new term. For example,
parsed as primary expression:
":" # next token 'end' has no action
"(:)" # next token ')' has no action
":+y" # next token '+' is infix operator
parsed as prefix operator:
":y" # next token 'y' is primary expression
":-y" # next token '-' is prefix operator
This is mostly the same resolution as the infix/suffix rules.
This will allow us to define both a primary expression, ":", and a prefix
operator, ":y". The ambiguity will be resolved by the next patch.
Prefix actions in elements table are adjusted as follows:
original prefix primary prefix
----------------- -------- -----------------
("group", 1, ")") -> n/a ("group", 1, ")")
("negate", 19) -> n/a ("negate", 19)
("symbol",) -> "symbol" n/a
Future patches will separate primary expression and prefix operator actions.
This function will be used to resolve ambiguity of them.
This is a step to remove the old-style revexpr parser. We need both ":" and
":y" operators for backward compatibility.
Keyword arguments will be convenient for functions that will take more than
one optional or boolean flags. For example,
file(pattern[, subrepos=false])
subrepo([[pattern], status])
Because I don't think all functions should accept key=value syntax, getkwargs()
does not support variadic functions such as 'ancestor(*changeset)'.
The core logic is placed in the parser module because keyword arguments will
be more useful in the templater, where functions take more options. Test cases
will be added by the next patch.
This can simplify the interface of parse() function. Our tokenizer tends to
have optional arguments other than the message to be parsed.
Before this patch, the "lookup" argument existed only for the revset, and the
templater had to pack [program, start, end] to be passed to its tokenizer.
This get rid of another StopIteration abomination. The change in self.current
value is supposed to not matter as nobody should be calling '_advance' after
that (as per Matt wisdom).