annotate mercurial/parser.py @ 31553:56acc4250900

scmutil: add a simple key-value file helper The purpose of the added class is to serve purposes like save files of shelve or state files of shelve, rebase and histedit. Keys of these files can be alphanumeric and start with letters, while values must not contain newlines. In light of Mercurial's reluctancy to use Python's json module, this tries to provide a reasonable alternative for a non-nested named data. Comparing to current approach of storing state in plain text files, where semantic meaning of lines of text is only determined by their oreder, simple key-value file allows for reordering lines and thus helps handle optional values. Initial use-case I see for this is obs-shelve's shelve files. Later we can possibly migrate state files to this approach. The test is in a new file beause I did not figure out where to put it within existing test suite. If you give me a better idea, I will gladly follow it.
author Kostia Balytskyi <ikostia@fb.com>
date Fri, 10 Mar 2017 14:33:42 -0800
parents afb335353d28
children a98540ea1e42
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # parser.py - simple top-down operator precedence parser for mercurial
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
11449
05af334bac05 parser: fix URL to effbot
Julian Cowley <julian@lava.net>
parents: 11412
diff changeset
8 # see http://effbot.org/zone/simple-top-down-parsing.htm and
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
9 # http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
10 # for background
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
12 # takes a tokenizer and elements
25655
b8b73652c1c9 parser: update documentation about tokenizer and elements
Yuya Nishihara <yuya@tcha.org>
parents: 25654
diff changeset
13 # tokenizer is an iterator that returns (type, value, pos) tuples
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
14 # elements is a mapping of types to binding strength, primary, prefix, infix
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
15 # and suffix actions
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
16 # an action is a tree node name, a tree label, and an optional match
17500
8ac8db8dc346 en-us: labeled
timeless@mozdev.org
parents: 14701
diff changeset
17 # __call__(program) parses program into a labeled tree
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
18
25963
7448df709b2e parser: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25818
diff changeset
19 from __future__ import absolute_import
7448df709b2e parser: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25818
diff changeset
20
7448df709b2e parser: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25818
diff changeset
21 from .i18n import _
31484
afb335353d28 util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 31353
diff changeset
22 from . import (
afb335353d28 util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 31353
diff changeset
23 error,
afb335353d28 util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 31353
diff changeset
24 util,
afb335353d28 util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 31353
diff changeset
25 )
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
26
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 class parser(object):
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
28 def __init__(self, elements, methods=None):
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29 self._elements = elements
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
30 self._methods = methods
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 11449
diff changeset
31 self.current = None
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
32 def _advance(self):
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
33 'advance the tokenizer'
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
34 t = self.current
25171
d647f97f88dd parsers: use 'next' instead of try/except
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20778
diff changeset
35 self.current = next(self._iter, None)
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
36 return t
25804
f0a77cb6316a parser: extract function that tests if next token may start new term
Yuya Nishihara <yuya@tcha.org>
parents: 25803
diff changeset
37 def _hasnewterm(self):
f0a77cb6316a parser: extract function that tests if next token may start new term
Yuya Nishihara <yuya@tcha.org>
parents: 25803
diff changeset
38 'True if next token may start new term'
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
39 return any(self._elements[self.current[0]][1:3])
25802
cc741c76b26a parser: remove unused parameter 'pos' from _match()
Yuya Nishihara <yuya@tcha.org>
parents: 25801
diff changeset
40 def _match(self, m):
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
41 'make sure the tokenizer matches an end condition'
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
42 if self.current[0] != m:
14701
4b93bd041772 parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents: 13665
diff changeset
43 raise error.ParseError(_("unexpected token: %s") % self.current[0],
11305
d4cafcb63f77 cleanups: undefined variables
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 11289
diff changeset
44 self.current[2])
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
45 self._advance()
25803
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
46 def _parseoperand(self, bind, m=None):
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
47 'gather right-hand-side operand until an end condition or binding met'
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
48 if m and self.current[0] == m:
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
49 expr = None
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
50 else:
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
51 expr = self._parse(bind)
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
52 if m:
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
53 self._match(m)
b3004d273874 parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents: 25802
diff changeset
54 return expr
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
55 def _parse(self, bind=0):
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
56 token, value, pos = self._advance()
25816
43a8a87fc175 parser: resolve ambiguity where both prefix and primary actions are defined
Yuya Nishihara <yuya@tcha.org>
parents: 25815
diff changeset
57 # handle prefix rules on current token, take as primary if unambiguous
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
58 primary, prefix = self._elements[token][1:3]
25816
43a8a87fc175 parser: resolve ambiguity where both prefix and primary actions are defined
Yuya Nishihara <yuya@tcha.org>
parents: 25815
diff changeset
59 if primary and not (prefix and self._hasnewterm()):
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
60 expr = (primary, value)
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
61 elif prefix:
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
62 expr = (prefix[0], self._parseoperand(*prefix[1:]))
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
63 else:
14701
4b93bd041772 parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents: 13665
diff changeset
64 raise error.ParseError(_("not a prefix: %s") % token, pos)
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
65 # gather tokens until we meet a lower binding strength
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
66 while bind < self._elements[self.current[0]][0]:
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
67 token, value, pos = self._advance()
25817
42ac9d1d1572 parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents: 25816
diff changeset
68 # handle infix rules, take as suffix if unambiguous
25815
e71e5629e006 parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents: 25804
diff changeset
69 infix, suffix = self._elements[token][3:]
25818
455190fb4e51 parser: take suffix action if no infix action is defined
Yuya Nishihara <yuya@tcha.org>
parents: 25817
diff changeset
70 if suffix and not (infix and self._hasnewterm()):
29767
e5b794063fd4 parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents: 29059
diff changeset
71 expr = (suffix, expr)
25817
42ac9d1d1572 parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents: 25816
diff changeset
72 elif infix:
42ac9d1d1572 parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents: 25816
diff changeset
73 expr = (infix[0], expr, self._parseoperand(*infix[1:]))
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
74 else:
25817
42ac9d1d1572 parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents: 25816
diff changeset
75 raise error.ParseError(_("not an infix: %s") % token, pos)
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
76 return expr
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
77 def parse(self, tokeniter):
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
78 'generate a parse tree from tokens'
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
79 self._iter = tokeniter
13176
895f54a79c6e templater: use the parser.py parser to extend the templater syntax
Matt Mackall <mpm@selenic.com>
parents: 11449
diff changeset
80 self._advance()
13665
e798e430c5e5 revset: report a parse error if a revset is not parsed completely (issue2654)
Bernhard Leiner <bleiner@gmail.com>
parents: 13176
diff changeset
81 res = self._parse()
e798e430c5e5 revset: report a parse error if a revset is not parsed completely (issue2654)
Bernhard Leiner <bleiner@gmail.com>
parents: 13176
diff changeset
82 token, value, pos = self.current
e798e430c5e5 revset: report a parse error if a revset is not parsed completely (issue2654)
Bernhard Leiner <bleiner@gmail.com>
parents: 13176
diff changeset
83 return res, pos
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
84 def eval(self, tree):
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
85 'recursively evaluate a parse tree using node methods'
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
86 if not isinstance(tree, tuple):
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 return tree
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
88 return self._methods[tree[0]](*[self.eval(t) for t in tree[1:]])
25654
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
89 def __call__(self, tokeniter):
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
90 'parse tokens into a parse tree and evaluate if methods given'
af329a84310c parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents: 25306
diff changeset
91 t = self.parse(tokeniter)
11274
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92 if self._methods:
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
93 return self.eval(t)
77272d28b53f revset: introduce basic parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94 return t
25253
3f1a9b44b8c2 parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 25171
diff changeset
95
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
96 def splitargspec(spec):
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
97 """Parse spec of function arguments into (poskeys, varkey, keys)
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
98
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
99 >>> splitargspec('')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
100 ([], None, [])
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
101 >>> splitargspec('foo bar')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
102 ([], None, ['foo', 'bar'])
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
103 >>> splitargspec('foo *bar baz')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
104 (['foo'], 'bar', ['baz'])
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
105 >>> splitargspec('*foo')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
106 ([], 'foo', [])
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
107 """
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
108 pre, sep, post = spec.partition('*')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
109 pres = pre.split()
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
110 posts = post.split()
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
111 if sep:
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
112 if not posts:
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
113 raise error.ProgrammingError('no *varkey name provided')
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
114 return pres, posts[0], posts[1:]
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
115 return [], None, pres
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
116
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
117 def buildargsdict(trees, funcname, argspec, keyvaluenode, keynode):
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
118 """Build dict from list containing positional and keyword arguments
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
119
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
120 Arguments are specified by a tuple of ``(poskeys, varkey, keys)`` where
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
121
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
122 - ``poskeys``: list of names of positional arguments
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
123 - ``varkey``: optional argument name that takes up remainder
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
124 - ``keys``: list of names that can be either positional or keyword arguments
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
125
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
126 If ``varkey`` specified, all ``keys`` must be given as keyword arguments.
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
127
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
128 Invalid keywords, too few positional arguments, or too many positional
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
129 arguments are rejected, but missing keyword arguments are just omitted.
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
130 """
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
131 poskeys, varkey, keys = argspec
30752
ffd324eaf994 parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents: 30332
diff changeset
132 kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode),
ffd324eaf994 parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents: 30332
diff changeset
133 len(trees))
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
134 if kwstart < len(poskeys):
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
135 raise error.ParseError(_("%(func)s takes at least %(nargs)d positional "
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
136 "arguments")
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
137 % {'func': funcname, 'nargs': len(poskeys)})
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
138 if not varkey and len(trees) > len(poskeys) + len(keys):
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
139 raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments")
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
140 % {'func': funcname,
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
141 'nargs': len(poskeys) + len(keys)})
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
142 args = {}
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
143 # consume positional arguments
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
144 for k, x in zip(poskeys, trees[:kwstart]):
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
145 args[k] = x
30753
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
146 if varkey:
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
147 args[varkey] = trees[len(args):kwstart]
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
148 else:
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
149 for k, x in zip(keys, trees[len(args):kwstart]):
c3a3896a9fa8 parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents: 30752
diff changeset
150 args[k] = x
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
151 # remainder should be keyword arguments
30752
ffd324eaf994 parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents: 30332
diff changeset
152 for x in trees[kwstart:]:
25705
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
153 if x[0] != keyvaluenode or x[1][0] != keynode:
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
154 raise error.ParseError(_("%(func)s got an invalid argument")
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
155 % {'func': funcname})
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
156 k = x[1][1]
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
157 if k not in keys:
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
158 raise error.ParseError(_("%(func)s got an unexpected keyword "
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
159 "argument '%(key)s'")
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
160 % {'func': funcname, 'key': k})
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
161 if k in args:
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
162 raise error.ParseError(_("%(func)s got multiple values for keyword "
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
163 "argument '%(key)s'")
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
164 % {'func': funcname, 'key': k})
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
165 args[k] = x[2]
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
166 return args
48919d246a47 revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents: 25655
diff changeset
167
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
168 def unescapestr(s):
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
169 try:
31484
afb335353d28 util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents: 31353
diff changeset
170 return util.unescapestr(s)
26231
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
171 except ValueError as e:
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
172 # mangle Python's exception into our format
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
173 raise error.ParseError(str(e).lower())
87c9c562c37a parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents: 25963
diff changeset
174
25254
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
175 def _prettyformat(tree, leafnodes, level, lines):
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
176 if not isinstance(tree, tuple) or tree[0] in leafnodes:
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
177 lines.append((level, str(tree)))
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
178 else:
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
179 lines.append((level, '(%s' % tree[0]))
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
180 for s in tree[1:]:
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
181 _prettyformat(s, leafnodes, level + 1, lines)
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
182 lines[-1:] = [(lines[-1][0], lines[-1][1] + ')')]
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
183
25253
3f1a9b44b8c2 parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 25171
diff changeset
184 def prettyformat(tree, leafnodes):
3f1a9b44b8c2 parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 25171
diff changeset
185 lines = []
25254
060bdfef2517 parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents: 25253
diff changeset
186 _prettyformat(tree, leafnodes, 0, lines)
25253
3f1a9b44b8c2 parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 25171
diff changeset
187 output = '\n'.join((' ' * l + s) for l, s in lines)
3f1a9b44b8c2 parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 25171
diff changeset
188 return output
25306
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
189
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
190 def simplifyinfixops(tree, targetnodes):
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
191 """Flatten chained infix operations to reduce usage of Python stack
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
192
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
193 >>> def f(tree):
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
194 ... print prettyformat(simplifyinfixops(tree, ('or',)), ('symbol',))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
195 >>> f(('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
196 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
197 ... ('symbol', '1'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
198 ... ('symbol', '2')),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
199 ... ('symbol', '3')))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
200 (or
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
201 ('symbol', '1')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
202 ('symbol', '2')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
203 ('symbol', '3'))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
204 >>> f(('func',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
205 ... ('symbol', 'p1'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
206 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
207 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
208 ... ('func',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
209 ... ('symbol', 'sort'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
210 ... ('list',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
211 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
212 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
213 ... ('symbol', '1'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
214 ... ('symbol', '2')),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
215 ... ('symbol', '3')),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
216 ... ('negate',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
217 ... ('symbol', 'rev')))),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
218 ... ('and',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
219 ... ('symbol', '4'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
220 ... ('group',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
221 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
222 ... ('or',
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
223 ... ('symbol', '5'),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
224 ... ('symbol', '6')),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
225 ... ('symbol', '7'))))),
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
226 ... ('symbol', '8'))))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
227 (func
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
228 ('symbol', 'p1')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
229 (or
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
230 (func
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
231 ('symbol', 'sort')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
232 (list
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
233 (or
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
234 ('symbol', '1')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
235 ('symbol', '2')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
236 ('symbol', '3'))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
237 (negate
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
238 ('symbol', 'rev'))))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
239 (and
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
240 ('symbol', '4')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
241 (group
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
242 (or
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
243 ('symbol', '5')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
244 ('symbol', '6')
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
245 ('symbol', '7'))))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
246 ('symbol', '8')))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
247 """
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
248 if not isinstance(tree, tuple):
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
249 return tree
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
250 op = tree[0]
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
251 if op not in targetnodes:
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
252 return (op,) + tuple(simplifyinfixops(x, targetnodes) for x in tree[1:])
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
253
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
254 # walk down left nodes taking each right node. no recursion to left nodes
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
255 # because infix operators are left-associative, i.e. left tree is deep.
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
256 # e.g. '1 + 2 + 3' -> (+ (+ 1 2) 3) -> (+ 1 2 3)
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
257 simplified = []
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
258 x = tree
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
259 while x[0] == op:
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
260 l, r = x[1:]
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
261 simplified.append(simplifyinfixops(r, targetnodes))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
262 x = l
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
263 simplified.append(simplifyinfixops(x, targetnodes))
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
264 simplified.append(op)
c87b05925054 parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents: 25254
diff changeset
265 return tuple(reversed(simplified))
28720
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
266
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
267 def parseerrordetail(inst):
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
268 """Compose error message from specified ParseError object
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
269 """
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
270 if len(inst.args) > 1:
31353
089e37802fb3 parser: use %d instead of %s for interpolating error position
Augie Fackler <augie@google.com>
parents: 30753
diff changeset
271 return _('at %d: %s') % (inst.args[1], inst.args[0])
28720
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
272 else:
639e0f1e8ffa parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents: 26231
diff changeset
273 return inst.args[0]
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
274
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
275 class alias(object):
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
276 """Parsed result of alias"""
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
277
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
278 def __init__(self, name, args, err, replacement):
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
279 self.name = name
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
280 self.args = args
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
281 self.error = err
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
282 self.replacement = replacement
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
283 # whether own `error` information is already shown or not.
28898
8d398155bfda revset: rename findaliases() to expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents: 28897
diff changeset
284 # this avoids showing same warning multiple times at each
8d398155bfda revset: rename findaliases() to expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents: 28897
diff changeset
285 # `expandaliases`.
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
286 self.warned = False
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
287
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
288 class basealiasrules(object):
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
289 """Parsing and expansion rule set of aliases
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
290
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
291 This is a helper for fileset/revset/template aliases. A concrete rule set
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
292 should be made by sub-classing this and implementing class/static methods.
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
293
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 29767
diff changeset
294 It supports alias expansion of symbol and function-call styles::
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
295
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
296 # decl = defn
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
297 h = heads(default)
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
298 b($1) = ancestors($1) - ancestors(default)
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
299 """
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
300 # typically a config section, which will be included in error messages
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
301 _section = None
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
302 # tag of symbol node
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
303 _symbolnode = 'symbol'
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
304
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
305 def __new__(cls):
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
306 raise TypeError("'%s' is not instantiatable" % cls.__name__)
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
307
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
308 @staticmethod
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
309 def _parse(spec):
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
310 """Parse an alias name, arguments and definition"""
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
311 raise NotImplementedError
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
312
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
313 @staticmethod
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
314 def _trygetfunc(tree):
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
315 """Return (name, args) if tree is a function; otherwise None"""
28870
475dad3432fd parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents: 28720
diff changeset
316 raise NotImplementedError
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
317
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
318 @classmethod
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
319 def _builddecl(cls, decl):
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
320 """Parse an alias declaration into ``(name, args, errorstr)``
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
321
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
322 This function analyzes the parsed tree. The parsing rule is provided
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
323 by ``_parse()``.
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
324
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
325 - ``name``: of declared alias (may be ``decl`` itself at error)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
326 - ``args``: list of argument names (or None for symbol declaration)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
327 - ``errorstr``: detail about detected error (or None)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
328
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
329 >>> sym = lambda x: ('symbol', x)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
330 >>> symlist = lambda *xs: ('list',) + tuple(sym(x) for x in xs)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
331 >>> func = lambda n, a: ('func', sym(n), a)
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
332 >>> parsemap = {
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
333 ... 'foo': sym('foo'),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
334 ... '$foo': sym('$foo'),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
335 ... 'foo::bar': ('dagrange', sym('foo'), sym('bar')),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
336 ... 'foo()': func('foo', None),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
337 ... '$foo()': func('$foo', None),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
338 ... 'foo($1, $2)': func('foo', symlist('$1', '$2')),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
339 ... 'foo(bar_bar, baz.baz)':
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
340 ... func('foo', symlist('bar_bar', 'baz.baz')),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
341 ... 'foo(bar($1, $2))':
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
342 ... func('foo', func('bar', symlist('$1', '$2'))),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
343 ... 'foo($1, $2, nested($1, $2))':
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
344 ... func('foo', (symlist('$1', '$2') +
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
345 ... (func('nested', symlist('$1', '$2')),))),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
346 ... 'foo("bar")': func('foo', ('string', 'bar')),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
347 ... 'foo($1, $2': error.ParseError('unexpected token: end', 10),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
348 ... 'foo("bar': error.ParseError('unterminated string', 5),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
349 ... 'foo($1, $2, $1)': func('foo', symlist('$1', '$2', '$1')),
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
350 ... }
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
351 >>> def parse(expr):
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
352 ... x = parsemap[expr]
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
353 ... if isinstance(x, Exception):
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
354 ... raise x
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
355 ... return x
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
356 >>> def trygetfunc(tree):
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
357 ... if not tree or tree[0] != 'func' or tree[1][0] != 'symbol':
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
358 ... return None
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
359 ... if not tree[2]:
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
360 ... return tree[1][1], []
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
361 ... if tree[2][0] == 'list':
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
362 ... return tree[1][1], list(tree[2][1:])
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
363 ... return tree[1][1], [tree[2]]
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
364 >>> class aliasrules(basealiasrules):
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
365 ... _parse = staticmethod(parse)
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
366 ... _trygetfunc = staticmethod(trygetfunc)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
367 >>> builddecl = aliasrules._builddecl
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
368 >>> builddecl('foo')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
369 ('foo', None, None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
370 >>> builddecl('$foo')
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
371 ('$foo', None, "invalid symbol '$foo'")
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
372 >>> builddecl('foo::bar')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
373 ('foo::bar', None, 'invalid format')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
374 >>> builddecl('foo()')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
375 ('foo', [], None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
376 >>> builddecl('$foo()')
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
377 ('$foo()', None, "invalid function '$foo'")
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
378 >>> builddecl('foo($1, $2)')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
379 ('foo', ['$1', '$2'], None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
380 >>> builddecl('foo(bar_bar, baz.baz)')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
381 ('foo', ['bar_bar', 'baz.baz'], None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
382 >>> builddecl('foo($1, $2, nested($1, $2))')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
383 ('foo($1, $2, nested($1, $2))', None, 'invalid argument list')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
384 >>> builddecl('foo(bar($1, $2))')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
385 ('foo(bar($1, $2))', None, 'invalid argument list')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
386 >>> builddecl('foo("bar")')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
387 ('foo("bar")', None, 'invalid argument list')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
388 >>> builddecl('foo($1, $2')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
389 ('foo($1, $2', None, 'at 10: unexpected token: end')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
390 >>> builddecl('foo("bar')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
391 ('foo("bar', None, 'at 5: unterminated string')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
392 >>> builddecl('foo($1, $2, $1)')
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
393 ('foo', None, 'argument names collide with each other')
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
394 """
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
395 try:
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
396 tree = cls._parse(decl)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
397 except error.ParseError as inst:
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
398 return (decl, None, parseerrordetail(inst))
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
399
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
400 if tree[0] == cls._symbolnode:
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
401 # "name = ...." style
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
402 name = tree[1]
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
403 if name.startswith('$'):
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
404 return (decl, None, _("invalid symbol '%s'") % name)
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
405 return (name, None, None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
406
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
407 func = cls._trygetfunc(tree)
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
408 if func:
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
409 # "name(arg, ....) = ...." style
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
410 name, args = func
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
411 if name.startswith('$'):
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
412 return (decl, None, _("invalid function '%s'") % name)
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
413 if any(t[0] != cls._symbolnode for t in args):
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
414 return (decl, None, _("invalid argument list"))
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
415 if len(args) != len(set(args)):
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
416 return (name, None, _("argument names collide with each other"))
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
417 return (name, [t[1] for t in args], None)
28871
6d6201fc5aae parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28870
diff changeset
418
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
419 return (decl, None, _("invalid format"))
28872
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
420
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
421 @classmethod
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
422 def _relabelargs(cls, tree, args):
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
423 """Mark alias arguments as ``_aliasarg``"""
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
424 if not isinstance(tree, tuple):
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
425 return tree
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
426 op = tree[0]
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
427 if op != cls._symbolnode:
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
428 return (op,) + tuple(cls._relabelargs(x, args) for x in tree[1:])
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
429
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
430 assert len(tree) == 2
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
431 sym = tree[1]
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
432 if sym in args:
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
433 op = '_aliasarg'
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
434 elif sym.startswith('$'):
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
435 raise error.ParseError(_("invalid symbol '%s'") % sym)
28872
5f31d2248745 parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28871
diff changeset
436 return (op, sym)
28873
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
437
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
438 @classmethod
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
439 def _builddefn(cls, defn, args):
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
440 """Parse an alias definition into a tree and marks substitutions
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
441
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
442 This function marks alias argument references as ``_aliasarg``. The
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
443 parsing rule is provided by ``_parse()``.
28873
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
444
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
445 ``args`` is a list of alias argument names, or None if the alias
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
446 is declared as a symbol.
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
447
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
448 >>> parsemap = {
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
449 ... '$1 or foo': ('or', ('symbol', '$1'), ('symbol', 'foo')),
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
450 ... '$1 or $bar': ('or', ('symbol', '$1'), ('symbol', '$bar')),
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
451 ... '$10 or baz': ('or', ('symbol', '$10'), ('symbol', 'baz')),
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
452 ... '"$1" or "foo"': ('or', ('string', '$1'), ('string', 'foo')),
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
453 ... }
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
454 >>> class aliasrules(basealiasrules):
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
455 ... _parse = staticmethod(parsemap.__getitem__)
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
456 ... _trygetfunc = staticmethod(lambda x: None)
28873
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
457 >>> builddefn = aliasrules._builddefn
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
458 >>> def pprint(tree):
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
459 ... print prettyformat(tree, ('_aliasarg', 'string', 'symbol'))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
460 >>> args = ['$1', '$2', 'foo']
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
461 >>> pprint(builddefn('$1 or foo', args))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
462 (or
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
463 ('_aliasarg', '$1')
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
464 ('_aliasarg', 'foo'))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
465 >>> try:
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
466 ... builddefn('$1 or $bar', args)
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
467 ... except error.ParseError as inst:
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
468 ... print parseerrordetail(inst)
29058
dbed4c4f48ae parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents: 28910
diff changeset
469 invalid symbol '$bar'
28873
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
470 >>> args = ['$1', '$10', 'foo']
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
471 >>> pprint(builddefn('$10 or baz', args))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
472 (or
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
473 ('_aliasarg', '$10')
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
474 ('symbol', 'baz'))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
475 >>> pprint(builddefn('"$1" or "foo"', args))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
476 (or
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
477 ('string', '$1')
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
478 ('string', 'foo'))
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
479 """
28875
2e9f5453ab5a parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents: 28873
diff changeset
480 tree = cls._parse(defn)
28873
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
481 if args:
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
482 args = set(args)
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
483 else:
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
484 args = set()
2ca3b7c563f3 parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28872
diff changeset
485 return cls._relabelargs(tree, args)
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
486
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
487 @classmethod
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
488 def build(cls, decl, defn):
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
489 """Parse an alias declaration and definition into an alias object"""
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
490 repl = efmt = None
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
491 name, args, err = cls._builddecl(decl)
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
492 if err:
29059
8eba4cdcfd81 parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents: 29058
diff changeset
493 efmt = _('bad declaration of %(section)s "%(name)s": %(error)s')
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
494 else:
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
495 try:
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
496 repl = cls._builddefn(defn, args)
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
497 except error.ParseError as inst:
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
498 err = parseerrordetail(inst)
29059
8eba4cdcfd81 parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents: 29058
diff changeset
499 efmt = _('bad definition of %(section)s "%(name)s": %(error)s')
28892
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
500 if err:
0c135f37c6f8 parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28875
diff changeset
501 err = efmt % {'section': cls._section, 'name': name, 'error': err}
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
502 return alias(name, args, err, repl)
28893
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
503
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
504 @classmethod
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
505 def buildmap(cls, items):
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
506 """Parse a list of alias (name, replacement) pairs into a dict of
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
507 alias objects"""
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
508 aliases = {}
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
509 for decl, defn in items:
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
510 a = cls.build(decl, defn)
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
511 aliases[a.name] = a
ee11167fe1da parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents: 28892
diff changeset
512 return aliases
28895
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
513
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
514 @classmethod
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
515 def _getalias(cls, aliases, tree):
28909
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
516 """If tree looks like an unexpanded alias, return (alias, pattern-args)
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
517 pair. Return None otherwise.
28895
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
518 """
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
519 if not isinstance(tree, tuple):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
520 return None
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
521 if tree[0] == cls._symbolnode:
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
522 name = tree[1]
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
523 a = aliases.get(name)
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
524 if a and a.args is None:
28909
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
525 return a, None
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
526 func = cls._trygetfunc(tree)
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
527 if func:
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
528 name, args = func
28895
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
529 a = aliases.get(name)
28908
7a772deffa12 parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents: 28898
diff changeset
530 if a and a.args is not None:
28910
1203159c8928 parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents: 28909
diff changeset
531 return a, args
28895
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
532 return None
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
533
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
534 @classmethod
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
535 def _expandargs(cls, tree, args):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
536 """Replace _aliasarg instances with the substitution value of the
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
537 same name in args, recursively.
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
538 """
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
539 if not isinstance(tree, tuple):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
540 return tree
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
541 if tree[0] == '_aliasarg':
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
542 sym = tree[1]
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
543 return args[sym]
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
544 return tuple(cls._expandargs(t, args) for t in tree)
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
545
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
546 @classmethod
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
547 def _expand(cls, aliases, tree, expanding, cache):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
548 if not isinstance(tree, tuple):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
549 return tree
28909
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
550 r = cls._getalias(aliases, tree)
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
551 if r is None:
28896
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
552 return tuple(cls._expand(aliases, t, expanding, cache)
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
553 for t in tree)
28909
edbffdc7f6a0 parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents: 28908
diff changeset
554 a, l = r
28896
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
555 if a.error:
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
556 raise error.Abort(a.error)
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
557 if a in expanding:
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
558 raise error.ParseError(_('infinite expansion of %(section)s '
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
559 '"%(name)s" detected')
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
560 % {'section': cls._section, 'name': a.name})
28897
c1f254138f44 parser: add short comment how aliases are expanded in phases
Yuya Nishihara <yuya@tcha.org>
parents: 28896
diff changeset
561 # get cacheable replacement tree by expanding aliases recursively
28896
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
562 expanding.append(a)
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
563 if a.name not in cache:
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
564 cache[a.name] = cls._expand(aliases, a.replacement, expanding,
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
565 cache)
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
566 result = cache[a.name]
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
567 expanding.pop()
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
568 if a.args is None:
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
569 return result
28897
c1f254138f44 parser: add short comment how aliases are expanded in phases
Yuya Nishihara <yuya@tcha.org>
parents: 28896
diff changeset
570 # substitute function arguments in replacement tree
28896
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
571 if len(l) != len(a.args):
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
572 raise error.ParseError(_('invalid number of arguments: %d')
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
573 % len(l))
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
574 l = [cls._expand(aliases, t, [], cache) for t in l]
4c76a032ec7e parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents: 28895
diff changeset
575 return cls._expandargs(result, dict(zip(a.args, l)))
28895
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
576
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
577 @classmethod
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
578 def expand(cls, aliases, tree):
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
579 """Expand aliases in tree, recursively.
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
580
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
581 'aliases' is a dictionary mapping user defined aliases to alias objects.
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
582 """
4bf9ed7a260e parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents: 28893
diff changeset
583 return cls._expand(aliases, tree, [], {})