Mercurial > hg
annotate mercurial/parser.py @ 37295:45b39c69fae0
wireproto: separate commands tables for version 1 and 2 commands
We can't easily reuse existing command handlers for version 2
commands because the response types will be different. e.g. many
commands return nodes encoded as hex. Our new wire protocol is
binary safe, so we'll wish to encode nodes as binary.
We /could/ teach each command handler to look at the protocol
handler and change behavior based on the version in use. However,
this would make logic a bit unwieldy over time and would make
it harder to design a unified protocol handler interface. I think
it's better to create a clean break between version 1 and version 2
of commands on the server.
What I imagine happening is we will have separate @wireprotocommand
functions for each protocol generation. Those functions will parse the
request, dispatch to a common function to process it, then generate
the response in its own, transport-specific manner.
This commit establishes a separate table for tracking version 1
commands from version 2 commands. The HTTP server pieces have been
updated to use this new table.
Most commands are marked as both version 1 and version 2, so there is
little practical impact to this change.
A side-effect of this change is we now rely on transport registration
in wireprototypes.TRANSPORTS and certain properties of the protocol
interface. So a test had to be updated to conform.
Differential Revision: https://phab.mercurial-scm.org/D2982
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 28 Mar 2018 10:40:41 -0700 |
parents | f0b6fbea00cf |
children | 0a2ce5b43574 |
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 ( |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
23 encoding, |
31484
afb335353d28
util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
31353
diff
changeset
|
24 error, |
36547
7840d8bd0558
py3: byte-stringify ValueError of unescapestr() to reraise as ParseError
Yuya Nishihara <yuya@tcha.org>
parents:
34137
diff
changeset
|
25 pycompat, |
31484
afb335353d28
util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
31353
diff
changeset
|
26 util, |
afb335353d28
util: wrap s.decode('string_escape') calls for future py3 compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
31353
diff
changeset
|
27 ) |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
28 from .utils import ( |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
29 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
30 ) |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
31 |
11274 | 32 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
|
33 def __init__(self, elements, methods=None): |
11274 | 34 self._elements = elements |
35 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
|
36 self.current = None |
11274 | 37 def _advance(self): |
38 'advance the tokenizer' | |
39 t = self.current | |
25171
d647f97f88dd
parsers: use 'next' instead of try/except
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20778
diff
changeset
|
40 self.current = next(self._iter, None) |
11274 | 41 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
|
42 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
|
43 '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
|
44 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
|
45 def _match(self, m): |
11274 | 46 'make sure the tokenizer matches an end condition' |
47 if self.current[0] != m: | |
14701
4b93bd041772
parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents:
13665
diff
changeset
|
48 raise error.ParseError(_("unexpected token: %s") % self.current[0], |
11305
d4cafcb63f77
cleanups: undefined variables
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11289
diff
changeset
|
49 self.current[2]) |
11274 | 50 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
|
51 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
|
52 '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
|
53 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
|
54 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
|
55 else: |
b3004d273874
parser: factor out function that parses right-hand side of prefix/infix ops
Yuya Nishihara <yuya@tcha.org>
parents:
25802
diff
changeset
|
56 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
|
57 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
|
58 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
|
59 return expr |
11274 | 60 def _parse(self, bind=0): |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
61 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
|
62 # 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
|
63 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
|
64 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
|
65 expr = (primary, value) |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25804
diff
changeset
|
66 elif prefix: |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25804
diff
changeset
|
67 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
|
68 else: |
14701
4b93bd041772
parsers: fix localization markup of parser errors
Mads Kiilerich <mads@kiilerich.com>
parents:
13665
diff
changeset
|
69 raise error.ParseError(_("not a prefix: %s") % token, pos) |
11274 | 70 # gather tokens until we meet a lower binding strength |
71 while bind < self._elements[self.current[0]][0]: | |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
72 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
|
73 # 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
|
74 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
|
75 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
|
76 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
|
77 elif infix: |
42ac9d1d1572
parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents:
25816
diff
changeset
|
78 expr = (infix[0], expr, self._parseoperand(*infix[1:])) |
11274 | 79 else: |
25817
42ac9d1d1572
parser: reorder infix/suffix handling to be similar to prefix/primary flow
Yuya Nishihara <yuya@tcha.org>
parents:
25816
diff
changeset
|
80 raise error.ParseError(_("not an infix: %s") % token, pos) |
11274 | 81 return expr |
25654
af329a84310c
parser: accept iterator of tokens instead of tokenizer function and program
Yuya Nishihara <yuya@tcha.org>
parents:
25306
diff
changeset
|
82 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
|
83 '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
|
84 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
|
85 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
|
86 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
|
87 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
|
88 return res, pos |
11274 | 89 def eval(self, tree): |
90 'recursively evaluate a parse tree using node methods' | |
91 if not isinstance(tree, tuple): | |
92 return tree | |
93 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
|
94 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
|
95 '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
|
96 t = self.parse(tokeniter) |
11274 | 97 if self._methods: |
98 return self.eval(t) | |
99 return t | |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
100 |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
101 def splitargspec(spec): |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
102 """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
|
103 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
104 >>> splitargspec(b'') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
105 ([], None, [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
106 >>> splitargspec(b'foo bar') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
107 ([], 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
|
108 >>> 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
|
109 (['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
|
110 >>> splitargspec(b'*foo') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
111 ([], 'foo', [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
112 >>> splitargspec(b'**foo') |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
113 ([], None, [], 'foo') |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
114 """ |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
115 optkey = None |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
116 pre, sep, post = spec.partition('**') |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
117 if sep: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
118 posts = post.split() |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
119 if not posts: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
120 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
|
121 if len(posts) > 1: |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
122 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
|
123 optkey = posts[0] |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
124 |
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
125 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
|
126 pres = pre.split() |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
127 posts = post.split() |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
128 if sep: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
129 if not posts: |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
130 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
|
131 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
|
132 return [], None, pres, optkey |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
133 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
134 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
|
135 """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
|
136 |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
137 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
|
138 where |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
139 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
140 - ``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
|
141 - ``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
|
142 - ``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
|
143 - ``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
|
144 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
145 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
|
146 |
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30752
diff
changeset
|
147 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
|
148 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
|
149 """ |
31921
2156934b7917
parser: extend buildargsdict() to support arbitrary number of **kwargs
Yuya Nishihara <yuya@tcha.org>
parents:
31920
diff
changeset
|
150 poskeys, varkey, keys, optkey = argspec |
30752
ffd324eaf994
parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents:
30332
diff
changeset
|
151 kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode), |
ffd324eaf994
parser: make buildargsdict() precompute position where keyword args start
Yuya Nishihara <yuya@tcha.org>
parents:
30332
diff
changeset
|
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:]: |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
175 if x[0] != keyvaluenode or x[1][0] != keynode: |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25655
diff
changeset
|
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 |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
201 def _brepr(obj): |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
202 if isinstance(obj, bytes): |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36547
diff
changeset
|
203 return b"'%s'" % stringutil.escapestr(obj) |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
204 return encoding.strtolocal(repr(obj)) |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
205 |
25254
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
206 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
|
207 if not isinstance(tree, tuple): |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
208 lines.append((level, _brepr(tree))) |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
209 elif tree[0] in leafnodes: |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
210 rs = map(_brepr, tree[1:]) |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
211 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
|
212 else: |
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
213 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
|
214 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
|
215 _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
|
216 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
|
217 |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
218 def prettyformat(tree, leafnodes): |
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
219 lines = [] |
25254
060bdfef2517
parser: extract closure of prettyformat() to a top-level function
Yuya Nishihara <yuya@tcha.org>
parents:
25253
diff
changeset
|
220 _prettyformat(tree, leafnodes, 0, lines) |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25171
diff
changeset
|
221 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
|
222 return output |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
223 |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
224 def simplifyinfixops(tree, targetnodes): |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
225 """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
|
226 |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
227 >>> from . import pycompat |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
228 >>> 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
|
229 ... 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
|
230 ... 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
|
231 >>> f((b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
232 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
233 ... (b'symbol', b'1'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
234 ... (b'symbol', b'2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
235 ... (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
|
236 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
237 (symbol '1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
238 (symbol '2') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
239 (symbol '3')) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
240 >>> f((b'func', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
241 ... (b'symbol', b'p1'), |
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'func', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
245 ... (b'symbol', b'sort'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
246 ... (b'list', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
247 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
248 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
249 ... (b'symbol', b'1'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
250 ... (b'symbol', b'2')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
251 ... (b'symbol', b'3')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
252 ... (b'negate', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
253 ... (b'symbol', b'rev')))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
254 ... (b'and', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
255 ... (b'symbol', b'4'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
256 ... (b'group', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
257 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
258 ... (b'or', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
259 ... (b'symbol', b'5'), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
260 ... (b'symbol', b'6')), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
261 ... (b'symbol', b'7'))))), |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
262 ... (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
|
263 (func |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
264 (symbol 'p1') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
265 (or |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
266 (func |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
267 (symbol 'sort') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
268 (list |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
269 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
270 (symbol '1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
271 (symbol '2') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
272 (symbol '3')) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
273 (negate |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
274 (symbol 'rev')))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
275 (and |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
276 (symbol '4') |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
277 (group |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
278 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
279 (symbol '5') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
280 (symbol '6') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
281 (symbol '7')))) |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
282 (symbol '8'))) |
25306
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
283 """ |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
284 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
|
285 return tree |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
286 op = tree[0] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
287 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
|
288 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
|
289 |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
290 # 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
|
291 # 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
|
292 # 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
|
293 simplified = [] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
294 x = tree |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
295 while x[0] == op: |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
296 l, r = x[1:] |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
297 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
|
298 x = l |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
299 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
|
300 simplified.append(op) |
c87b05925054
parser: add helper to reduce nesting of chained infix operations
Yuya Nishihara <yuya@tcha.org>
parents:
25254
diff
changeset
|
301 return tuple(reversed(simplified)) |
28720
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
302 |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
303 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
|
304 if template == placeholder: |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
305 return replstack.pop() |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
306 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
|
307 return template |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
308 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
|
309 |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
310 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
|
311 """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
|
312 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
313 >>> _ = (b'symbol', b'_') |
34043
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
314 >>> def f(template, *repls): |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
315 ... 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
|
316 >>> 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
|
317 ... ('symbol', '1'), ('symbol', '2')) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
318 ('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
|
319 >>> 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
|
320 ('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
|
321 """ |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
322 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
|
323 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
|
324 replstack = list(reversed(repls)) |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
325 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
|
326 if replstack: |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
327 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
|
328 return r |
90896b61fe26
parser: add helper function that constructs parsed tree from template
Yuya Nishihara <yuya@tcha.org>
parents:
31922
diff
changeset
|
329 |
34045
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
330 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
|
331 if pattern == 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 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
|
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 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
|
336 matches.append(tree) |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
337 return True |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
338 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
|
339 return False |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
340 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
|
341 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
|
342 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
343 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
|
344 """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
|
345 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
|
346 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
347 >>> 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
|
348 ... 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
|
349 ... if m: |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
350 ... return m[1:] |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
351 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
352 >>> _ = (b'symbol', b'_') |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
353 >>> 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
|
354 ... (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
|
355 [('symbol', '1')] |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
356 >>> 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
|
357 ... (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
|
358 >>> 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
|
359 ... (b'range', |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
360 ... (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
|
361 ... (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
|
362 [('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
|
363 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
364 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
|
365 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
|
366 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
367 >>> 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
|
368 ... (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
|
369 ... (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
|
370 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
371 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
|
372 |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
373 >>> _ = None |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
374 >>> 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
|
375 ... (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
|
376 """ |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
377 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
|
378 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
|
379 matches = [tree] |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
380 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
|
381 return matches |
79681d8ee587
parser: add helper function to test if pattern matches parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
34043
diff
changeset
|
382 |
28720
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
383 def parseerrordetail(inst): |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
384 """Compose error message from specified ParseError object |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
385 """ |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
386 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
|
387 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
|
388 else: |
639e0f1e8ffa
parser: move parsererrordetail() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
26231
diff
changeset
|
389 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
|
390 |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
391 class alias(object): |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
392 """Parsed result of alias""" |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
393 |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
394 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
|
395 self.name = name |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
396 self.args = args |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
397 self.error = err |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
398 self.replacement = replacement |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
399 # 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
|
400 # this avoids showing same warning multiple times at each |
8d398155bfda
revset: rename findaliases() to expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents:
28897
diff
changeset
|
401 # `expandaliases`. |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
402 self.warned = False |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
403 |
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
404 class basealiasrules(object): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
405 """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
|
406 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
407 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
|
408 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
|
409 |
30332
318a24b52eeb
spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents:
29767
diff
changeset
|
410 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
|
411 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
412 # decl = defn |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
413 h = heads(default) |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
414 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
|
415 """ |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
416 # 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
|
417 _section = None |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
418 # 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
|
419 _symbolnode = 'symbol' |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
420 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
421 def __new__(cls): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
422 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
|
423 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
424 @staticmethod |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
425 def _parse(spec): |
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
426 """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
|
427 raise NotImplementedError |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
428 |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28720
diff
changeset
|
429 @staticmethod |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
430 def _trygetfunc(tree): |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
431 """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
|
432 raise NotImplementedError |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
433 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
434 @classmethod |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
435 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
|
436 """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
|
437 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
438 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
|
439 by ``_parse()``. |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
440 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
441 - ``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
|
442 - ``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
|
443 - ``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
|
444 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
445 >>> 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
|
446 >>> 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
|
447 >>> 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
|
448 >>> parsemap = { |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
449 ... 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
|
450 ... 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
|
451 ... 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
|
452 ... 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
|
453 ... 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
|
454 ... 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
|
455 ... 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
|
456 ... 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
|
457 ... 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
|
458 ... 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
|
459 ... 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
|
460 ... 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
|
461 ... (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
|
462 ... 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
|
463 ... 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
|
464 ... 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
|
465 ... 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
|
466 ... } |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
467 >>> def parse(expr): |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
468 ... x = parsemap[expr] |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
469 ... if isinstance(x, Exception): |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
470 ... raise x |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
471 ... return x |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
472 >>> def trygetfunc(tree): |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
473 ... 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
|
474 ... return None |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
475 ... if not tree[2]: |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
476 ... 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
|
477 ... 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
|
478 ... 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
|
479 ... 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
|
480 >>> class aliasrules(basealiasrules): |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
481 ... _parse = staticmethod(parse) |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
482 ... _trygetfunc = staticmethod(trygetfunc) |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
483 >>> builddecl = aliasrules._builddecl |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
484 >>> builddecl(b'foo') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
485 ('foo', None, None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
486 >>> builddecl(b'$foo') |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
487 ('$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
|
488 >>> 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
|
489 ('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
|
490 >>> builddecl(b'foo()') |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
491 ('foo', [], None) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
492 >>> builddecl(b'$foo()') |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
493 ('$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
|
494 >>> 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
|
495 ('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
|
496 >>> 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
|
497 ('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
|
498 >>> 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
|
499 ('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
|
500 >>> 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
|
501 ('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
|
502 >>> 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
|
503 ('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
|
504 >>> 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
|
505 ('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
|
506 >>> 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
|
507 ('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
|
508 >>> 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
|
509 ('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
|
510 """ |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
511 try: |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
512 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
|
513 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
|
514 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
|
515 |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
516 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
|
517 # "name = ...." style |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
518 name = tree[1] |
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
519 if name.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
520 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
|
521 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
|
522 |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
523 func = cls._trygetfunc(tree) |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
524 if func: |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
525 # "name(arg, ....) = ...." style |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
526 name, args = func |
28871
6d6201fc5aae
parser: move alias declaration parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28870
diff
changeset
|
527 if name.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
528 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
|
529 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
|
530 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
|
531 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
|
532 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
|
533 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
|
534 |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
535 return (decl, None, _("invalid format")) |
28872
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
536 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
537 @classmethod |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
538 def _relabelargs(cls, tree, args): |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
539 """Mark alias arguments as ``_aliasarg``""" |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
540 if not isinstance(tree, tuple): |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
541 return tree |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
542 op = tree[0] |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
543 if op != cls._symbolnode: |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
544 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
|
545 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
546 assert len(tree) == 2 |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
547 sym = tree[1] |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
548 if sym in args: |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
549 op = '_aliasarg' |
5f31d2248745
parser: move _relabelaliasargs() to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28871
diff
changeset
|
550 elif sym.startswith('$'): |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
551 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
|
552 return (op, sym) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
553 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
554 @classmethod |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
555 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
|
556 """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
|
557 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
558 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
|
559 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
|
560 |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
561 ``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
|
562 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
|
563 |
34137
a8994d08e4a2
doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents:
34131
diff
changeset
|
564 >>> from . import pycompat |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
565 >>> parsemap = { |
34131
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': (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
|
567 ... b'$1 or $bar': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
568 ... (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
|
569 ... b'$10 or baz': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
570 ... (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
|
571 ... b'"$1" or "foo"': |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
572 ... (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
|
573 ... } |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
574 >>> class aliasrules(basealiasrules): |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
575 ... _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
|
576 ... _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
|
577 >>> builddefn = aliasrules._builddefn |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
578 >>> 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
|
579 ... 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
|
580 ... 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
|
581 >>> 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
|
582 >>> 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
|
583 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
584 (_aliasarg '$1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
585 (_aliasarg 'foo')) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
586 >>> try: |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
587 ... 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
|
588 ... 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
|
589 ... print(pycompat.sysstr(parseerrordetail(inst))) |
29058
dbed4c4f48ae
parser: rephrase "'$' not for alias arguments" message
Yuya Nishihara <yuya@tcha.org>
parents:
28910
diff
changeset
|
590 invalid symbol '$bar' |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
591 >>> 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
|
592 >>> 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
|
593 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
594 (_aliasarg '$10') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
595 (symbol 'baz')) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34073
diff
changeset
|
596 >>> 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
|
597 (or |
34073
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
598 (string '$1') |
7bbc4e113e5f
parser: stabilize output of prettyformat() by using byte-safe repr()
Yuya Nishihara <yuya@tcha.org>
parents:
34045
diff
changeset
|
599 (string 'foo')) |
28873
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
600 """ |
28875
2e9f5453ab5a
parser: unify parser function of alias declaration and definition
Yuya Nishihara <yuya@tcha.org>
parents:
28873
diff
changeset
|
601 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
|
602 if args: |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
603 args = set(args) |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
604 else: |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
605 args = set() |
2ca3b7c563f3
parser: move alias definition parser to common rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28872
diff
changeset
|
606 return cls._relabelargs(tree, args) |
28892
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
607 |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
608 @classmethod |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
609 def build(cls, decl, defn): |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
610 """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
|
611 repl = efmt = None |
28908
7a772deffa12
parser: drop redundant comparison between alias declaration tree and pattern
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
612 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
|
613 if err: |
29059
8eba4cdcfd81
parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents:
29058
diff
changeset
|
614 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
|
615 else: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
616 try: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
617 repl = cls._builddefn(defn, args) |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
618 except error.ParseError as inst: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
619 err = parseerrordetail(inst) |
29059
8eba4cdcfd81
parser: shorten prefix of alias parsing errors
Yuya Nishihara <yuya@tcha.org>
parents:
29058
diff
changeset
|
620 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
|
621 if err: |
0c135f37c6f8
parser: construct alias object by rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28875
diff
changeset
|
622 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
|
623 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
|
624 |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
625 @classmethod |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
626 def buildmap(cls, items): |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
627 """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
|
628 alias objects""" |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
629 aliases = {} |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
630 for decl, defn in items: |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
631 a = cls.build(decl, defn) |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
632 aliases[a.name] = a |
ee11167fe1da
parser: extract helper that creates a dict of aliases
Yuya Nishihara <yuya@tcha.org>
parents:
28892
diff
changeset
|
633 return aliases |
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 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
636 def _getalias(cls, aliases, tree): |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
637 """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
|
638 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
|
639 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
640 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
|
641 return None |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
642 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
|
643 name = tree[1] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
644 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
|
645 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
|
646 return a, None |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
647 func = cls._trygetfunc(tree) |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
648 if func: |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28909
diff
changeset
|
649 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
|
650 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
|
651 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
|
652 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
|
653 return None |
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 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
656 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
|
657 """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
|
658 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
|
659 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
660 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
|
661 return tree |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
662 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
|
663 sym = tree[1] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
664 return args[sym] |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
665 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
|
666 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
667 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
668 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
|
669 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
|
670 return tree |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
671 r = cls._getalias(aliases, tree) |
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
672 if r is None: |
28896
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
673 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
|
674 for t in tree) |
28909
edbffdc7f6a0
parser: make _getalias() return (alias, pattern-args) pair
Yuya Nishihara <yuya@tcha.org>
parents:
28908
diff
changeset
|
675 a, l = r |
28896
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
676 if a.error: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
677 raise error.Abort(a.error) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
678 if a in expanding: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
679 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
|
680 '"%(name)s" detected') |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
681 % {'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
|
682 # 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
|
683 expanding.append(a) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
684 if a.name not in cache: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
685 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
|
686 cache) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
687 result = cache[a.name] |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
688 expanding.pop() |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
689 if a.args is None: |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
690 return result |
28897
c1f254138f44
parser: add short comment how aliases are expanded in phases
Yuya Nishihara <yuya@tcha.org>
parents:
28896
diff
changeset
|
691 # 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
|
692 if len(l) != len(a.args): |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
693 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
|
694 % len(l)) |
4c76a032ec7e
parser: reorder alias expansion routine to return early
Yuya Nishihara <yuya@tcha.org>
parents:
28895
diff
changeset
|
695 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
|
696 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
|
697 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
698 @classmethod |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
699 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
|
700 """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
|
701 |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
702 '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
|
703 """ |
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28893
diff
changeset
|
704 return cls._expand(aliases, tree, [], {}) |