Mercurial > hg
annotate mercurial/parser.py @ 42785:c00005975c91
perf: don't depend on pycompat for older Mercurial versions
We already define local _sysstr() and _xrange() for compatibility, so
we should use those.
Also create a similar local _bytestr() corresponding to
pycompat.bytestr().
Differential Revision: https://phab.mercurial-scm.org/D6745
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Mon, 19 Aug 2019 10:34:10 -0700 |
parents | 29798c9ba5c9 |
children | 2372284d9457 |
rev | line source |
---|---|
11274 | 1 # parser.py - simple top-down operator precedence parser for mercurial |
2 # | |
3 # Copyright 2010 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2 or any later version. | |
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 | 9 # http://eli.thegreenplace.net/2010/01/02/top-down-operator-precedence-parsing/ |
10 # for background | |
11 | |
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 | 16 # an action is a tree node name, a tree label, and an optional match |
17500 | 17 # __call__(program) parses program into a labeled tree |
11274 | 18 |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
19 from __future__ import absolute_import, print_function |
25963
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, |
36547
7840d8bd0558
py3: byte-stringify ValueError of unescapestr() to reraise as ParseError
Yuya Nishihara <yuya@tcha.org>
parents:
34137
diff
changeset
|
24 pycompat, |
31484
afb335353d28
util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
31353
diff
changeset
|
25 util, |
afb335353d28
util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
31353
diff
changeset
|
26 ) |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
27 from .utils import ( |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
28 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
29 ) |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
30 |
11274 | 31 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
|
32 def __init__(self, elements, methods=None): |
11274 | 33 self._elements = elements |
34 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
|
35 self.current = None |
11274 | 36 def _advance(self): |
37 'advance the tokenizer' | |
38 t = self.current | |
25171
d647f97f88dd
parsers: use 'next' instead of try/except
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20778
diff
changeset
|
39 self.current = next(self._iter, None) |
11274 | 40 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
|
41 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
|
42 '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
|
43 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
|
44 def _match(self, m): |
11274 | 45 'make sure the tokenizer matches an end condition' |
46 if self.current[0] != m: | |
14701
4b93bd041772
parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents:
13665
diff
changeset
|
47 raise error.ParseError(_("unexpected token: %s") % self.current[0], |
11305
d4cafcb63f77
cleanups: undefined variables
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11289
diff
changeset
|
48 self.current[2]) |
11274 | 49 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
|
50 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
|
51 '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
|
52 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
|
53 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
|
54 else: |
b3004d273874
parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents:
25802
diff
changeset
|
55 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
|
56 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
|
57 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
|
58 return expr |
11274 | 59 def _parse(self, bind=0): |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
60 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
|
61 # 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
|
62 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
|
63 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
|
64 expr = (primary, value) |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25804
diff
changeset
|
65 elif prefix: |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25804
diff
changeset
|
66 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
|
67 else: |
14701
4b93bd041772
parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents:
13665
diff
changeset
|
68 raise error.ParseError(_("not a prefix: %s") % token, pos) |
11274 | 69 # gather tokens until we meet a lower binding strength |
70 while bind < self._elements[self.current[0]][0]: | |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
71 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
|
72 # 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
|
73 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
|
74 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
|
75 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
|
76 elif infix: |
42ac9d1d1572
parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents:
25816
diff
changeset
|
77 expr = (infix[0], expr, self._parseoperand(*infix[1:])) |
11274 | 78 else: |
25817
42ac9d1d1572
parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents:
25816
diff
changeset
|
79 raise error.ParseError(_("not an infix: %s") % token, pos) |
11274 | 80 return expr |
25654
af329a84310c
parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents:
25306
diff
changeset
|
81 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
|
82 '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
|
83 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
|
84 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
|
85 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
|
86 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
|
87 return res, pos |
11274 | 88 def eval(self, tree): |
89 'recursively evaluate a parse tree using node methods' | |
90 if not isinstance(tree, tuple): | |
91 return tree | |
92 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
|
93 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
|
94 '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
|
95 t = self.parse(tokeniter) |
11274 | 96 if self._methods: |
97 return self.eval(t) | |
98 return t | |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
99 |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
100 def splitargspec(spec): |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
101 """Parse spec of function arguments into (poskeys, varkey, keys, optkey) |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
102 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
103 >>> splitargspec(b'') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
104 ([], None, [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
105 >>> splitargspec(b'foo bar') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
106 ([], None, ['foo', 'bar'], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
107 >>> splitargspec(b'foo *bar baz **qux') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
108 (['foo'], 'bar', ['baz'], 'qux') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
109 >>> splitargspec(b'*foo') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
110 ([], 'foo', [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
111 >>> splitargspec(b'**foo') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
112 ([], None, [], 'foo') |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
113 """ |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
114 optkey = None |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
115 pre, sep, post = spec.partition('**') |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
116 if sep: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
117 posts = post.split() |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
118 if not posts: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
119 raise error.ProgrammingError('no **optkey name provided') |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
120 if len(posts) > 1: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
121 raise error.ProgrammingError('excessive **optkey names provided') |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
122 optkey = posts[0] |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
123 |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
124 pre, sep, post = pre.partition('*') |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
125 pres = pre.split() |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
126 posts = post.split() |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
127 if sep: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
128 if not posts: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
129 raise error.ProgrammingError('no *varkey name provided') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
130 return pres, posts[0], posts[1:], optkey |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
131 return [], None, pres, optkey |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
132 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
133 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
|
134 """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
|
135 |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
136 Arguments are specified by a tuple of ``(poskeys, varkey, keys, optkey)`` |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
137 where |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
138 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
139 - ``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
|
140 - ``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
|
141 - ``keys``: list of names that can be either positional or keyword arguments |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
142 - ``optkey``: optional argument name that takes up excess keyword arguments |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
143 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
144 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
|
145 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
146 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
|
147 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
|
148 """ |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
149 poskeys, varkey, keys, optkey = argspec |
42232
29798c9ba5c9
parser: fix crash by parsing "()" in keyword argument position
Yuya Nishihara <yuya@tcha.org>
parents:
39050
diff
changeset
|
150 kwstart = next((i for i, x in enumerate(trees) |
29798c9ba5c9
parser: fix crash by parsing "()" in keyword argument position
Yuya Nishihara <yuya@tcha.org>
parents:
39050
diff
changeset
|
151 if x and x[0] == keyvaluenode), |
30752
ffd324eaf994
parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents:
30332
diff
changeset
|
152 len(trees)) |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
153 if kwstart < len(poskeys): |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
154 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
|
155 "arguments") |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
156 % {'func': funcname, 'nargs': len(poskeys)}) |
31920
a98540ea1e42
parser: verify excessive number of args excluding kwargs in buildargsdict()
Yuya Nishihara <yuya@tcha.org>
parents:
31484
diff
changeset
|
157 if not varkey and kwstart > len(poskeys) + len(keys): |
a98540ea1e42
parser: verify excessive number of args excluding kwargs in buildargsdict()
Yuya Nishihara <yuya@tcha.org>
parents:
31484
diff
changeset
|
158 raise error.ParseError(_("%(func)s takes at most %(nargs)d positional " |
a98540ea1e42
parser: verify excessive number of args excluding kwargs in buildargsdict()
Yuya Nishihara <yuya@tcha.org>
parents:
31484
diff
changeset
|
159 "arguments") |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
160 % {'func': funcname, |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
161 'nargs': len(poskeys) + len(keys)}) |
31922
0f41f1e3c75c
parser: preserve order of keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
31921
diff
changeset
|
162 args = util.sortdict() |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
163 # consume positional arguments |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
164 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
|
165 args[k] = x |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
166 if varkey: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
167 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
|
168 else: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
169 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
|
170 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
|
171 # remainder should be keyword arguments |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
172 if optkey: |
31922
0f41f1e3c75c
parser: preserve order of keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
31921
diff
changeset
|
173 args[optkey] = util.sortdict() |
30752
ffd324eaf994
parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents:
30332
diff
changeset
|
174 for x in trees[kwstart:]: |
42232
29798c9ba5c9
parser: fix crash by parsing "()" in keyword argument position
Yuya Nishihara <yuya@tcha.org>
parents:
39050
diff
changeset
|
175 if not x or x[0] != keyvaluenode or x[1][0] != keynode: |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
176 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
|
177 % {'func': funcname}) |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
178 k = x[1][1] |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
179 if k in keys: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
180 d = args |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
181 elif not optkey: |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
182 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
|
183 "argument '%(key)s'") |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
184 % {'func': funcname, 'key': k}) |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
185 else: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
186 d = args[optkey] |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
187 if k in d: |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
188 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
|
189 "argument '%(key)s'") |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
190 % {'func': funcname, 'key': k}) |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
191 d[k] = x[2] |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
192 return args |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
193 |
26231
87c9c562c37a
parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents:
25963
diff
changeset
|
194 def unescapestr(s): |
87c9c562c37a
parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents:
25963
diff
changeset
|
195 try: |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
196 return stringutil.unescapestr(s) |
26231
87c9c562c37a
parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents:
25963
diff
changeset
|
197 except ValueError as e: |
87c9c562c37a
parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents:
25963
diff
changeset
|
198 # mangle Python's exception into our format |
36547
7840d8bd0558
py3: byte-stringify ValueError of unescapestr() to reraise as ParseError
Yuya Nishihara <yuya@tcha.org>
parents:
34137
diff
changeset
|
199 raise error.ParseError(pycompat.bytestr(e).lower()) |
26231
87c9c562c37a
parser: move unescape helper from templater
Yuya Nishihara <yuya@tcha.org>
parents:
25963
diff
changeset
|
200 |
25254
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
201 def _prettyformat(tree, leafnodes, level, lines): |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
202 if not isinstance(tree, tuple): |
39050
0a2ce5b43574
parser: replace bespoke _brepr with stringutil.pprint
Augie Fackler <augie@google.com>
parents:
37084
diff
changeset
|
203 lines.append((level, stringutil.pprint(tree))) |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
204 elif tree[0] in leafnodes: |
39050
0a2ce5b43574
parser: replace bespoke _brepr with stringutil.pprint
Augie Fackler <augie@google.com>
parents:
37084
diff
changeset
|
205 rs = map(stringutil.pprint, tree[1:]) |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
206 lines.append((level, '(%s %s)' % (tree[0], ' '.join(rs)))) |
25254
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
207 else: |
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
208 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
|
209 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
|
210 _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
|
211 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
|
212 |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
213 def prettyformat(tree, leafnodes): |
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
214 lines = [] |
25254
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
215 _prettyformat(tree, leafnodes, 0, lines) |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
216 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
|
217 return output |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
218 |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
219 def simplifyinfixops(tree, targetnodes): |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
220 """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
|
221 |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
222 >>> from . import pycompat |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
223 >>> def f(tree): |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
224 ... s = prettyformat(simplifyinfixops(tree, (b'or',)), (b'symbol',)) |
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
225 ... print(pycompat.sysstr(s)) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
226 >>> f((b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
227 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
228 ... (b'symbol', b'1'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
229 ... (b'symbol', b'2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
230 ... (b'symbol', b'3'))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
231 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
232 (symbol '1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
233 (symbol '2') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
234 (symbol '3')) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
235 >>> f((b'func', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
236 ... (b'symbol', b'p1'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
237 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
238 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
239 ... (b'func', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
240 ... (b'symbol', b'sort'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
241 ... (b'list', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
242 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
243 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
244 ... (b'symbol', b'1'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
245 ... (b'symbol', b'2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
246 ... (b'symbol', b'3')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
247 ... (b'negate', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
248 ... (b'symbol', b'rev')))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
249 ... (b'and', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
250 ... (b'symbol', b'4'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
251 ... (b'group', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
252 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
253 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
254 ... (b'symbol', b'5'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
255 ... (b'symbol', b'6')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
256 ... (b'symbol', b'7'))))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
257 ... (b'symbol', b'8')))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
258 (func |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
259 (symbol 'p1') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
260 (or |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
261 (func |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
262 (symbol 'sort') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
263 (list |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
264 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
265 (symbol '1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
266 (symbol '2') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
267 (symbol '3')) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
268 (negate |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
269 (symbol 'rev')))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
270 (and |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
271 (symbol '4') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
272 (group |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
273 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
274 (symbol '5') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
275 (symbol '6') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
276 (symbol '7')))) |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
277 (symbol '8'))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
278 """ |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
279 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
|
280 return tree |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
281 op = tree[0] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
282 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
|
283 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
|
284 |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
285 # 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
|
286 # 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
|
287 # 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
|
288 simplified = [] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
289 x = tree |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
290 while x[0] == op: |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
291 l, r = x[1:] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
292 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
|
293 x = l |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
294 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
|
295 simplified.append(op) |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
296 return tuple(reversed(simplified)) |
28720
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
297 |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
298 def _buildtree(template, placeholder, replstack): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
299 if template == placeholder: |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
300 return replstack.pop() |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
301 if not isinstance(template, tuple): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
302 return template |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
303 return tuple(_buildtree(x, placeholder, replstack) for x in template) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
304 |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
305 def buildtree(template, placeholder, *repls): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
306 """Create new tree by substituting placeholders by replacements |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
307 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
308 >>> _ = (b'symbol', b'_') |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
309 >>> def f(template, *repls): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
310 ... return buildtree(template, _, *repls) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
311 >>> f((b'func', (b'symbol', b'only'), (b'list', _, _)), |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
312 ... ('symbol', '1'), ('symbol', '2')) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
313 ('func', ('symbol', 'only'), ('list', ('symbol', '1'), ('symbol', '2'))) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
314 >>> f((b'and', _, (b'not', _)), (b'symbol', b'1'), (b'symbol', b'2')) |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
315 ('and', ('symbol', '1'), ('not', ('symbol', '2'))) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
316 """ |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
317 if not isinstance(placeholder, tuple): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
318 raise error.ProgrammingError('placeholder must be a node tuple') |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
319 replstack = list(reversed(repls)) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
320 r = _buildtree(template, placeholder, replstack) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
321 if replstack: |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
322 raise error.ProgrammingError('too many replacements') |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
323 return r |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
324 |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
325 def _matchtree(pattern, tree, placeholder, incompletenodes, matches): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
326 if pattern == tree: |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
327 return True |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
328 if not isinstance(pattern, tuple) or not isinstance(tree, tuple): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
329 return False |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
330 if pattern == placeholder and tree[0] not in incompletenodes: |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
331 matches.append(tree) |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
332 return True |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
333 if len(pattern) != len(tree): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
334 return False |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
335 return all(_matchtree(p, x, placeholder, incompletenodes, matches) |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
336 for p, x in zip(pattern, tree)) |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
337 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
338 def matchtree(pattern, tree, placeholder=None, incompletenodes=()): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
339 """If a tree matches the pattern, return a list of the tree and nodes |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
340 matched with the placeholder; Otherwise None |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
341 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
342 >>> def f(pattern, tree): |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
343 ... m = matchtree(pattern, tree, _, {b'keyvalue', b'list'}) |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
344 ... if m: |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
345 ... return m[1:] |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
346 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
347 >>> _ = (b'symbol', b'_') |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
348 >>> f((b'func', (b'symbol', b'ancestors'), _), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
349 ... (b'func', (b'symbol', b'ancestors'), (b'symbol', b'1'))) |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
350 [('symbol', '1')] |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
351 >>> f((b'func', (b'symbol', b'ancestors'), _), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
352 ... (b'func', (b'symbol', b'ancestors'), None)) |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
353 >>> f((b'range', (b'dagrange', _, _), _), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
354 ... (b'range', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
355 ... (b'dagrange', (b'symbol', b'1'), (b'symbol', b'2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
356 ... (b'symbol', b'3'))) |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
357 [('symbol', '1'), ('symbol', '2'), ('symbol', '3')] |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
358 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
359 The placeholder does not match the specified incomplete nodes because |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
360 an incomplete node (e.g. argument list) cannot construct an expression. |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
361 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
362 >>> f((b'func', (b'symbol', b'ancestors'), _), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
363 ... (b'func', (b'symbol', b'ancestors'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
364 ... (b'list', (b'symbol', b'1'), (b'symbol', b'2')))) |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
365 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
366 The placeholder may be omitted, but which shouldn't match a None node. |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
367 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
368 >>> _ = None |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
369 >>> f((b'func', (b'symbol', b'ancestors'), None), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
370 ... (b'func', (b'symbol', b'ancestors'), (b'symbol', b'0'))) |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
371 """ |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
372 if placeholder is not None and not isinstance(placeholder, tuple): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
373 raise error.ProgrammingError('placeholder must be a node tuple') |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
374 matches = [tree] |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
375 if _matchtree(pattern, tree, placeholder, incompletenodes, matches): |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
376 return matches |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
377 |
28720
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
378 def parseerrordetail(inst): |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
379 """Compose error message from specified ParseError object |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
380 """ |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
381 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
|
382 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
|
383 else: |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
384 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
|
385 |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
386 class alias(object): |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
387 """Parsed result of alias""" |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
388 |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
389 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
|
390 self.name = name |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
391 self.args = args |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
392 self.error = err |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
393 self.replacement = replacement |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
394 # 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
|
395 # this avoids showing same warning multiple times at each |
8d398155bfda
revset: rename findaliases() to expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents:
28897
diff
changeset
|
396 # `expandaliases`. |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
397 self.warned = False |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
398 |
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
399 class basealiasrules(object): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
400 """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
|
401 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
402 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
|
403 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
|
404 |
30332
318a24b52eeb
spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents:
29767
diff
changeset
|
405 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
|
406 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
407 # decl = defn |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
408 h = heads(default) |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
409 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
|
410 """ |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
411 # 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
|
412 _section = None |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
413 # 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
|
414 _symbolnode = 'symbol' |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
415 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
416 def __new__(cls): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
417 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
|
418 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
419 @staticmethod |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
420 def _parse(spec): |
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
421 """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
|
422 raise NotImplementedError |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
423 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
424 @staticmethod |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
425 def _trygetfunc(tree): |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
426 """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
|
427 raise NotImplementedError |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
428 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
429 @classmethod |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
430 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
|
431 """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
|
432 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
433 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
|
434 by ``_parse()``. |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
435 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
436 - ``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
|
437 - ``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
|
438 - ``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
|
439 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
440 >>> sym = lambda x: (b'symbol', x) |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
441 >>> symlist = lambda *xs: (b'list',) + tuple(sym(x) for x in xs) |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
442 >>> func = lambda n, a: (b'func', sym(n), a) |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
443 >>> parsemap = { |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
444 ... b'foo': sym(b'foo'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
445 ... b'$foo': sym(b'$foo'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
446 ... b'foo::bar': (b'dagrange', sym(b'foo'), sym(b'bar')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
447 ... b'foo()': func(b'foo', None), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
448 ... b'$foo()': func(b'$foo', None), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
449 ... b'foo($1, $2)': func(b'foo', symlist(b'$1', b'$2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
450 ... b'foo(bar_bar, baz.baz)': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
451 ... func(b'foo', symlist(b'bar_bar', b'baz.baz')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
452 ... b'foo(bar($1, $2))': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
453 ... func(b'foo', func(b'bar', symlist(b'$1', b'$2'))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
454 ... b'foo($1, $2, nested($1, $2))': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
455 ... func(b'foo', (symlist(b'$1', b'$2') + |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
456 ... (func(b'nested', symlist(b'$1', b'$2')),))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
457 ... b'foo("bar")': func(b'foo', (b'string', b'bar')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
458 ... b'foo($1, $2': error.ParseError(b'unexpected token: end', 10), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
459 ... b'foo("bar': error.ParseError(b'unterminated string', 5), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
460 ... b'foo($1, $2, $1)': func(b'foo', symlist(b'$1', b'$2', b'$1')), |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
461 ... } |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
462 >>> def parse(expr): |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
463 ... x = parsemap[expr] |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
464 ... if isinstance(x, Exception): |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
465 ... raise x |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
466 ... return x |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
467 >>> def trygetfunc(tree): |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
468 ... if not tree or tree[0] != b'func' or tree[1][0] != b'symbol': |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
469 ... return None |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
470 ... if not tree[2]: |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
471 ... return tree[1][1], [] |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
472 ... if tree[2][0] == b'list': |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
473 ... 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
|
474 ... 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
|
475 >>> class aliasrules(basealiasrules): |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
476 ... _parse = staticmethod(parse) |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
477 ... _trygetfunc = staticmethod(trygetfunc) |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
478 >>> builddecl = aliasrules._builddecl |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
479 >>> builddecl(b'foo') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
480 ('foo', None, None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
481 >>> builddecl(b'$foo') |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
482 ('$foo', None, "invalid symbol '$foo'") |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
483 >>> builddecl(b'foo::bar') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
484 ('foo::bar', None, 'invalid format') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
485 >>> builddecl(b'foo()') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
486 ('foo', [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
487 >>> builddecl(b'$foo()') |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
488 ('$foo()', None, "invalid function '$foo'") |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
489 >>> builddecl(b'foo($1, $2)') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
490 ('foo', ['$1', '$2'], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
491 >>> builddecl(b'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
|
492 ('foo', ['bar_bar', 'baz.baz'], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
493 >>> builddecl(b'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
|
494 ('foo($1, $2, nested($1, $2))', None, 'invalid argument list') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
495 >>> builddecl(b'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
|
496 ('foo(bar($1, $2))', None, 'invalid argument list') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
497 >>> builddecl(b'foo("bar")') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
498 ('foo("bar")', None, 'invalid argument list') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
499 >>> builddecl(b'foo($1, $2') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
500 ('foo($1, $2', None, 'at 10: unexpected token: end') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
501 >>> builddecl(b'foo("bar') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
502 ('foo("bar', None, 'at 5: unterminated string') |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
503 >>> builddecl(b'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
|
504 ('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
|
505 """ |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
506 try: |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
507 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
|
508 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
|
509 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
|
510 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
511 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
|
512 # "name = ...." style |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
513 name = tree[1] |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
514 if name.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
515 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
|
516 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
|
517 |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
518 func = cls._trygetfunc(tree) |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
519 if func: |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
520 # "name(arg, ....) = ...." style |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
521 name, args = func |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
522 if name.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
523 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
|
524 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
|
525 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
|
526 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
|
527 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
|
528 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
|
529 |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
530 return (decl, None, _("invalid format")) |
28872
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
531 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
532 @classmethod |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
533 def _relabelargs(cls, tree, args): |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
534 """Mark alias arguments as ``_aliasarg``""" |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
535 if not isinstance(tree, tuple): |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
536 return tree |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
537 op = tree[0] |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
538 if op != cls._symbolnode: |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
539 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
|
540 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
541 assert len(tree) == 2 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
542 sym = tree[1] |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
543 if sym in args: |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
544 op = '_aliasarg' |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
545 elif sym.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
546 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
|
547 return (op, sym) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
548 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
549 @classmethod |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
550 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
|
551 """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
|
552 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
553 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
|
554 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
|
555 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
556 ``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
|
557 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
|
558 |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
559 >>> from . import pycompat |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
560 >>> parsemap = { |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
561 ... b'$1 or foo': (b'or', (b'symbol', b'$1'), (b'symbol', b'foo')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
562 ... b'$1 or $bar': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
563 ... (b'or', (b'symbol', b'$1'), (b'symbol', b'$bar')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
564 ... b'$10 or baz': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
565 ... (b'or', (b'symbol', b'$10'), (b'symbol', b'baz')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
566 ... b'"$1" or "foo"': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
567 ... (b'or', (b'string', b'$1'), (b'string', b'foo')), |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
568 ... } |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
569 >>> class aliasrules(basealiasrules): |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
570 ... _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
|
571 ... _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
|
572 >>> builddefn = aliasrules._builddefn |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
573 >>> def pprint(tree): |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
574 ... s = prettyformat(tree, (b'_aliasarg', b'string', b'symbol')) |
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
575 ... print(pycompat.sysstr(s)) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
576 >>> args = [b'$1', b'$2', b'foo'] |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
577 >>> pprint(builddefn(b'$1 or foo', args)) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
578 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
579 (_aliasarg '$1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
580 (_aliasarg 'foo')) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
581 >>> try: |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
582 ... builddefn(b'$1 or $bar', args) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
583 ... except error.ParseError as inst: |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
584 ... print(pycompat.sysstr(parseerrordetail(inst))) |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
585 invalid symbol '$bar' |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
586 >>> args = [b'$1', b'$10', b'foo'] |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
587 >>> pprint(builddefn(b'$10 or baz', args)) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
588 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
589 (_aliasarg '$10') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
590 (symbol 'baz')) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
591 >>> pprint(builddefn(b'"$1" or "foo"', args)) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
592 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
593 (string '$1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
594 (string 'foo')) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
595 """ |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
596 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
|
597 if args: |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
598 args = set(args) |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
599 else: |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
600 args = set() |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
601 return cls._relabelargs(tree, args) |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
602 |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
603 @classmethod |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
604 def build(cls, decl, defn): |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
605 """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
|
606 repl = efmt = None |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
607 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
|
608 if err: |
29059
8eba4cdcfd81
parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents:
29058
diff
changeset
|
609 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
|
610 else: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
611 try: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
612 repl = cls._builddefn(defn, args) |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
613 except error.ParseError as inst: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
614 err = parseerrordetail(inst) |
29059
8eba4cdcfd81
parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents:
29058
diff
changeset
|
615 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
|
616 if err: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
617 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
|
618 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
|
619 |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
620 @classmethod |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
621 def buildmap(cls, items): |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
622 """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
|
623 alias objects""" |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
624 aliases = {} |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
625 for decl, defn in items: |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
626 a = cls.build(decl, defn) |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
627 aliases[a.name] = a |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
628 return aliases |
28895
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
629 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
630 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
631 def _getalias(cls, aliases, tree): |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
632 """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
|
633 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
|
634 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
635 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
|
636 return None |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
637 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
|
638 name = tree[1] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
639 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
|
640 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
|
641 return a, None |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
642 func = cls._trygetfunc(tree) |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
643 if func: |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
644 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
|
645 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
|
646 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
|
647 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
|
648 return None |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
649 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
650 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
651 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
|
652 """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
|
653 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
|
654 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
655 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
|
656 return tree |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
657 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
|
658 sym = tree[1] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
659 return args[sym] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
660 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
|
661 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
662 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
663 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
|
664 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
|
665 return tree |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
666 r = cls._getalias(aliases, tree) |
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
667 if r is None: |
28896
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
668 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
|
669 for t in tree) |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
670 a, l = r |
28896
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
671 if a.error: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
672 raise error.Abort(a.error) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
673 if a in expanding: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
674 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
|
675 '"%(name)s" detected') |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
676 % {'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
|
677 # 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
|
678 expanding.append(a) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
679 if a.name not in cache: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
680 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
|
681 cache) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
682 result = cache[a.name] |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
683 expanding.pop() |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
684 if a.args is None: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
685 return result |
28897
c1f254138f44
parser: add short comment how aliases are expanded in phases
Yuya Nishihara <yuya@tcha.org>
parents:
28896
diff
changeset
|
686 # 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
|
687 if len(l) != len(a.args): |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
688 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
|
689 % len(l)) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
690 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
|
691 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
|
692 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
693 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
694 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
|
695 """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
|
696 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
697 '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
|
698 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
699 return cls._expand(aliases, tree, [], {}) |