Show More
@@ -300,24 +300,27 b' def _scantemplate(tmpl, start, stop, quo' | |||||
300 | if quote: |
|
300 | if quote: | |
301 | raise error.ParseError(_(b"unterminated string"), start) |
|
301 | raise error.ParseError(_(b"unterminated string"), start) | |
302 | except error.ParseError as inst: |
|
302 | except error.ParseError as inst: | |
303 | if len(inst.args) > 1: # has location |
|
303 | _addparseerrorhint(inst, tmpl) | |
304 | loc = inst.args[1] |
|
|||
305 | # Offset the caret location by the number of newlines before the |
|
|||
306 | # location of the error, since we will replace one-char newlines |
|
|||
307 | # with the two-char literal r'\n'. |
|
|||
308 | offset = tmpl[:loc].count(b'\n') |
|
|||
309 | tmpl = tmpl.replace(b'\n', br'\n') |
|
|||
310 | # We want the caret to point to the place in the template that |
|
|||
311 | # failed to parse, but in a hint we get a open paren at the |
|
|||
312 | # start. Therefore, we print "loc + 1" spaces (instead of "loc") |
|
|||
313 | # to line up the caret with the location of the error. |
|
|||
314 | inst.hint = ( |
|
|||
315 | tmpl + b'\n' + b' ' * (loc + 1 + offset) + b'^ ' + _(b'here') |
|
|||
316 | ) |
|
|||
317 | raise |
|
304 | raise | |
318 | yield (b'end', None, pos) |
|
305 | yield (b'end', None, pos) | |
319 |
|
306 | |||
320 |
|
307 | |||
|
308 | def _addparseerrorhint(inst, tmpl): | |||
|
309 | if len(inst.args) <= 1: | |||
|
310 | return # no location | |||
|
311 | loc = inst.args[1] | |||
|
312 | # Offset the caret location by the number of newlines before the | |||
|
313 | # location of the error, since we will replace one-char newlines | |||
|
314 | # with the two-char literal r'\n'. | |||
|
315 | offset = tmpl[:loc].count(b'\n') | |||
|
316 | tmpl = tmpl.replace(b'\n', br'\n') | |||
|
317 | # We want the caret to point to the place in the template that | |||
|
318 | # failed to parse, but in a hint we get a open paren at the | |||
|
319 | # start. Therefore, we print "loc + 1" spaces (instead of "loc") | |||
|
320 | # to line up the caret with the location of the error. | |||
|
321 | inst.hint = tmpl + b'\n' + b' ' * (loc + 1 + offset) + b'^ ' + _(b'here') | |||
|
322 | ||||
|
323 | ||||
321 | def _unnesttemplatelist(tree): |
|
324 | def _unnesttemplatelist(tree): | |
322 | """Expand list of templates to node tuple |
|
325 | """Expand list of templates to node tuple | |
323 |
|
326 | |||
@@ -360,22 +363,30 b' def parse(tmpl):' | |||||
360 | return _unnesttemplatelist((b'template', parsed)) |
|
363 | return _unnesttemplatelist((b'template', parsed)) | |
361 |
|
364 | |||
362 |
|
365 | |||
363 |
def |
|
366 | def parseexpr(expr): | |
364 | """Parse a template expression into tree |
|
367 | """Parse a template expression into tree | |
365 |
|
368 | |||
366 |
>>> |
|
369 | >>> parseexpr(b'"foo"') | |
367 | ('string', 'foo') |
|
370 | ('string', 'foo') | |
368 |
>>> |
|
371 | >>> parseexpr(b'foo(bar)') | |
369 | ('func', ('symbol', 'foo'), ('symbol', 'bar')) |
|
372 | ('func', ('symbol', 'foo'), ('symbol', 'bar')) | |
370 |
>>> |
|
373 | >>> parseexpr(b'foo(') | |
371 | Traceback (most recent call last): |
|
374 | Traceback (most recent call last): | |
372 | ... |
|
375 | ... | |
373 | ParseError: ('not a prefix: end', 4) |
|
376 | ParseError: ('not a prefix: end', 4) | |
374 |
>>> |
|
377 | >>> parseexpr(b'"foo" "bar"') | |
375 | Traceback (most recent call last): |
|
378 | Traceback (most recent call last): | |
376 | ... |
|
379 | ... | |
377 | ParseError: ('invalid token', 7) |
|
380 | ParseError: ('invalid token', 7) | |
378 | """ |
|
381 | """ | |
|
382 | try: | |||
|
383 | return _parseexpr(expr) | |||
|
384 | except error.ParseError as inst: | |||
|
385 | _addparseerrorhint(inst, expr) | |||
|
386 | raise | |||
|
387 | ||||
|
388 | ||||
|
389 | def _parseexpr(expr): | |||
379 | p = parser.parser(elements) |
|
390 | p = parser.parser(elements) | |
380 | tree, pos = p.parse(tokenize(expr, 0, len(expr))) |
|
391 | tree, pos = p.parse(tokenize(expr, 0, len(expr))) | |
381 | if pos != len(expr): |
|
392 | if pos != len(expr): |
General Comments 0
You need to be logged in to leave comments.
Login now