Show More
@@ -151,6 +151,15 def orset(repo, subset, x, order): | |||
|
151 | 151 | def notset(repo, subset, x, order): |
|
152 | 152 | return subset - getset(repo, subset, x) |
|
153 | 153 | |
|
154 | def relationset(repo, subset, x, y, order): | |
|
155 | raise error.ParseError(_("can't use a relation in this context")) | |
|
156 | ||
|
157 | def relsubscriptset(repo, subset, x, y, z, order): | |
|
158 | raise error.ParseError(_("can't use a relation in this context")) | |
|
159 | ||
|
160 | def subscriptset(repo, subset, x, y, order): | |
|
161 | raise error.ParseError(_("can't use a subscript in this context")) | |
|
162 | ||
|
154 | 163 | def listset(repo, subset, *xs): |
|
155 | 164 | raise error.ParseError(_("can't use a list in this context"), |
|
156 | 165 | hint=_('see hg help "revsets.x or y"')) |
@@ -2004,6 +2013,9 methods = { | |||
|
2004 | 2013 | "or": orset, |
|
2005 | 2014 | "not": notset, |
|
2006 | 2015 | "difference": differenceset, |
|
2016 | "relation": relationset, | |
|
2017 | "relsubscript": relsubscriptset, | |
|
2018 | "subscript": subscriptset, | |
|
2007 | 2019 | "list": listset, |
|
2008 | 2020 | "keyvalue": keyvaluepair, |
|
2009 | 2021 | "func": func, |
@@ -21,6 +21,8 from . import ( | |||
|
21 | 21 | elements = { |
|
22 | 22 | # token-type: binding-strength, primary, prefix, infix, suffix |
|
23 | 23 | "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None), |
|
24 | "[": (21, None, None, ("subscript", 1, "]"), None), | |
|
25 | "#": (21, None, None, ("relation", 21), None), | |
|
24 | 26 | "##": (20, None, None, ("_concat", 20), None), |
|
25 | 27 | "~": (18, None, None, ("ancestor", 18), None), |
|
26 | 28 | "^": (18, None, None, ("parent", 18), "parentpost"), |
@@ -39,6 +41,7 elements = { | |||
|
39 | 41 | "=": (3, None, None, ("keyvalue", 3), None), |
|
40 | 42 | ",": (2, None, None, ("list", 2), None), |
|
41 | 43 | ")": (0, None, None, None, None), |
|
44 | "]": (0, None, None, None, None), | |
|
42 | 45 | "symbol": (0, "symbol", None, None, None), |
|
43 | 46 | "string": (0, "string", None, None, None), |
|
44 | 47 | "end": (0, None, None, None, None), |
@@ -47,7 +50,7 elements = { | |||
|
47 | 50 | keywords = {'and', 'or', 'not'} |
|
48 | 51 | |
|
49 | 52 | _quoteletters = {'"', "'"} |
|
50 | _simpleopletters = set(pycompat.iterbytestr("():=,-|&+!~^%")) | |
|
53 | _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%")) | |
|
51 | 54 | |
|
52 | 55 | # default set of valid characters for the initial letter of symbols |
|
53 | 56 | _syminitletters = set(pycompat.iterbytestr( |
@@ -331,6 +334,9 def _fixops(x): | |||
|
331 | 334 | # make number of arguments deterministic: |
|
332 | 335 | # x + y + z -> (or x y z) -> (or (list x y z)) |
|
333 | 336 | return (op, _fixops(('list',) + x[1:])) |
|
337 | elif op == 'subscript' and x[1][0] == 'relation': | |
|
338 | # x#y[z] ternary | |
|
339 | return _fixops(('relsubscript', x[1][1], x[1][2], x[2])) | |
|
334 | 340 | |
|
335 | 341 | return (op,) + tuple(_fixops(y) for y in x[1:]) |
|
336 | 342 | |
@@ -369,10 +375,16 def _analyze(x, order): | |||
|
369 | 375 | return (op, _analyze(x[1], defineorder), order) |
|
370 | 376 | elif op == 'group': |
|
371 | 377 | return _analyze(x[1], order) |
|
372 |
elif op in ('dagrange', 'range', 'parent', 'ancestor' |
|
|
378 | elif op in ('dagrange', 'range', 'parent', 'ancestor', 'relation', | |
|
379 | 'subscript'): | |
|
373 | 380 | ta = _analyze(x[1], defineorder) |
|
374 | 381 | tb = _analyze(x[2], defineorder) |
|
375 | 382 | return (op, ta, tb, order) |
|
383 | elif op == 'relsubscript': | |
|
384 | ta = _analyze(x[1], defineorder) | |
|
385 | tb = _analyze(x[2], defineorder) | |
|
386 | tc = _analyze(x[3], defineorder) | |
|
387 | return (op, ta, tb, tc, order) | |
|
376 | 388 | elif op == 'list': |
|
377 | 389 | return (op,) + tuple(_analyze(y, order) for y in x[1:]) |
|
378 | 390 | elif op == 'keyvalue': |
@@ -481,10 +493,14 def _optimize(x, small): | |||
|
481 | 493 | wb, tb = _optimize(x[2], small) |
|
482 | 494 | order = x[3] |
|
483 | 495 | return wa + wb, (op, ta, tb, order) |
|
484 | elif op in ('parent', 'ancestor'): | |
|
496 | elif op in ('parent', 'ancestor', 'relation', 'subscript'): | |
|
485 | 497 | w, t = _optimize(x[1], small) |
|
486 | 498 | order = x[3] |
|
487 | 499 | return w, (op, t, x[2], order) |
|
500 | elif op == 'relsubscript': | |
|
501 | w, t = _optimize(x[1], small) | |
|
502 | order = x[4] | |
|
503 | return w, (op, t, x[2], x[3], order) | |
|
488 | 504 | elif op == 'list': |
|
489 | 505 | ws, ts = zip(*(_optimize(y, small) for y in x[1:])) |
|
490 | 506 | return sum(ws), (op,) + ts |
@@ -812,7 +812,7 check error cases | |||
|
812 | 812 | abort: line range exceeds file size |
|
813 | 813 | [255] |
|
814 | 814 | $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])' |
|
815 | hg: parse error at 43: syntax error in revset 'followlines(baz, 2:4, startrev=20, descend=[1])' | |
|
815 | hg: parse error at 43: not a prefix: [ | |
|
816 | 816 | [255] |
|
817 | 817 | $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)' |
|
818 | 818 | hg: parse error: descend argument must be a boolean |
@@ -500,6 +500,151 keyword arguments | |||
|
500 | 500 | hg: parse error: can't use a key-value pair in this context |
|
501 | 501 | [255] |
|
502 | 502 | |
|
503 | relation-subscript operator has the highest binding strength (as function call): | |
|
504 | ||
|
505 | $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]' | |
|
506 | * parsed: | |
|
507 | (range | |
|
508 | ('symbol', 'tip') | |
|
509 | (relsubscript | |
|
510 | (parentpost | |
|
511 | ('symbol', 'tip')) | |
|
512 | ('symbol', 'generations') | |
|
513 | (negate | |
|
514 | ('symbol', '1')))) | |
|
515 | hg: parse error: can't use a relation in this context | |
|
516 | [255] | |
|
517 | ||
|
518 | $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]' | |
|
519 | * parsed: | |
|
520 | (not | |
|
521 | (relsubscript | |
|
522 | (func | |
|
523 | ('symbol', 'public') | |
|
524 | None) | |
|
525 | ('symbol', 'generations') | |
|
526 | ('symbol', '0'))) | |
|
527 | hg: parse error: can't use a relation in this context | |
|
528 | [255] | |
|
529 | ||
|
530 | left-hand side of relation-subscript operator should be optimized recursively: | |
|
531 | ||
|
532 | $ hg debugrevspec -p analyzed -p optimized --no-show-revs \ | |
|
533 | > '(not public())#generations[0]' | |
|
534 | * analyzed: | |
|
535 | (relsubscript | |
|
536 | (not | |
|
537 | (func | |
|
538 | ('symbol', 'public') | |
|
539 | None | |
|
540 | any) | |
|
541 | define) | |
|
542 | ('symbol', 'generations') | |
|
543 | ('symbol', '0') | |
|
544 | define) | |
|
545 | * optimized: | |
|
546 | (relsubscript | |
|
547 | (func | |
|
548 | ('symbol', '_notpublic') | |
|
549 | None | |
|
550 | any) | |
|
551 | ('symbol', 'generations') | |
|
552 | ('symbol', '0') | |
|
553 | define) | |
|
554 | hg: parse error: can't use a relation in this context | |
|
555 | [255] | |
|
556 | ||
|
557 | resolution of subscript and relation-subscript ternary operators: | |
|
558 | ||
|
559 | $ hg debugrevspec -p analyzed 'tip[0]' | |
|
560 | * analyzed: | |
|
561 | (subscript | |
|
562 | ('symbol', 'tip') | |
|
563 | ('symbol', '0') | |
|
564 | define) | |
|
565 | hg: parse error: can't use a subscript in this context | |
|
566 | [255] | |
|
567 | ||
|
568 | $ hg debugrevspec -p analyzed 'tip#rel[0]' | |
|
569 | * analyzed: | |
|
570 | (relsubscript | |
|
571 | ('symbol', 'tip') | |
|
572 | ('symbol', 'rel') | |
|
573 | ('symbol', '0') | |
|
574 | define) | |
|
575 | hg: parse error: can't use a relation in this context | |
|
576 | [255] | |
|
577 | ||
|
578 | $ hg debugrevspec -p analyzed '(tip#rel)[0]' | |
|
579 | * analyzed: | |
|
580 | (subscript | |
|
581 | (relation | |
|
582 | ('symbol', 'tip') | |
|
583 | ('symbol', 'rel') | |
|
584 | define) | |
|
585 | ('symbol', '0') | |
|
586 | define) | |
|
587 | hg: parse error: can't use a subscript in this context | |
|
588 | [255] | |
|
589 | ||
|
590 | $ hg debugrevspec -p analyzed 'tip#rel[0][1]' | |
|
591 | * analyzed: | |
|
592 | (subscript | |
|
593 | (relsubscript | |
|
594 | ('symbol', 'tip') | |
|
595 | ('symbol', 'rel') | |
|
596 | ('symbol', '0') | |
|
597 | define) | |
|
598 | ('symbol', '1') | |
|
599 | define) | |
|
600 | hg: parse error: can't use a subscript in this context | |
|
601 | [255] | |
|
602 | ||
|
603 | $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]' | |
|
604 | * analyzed: | |
|
605 | (relsubscript | |
|
606 | (relation | |
|
607 | ('symbol', 'tip') | |
|
608 | ('symbol', 'rel0') | |
|
609 | define) | |
|
610 | ('symbol', 'rel1') | |
|
611 | ('symbol', '1') | |
|
612 | define) | |
|
613 | hg: parse error: can't use a relation in this context | |
|
614 | [255] | |
|
615 | ||
|
616 | $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]' | |
|
617 | * analyzed: | |
|
618 | (relsubscript | |
|
619 | (relsubscript | |
|
620 | ('symbol', 'tip') | |
|
621 | ('symbol', 'rel0') | |
|
622 | ('symbol', '0') | |
|
623 | define) | |
|
624 | ('symbol', 'rel1') | |
|
625 | ('symbol', '1') | |
|
626 | define) | |
|
627 | hg: parse error: can't use a relation in this context | |
|
628 | [255] | |
|
629 | ||
|
630 | parse errors of relation, subscript and relation-subscript operators: | |
|
631 | ||
|
632 | $ hg debugrevspec '[0]' | |
|
633 | hg: parse error at 0: not a prefix: [ | |
|
634 | [255] | |
|
635 | $ hg debugrevspec '.#' | |
|
636 | hg: parse error at 2: not a prefix: end | |
|
637 | [255] | |
|
638 | $ hg debugrevspec '#rel' | |
|
639 | hg: parse error at 0: not a prefix: # | |
|
640 | [255] | |
|
641 | $ hg debugrevspec '.#rel[0' | |
|
642 | hg: parse error at 7: unexpected token: end | |
|
643 | [255] | |
|
644 | $ hg debugrevspec '.]' | |
|
645 | hg: parse error at 1: invalid token | |
|
646 | [255] | |
|
647 | ||
|
503 | 648 | parsed tree at stages: |
|
504 | 649 | |
|
505 | 650 | $ hg debugrevspec -p all '()' |
General Comments 0
You need to be logged in to leave comments.
Login now