Show More
@@ -267,6 +267,40 b' def getargs(x, min, max, err):' | |||||
267 | raise error.ParseError(err) |
|
267 | raise error.ParseError(err) | |
268 | return l |
|
268 | return l | |
269 |
|
269 | |||
|
270 | def isvalidsymbol(tree): | |||
|
271 | """Examine whether specified ``tree`` is valid ``symbol`` or not | |||
|
272 | """ | |||
|
273 | return tree[0] == 'symbol' and len(tree) > 1 | |||
|
274 | ||||
|
275 | def getsymbol(tree): | |||
|
276 | """Get symbol name from valid ``symbol`` in ``tree`` | |||
|
277 | ||||
|
278 | This assumes that ``tree`` is already examined by ``isvalidsymbol``. | |||
|
279 | """ | |||
|
280 | return tree[1] | |||
|
281 | ||||
|
282 | def isvalidfunc(tree): | |||
|
283 | """Examine whether specified ``tree`` is valid ``func`` or not | |||
|
284 | """ | |||
|
285 | return tree[0] == 'func' and len(tree) > 1 and isvalidsymbol(tree[1]) | |||
|
286 | ||||
|
287 | def getfuncname(tree): | |||
|
288 | """Get function name from valid ``func`` in ``tree`` | |||
|
289 | ||||
|
290 | This assumes that ``tree`` is already examined by ``isvalidfunc``. | |||
|
291 | """ | |||
|
292 | return getsymbol(tree[1]) | |||
|
293 | ||||
|
294 | def getfuncargs(tree): | |||
|
295 | """Get list of function arguments from valid ``func`` in ``tree`` | |||
|
296 | ||||
|
297 | This assumes that ``tree`` is already examined by ``isvalidfunc``. | |||
|
298 | """ | |||
|
299 | if len(tree) > 2: | |||
|
300 | return getlist(tree[2]) | |||
|
301 | else: | |||
|
302 | return [] | |||
|
303 | ||||
270 | def getset(repo, subset, x): |
|
304 | def getset(repo, subset, x): | |
271 | if not x: |
|
305 | if not x: | |
272 | raise error.ParseError(_("missing argument")) |
|
306 | raise error.ParseError(_("missing argument")) | |
@@ -2118,6 +2152,87 b' def _checkaliasarg(tree, known=None):' | |||||
2118 | for t in tree: |
|
2152 | for t in tree: | |
2119 | _checkaliasarg(t, known) |
|
2153 | _checkaliasarg(t, known) | |
2120 |
|
2154 | |||
|
2155 | # the set of valid characters for the initial letter of symbols in | |||
|
2156 | # alias declarations and definitions | |||
|
2157 | _aliassyminitletters = set(c for c in [chr(i) for i in xrange(256)] | |||
|
2158 | if c.isalnum() or c in '._@$' or ord(c) > 127) | |||
|
2159 | ||||
|
2160 | def _tokenizealias(program, lookup=None): | |||
|
2161 | """Parse alias declaration/definition into a stream of tokens | |||
|
2162 | ||||
|
2163 | This allows symbol names to use also ``$`` as an initial letter | |||
|
2164 | (for backward compatibility), and callers of this function should | |||
|
2165 | examine whether ``$`` is used also for unexpected symbols or not. | |||
|
2166 | """ | |||
|
2167 | return tokenize(program, lookup=lookup, | |||
|
2168 | syminitletters=_aliassyminitletters) | |||
|
2169 | ||||
|
2170 | def _parsealiasdecl(decl): | |||
|
2171 | """Parse alias declaration ``decl`` | |||
|
2172 | ||||
|
2173 | This returns ``(name, tree, args, errorstr)`` tuple: | |||
|
2174 | ||||
|
2175 | - ``name``: of declared alias (may be ``decl`` itself at error) | |||
|
2176 | - ``tree``: parse result (or ``None`` at error) | |||
|
2177 | - ``args``: list of alias argument names (or None for symbol declaration) | |||
|
2178 | - ``errorstr``: detail about detected error (or None) | |||
|
2179 | ||||
|
2180 | >>> _parsealiasdecl('foo') | |||
|
2181 | ('foo', ('symbol', 'foo'), None, None) | |||
|
2182 | >>> _parsealiasdecl('$foo') | |||
|
2183 | ('$foo', None, None, "'$' not for alias arguments") | |||
|
2184 | >>> _parsealiasdecl('foo::bar') | |||
|
2185 | ('foo::bar', None, None, 'invalid format') | |||
|
2186 | >>> _parsealiasdecl('foo bar') | |||
|
2187 | ('foo bar', None, None, 'at 4: invalid token') | |||
|
2188 | >>> _parsealiasdecl('foo()') | |||
|
2189 | ('foo', ('func', ('symbol', 'foo')), [], None) | |||
|
2190 | >>> _parsealiasdecl('$foo()') | |||
|
2191 | ('$foo()', None, None, "'$' not for alias arguments") | |||
|
2192 | >>> _parsealiasdecl('foo($1, $2)') | |||
|
2193 | ('foo', ('func', ('symbol', 'foo')), ['$1', '$2'], None) | |||
|
2194 | >>> _parsealiasdecl('foo(bar_bar, baz.baz)') | |||
|
2195 | ('foo', ('func', ('symbol', 'foo')), ['bar_bar', 'baz.baz'], None) | |||
|
2196 | >>> _parsealiasdecl('foo($1, $2, nested($1, $2))') | |||
|
2197 | ('foo($1, $2, nested($1, $2))', None, None, 'invalid argument list') | |||
|
2198 | >>> _parsealiasdecl('foo(bar($1, $2))') | |||
|
2199 | ('foo(bar($1, $2))', None, None, 'invalid argument list') | |||
|
2200 | >>> _parsealiasdecl('foo("string")') | |||
|
2201 | ('foo("string")', None, None, 'invalid argument list') | |||
|
2202 | >>> _parsealiasdecl('foo($1, $2') | |||
|
2203 | ('foo($1, $2', None, None, 'at 10: unexpected token: end') | |||
|
2204 | >>> _parsealiasdecl('foo("string') | |||
|
2205 | ('foo("string', None, None, 'at 5: unterminated string') | |||
|
2206 | """ | |||
|
2207 | p = parser.parser(_tokenizealias, elements) | |||
|
2208 | try: | |||
|
2209 | tree, pos = p.parse(decl) | |||
|
2210 | if (pos != len(decl)): | |||
|
2211 | raise error.ParseError(_('invalid token'), pos) | |||
|
2212 | ||||
|
2213 | if isvalidsymbol(tree): | |||
|
2214 | # "name = ...." style | |||
|
2215 | name = getsymbol(tree) | |||
|
2216 | if name.startswith('$'): | |||
|
2217 | return (decl, None, None, _("'$' not for alias arguments")) | |||
|
2218 | return (name, ('symbol', name), None, None) | |||
|
2219 | ||||
|
2220 | if isvalidfunc(tree): | |||
|
2221 | # "name(arg, ....) = ...." style | |||
|
2222 | name = getfuncname(tree) | |||
|
2223 | if name.startswith('$'): | |||
|
2224 | return (decl, None, None, _("'$' not for alias arguments")) | |||
|
2225 | args = [] | |||
|
2226 | for arg in getfuncargs(tree): | |||
|
2227 | if not isvalidsymbol(arg): | |||
|
2228 | return (decl, None, None, _("invalid argument list")) | |||
|
2229 | args.append(getsymbol(arg)) | |||
|
2230 | return (name, ('func', ('symbol', name)), args, None) | |||
|
2231 | ||||
|
2232 | return (decl, None, None, _("invalid format")) | |||
|
2233 | except error.ParseError, inst: | |||
|
2234 | return (decl, None, None, parseerrordetail(inst)) | |||
|
2235 | ||||
2121 | class revsetalias(object): |
|
2236 | class revsetalias(object): | |
2122 | funcre = re.compile('^([^(]+)\(([^)]+)\)$') |
|
2237 | funcre = re.compile('^([^(]+)\(([^)]+)\)$') | |
2123 | args = None |
|
2238 | args = None |
General Comments 0
You need to be logged in to leave comments.
Login now