src/blib2to3/pytree.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # Copyright 2006 Google, Inc. All Rights Reserved.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # Licensed to PSF under a Contributor Agreement.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Python parse tree definitions.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | This is a very concrete parse tree; we need to keep every token and
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | even the comments and whitespace between tokens.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | There's also a pattern matching implementation here.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | # mypy: allow-untyped-defs, allow-incomplete-defs
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from typing import (
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Any,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Dict,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Iterable,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Iterator,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | List,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Optional,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Set,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Tuple,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | TypeVar,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Union,
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | )
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from blib2to3.pgen2.grammar import Grammar
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | __author__ = "Guido van Rossum <guido@python.org>"
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import sys
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from io import StringIO
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | HUGE: int = 0x7FFFFFFF # maximum repeat count, default max
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | _type_reprs: Dict[int, Union[str, int]] = {}
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | def type_repr(type_num: int) -> Union[str, int]:
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | global _type_reprs
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | if not _type_reprs:
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | from .pygram import python_symbols
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 |
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | # printing tokens is possible but not as useful
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | # from .pgen2 import token // token.__dict__.items():
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | for name in dir(python_symbols):
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | val = getattr(python_symbols, name)
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | if type(val) == int:
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | _type_reprs[val] = name
0012 0009 0009 0002 0000 0001 0002 -- 04 002 003 002 003 005 005 0011.61 0011.61 0001.00 | return _type_reprs.setdefault(type_num, type_num)
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | _P = TypeVar("_P", bound="Base")
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | NL = Union["Node", "Leaf"]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Context = Tuple[str, Tuple[int, int]]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | RawNode = Tuple[int, Optional[str], Optional[Context], Optional[List[NL]]]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | class Base:
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | Abstract base class for Node and Leaf.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | This provides some default functionality and boilerplate using the
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | template pattern.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | A node may be a subnode of at most one parent.
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | # Default values for instance variables
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | type: int # int: token number (< 256) or symbol number (>= 256)
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | parent: Optional["Node"] = None # Parent node pointer, or None
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | children: List[NL] # List of subnodes
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | was_changed: bool = False
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | was_checked: bool = False
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0004 0004 0003 0000 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __new__(cls, *args, **kwds):
0004 0004 0003 0000 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Constructor that prevents Base from being instantiated."""
0004 0004 0003 0000 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert cls is not Base, "Cannot instantiate Base"
0004 0004 0003 0000 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return object.__new__(cls)
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | def __eq__(self, other: Any) -> bool:
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | """
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | Compare two nodes for equality.
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 |
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | This calls the method _eq().
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | """
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | if self.__class__ is not other.__class__:
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | return NotImplemented
0009 0005 0004 0000 0004 0001 0000 03 02 001 001 001 002 002 003 0003.00 0003.00 0001.00 | return self._eq(other)
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | @property
0003 0003 0003 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def prefix(self) -> str:
0003 0003 0003 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
0003 0003 0003 0000 0000 0000 0000 03 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _eq(self: _P, other: _P) -> bool:
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Compare two nodes for equality.
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This is called by __eq__ and __ne__. It is only called if the two nodes
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | have the same type. This must be implemented by the concrete subclass.
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Nodes should be considered equal if they have the same structure,
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | ignoring the prefix string and other context information.
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0003 0002 0000 0007 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0002 0002 0002 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def __deepcopy__(self: _P, memo: Any) -> _P:
0002 0002 0002 0000 0000 0000 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return self.clone()
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def clone(self: _P) -> _P:
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Return a cloned (deep) copy of self.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This must be implemented by the concrete subclass.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def post_order(self) -> Iterator[NL]:
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Return a post-order iterator for the tree.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This must be implemented by the concrete subclass.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def pre_order(self) -> Iterator[NL]:
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Return a pre-order iterator for the tree.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This must be implemented by the concrete subclass.
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | def replace(self, new: Union[NL, List[NL]]) -> None:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | """Replace this node with a new one in the parent."""
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | assert self.parent is not None, str(self)
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | assert new is not None
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | if not isinstance(new, list):
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | new = [new]
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | l_children = []
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | found = False
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | for ch in self.parent.children:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | if ch is self:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | assert not found, (self.parent.children, self, new)
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | if new is not None:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | l_children.extend(new)
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | found = True
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | else:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | l_children.append(ch)
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | assert found, (self.children, self, new)
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | self.parent.children = l_children
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | self.parent.changed()
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | self.parent.invalidate_sibling_maps()
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | for x in new:
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | x.parent = self.parent
0023 0023 0022 0000 0000 0000 0001 03 06 003 007 006 010 010 016 0053.15 0113.89 0002.14 | self.parent = None
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | def get_lineno(self) -> Optional[int]:
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | """Return the line number which generated the invocant node."""
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | node = self
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | while not isinstance(node, Leaf):
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | if not node.children:
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | return None
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | node = node.children[0]
0008 0008 0007 0000 0000 0000 0001 03 03 001 002 002 002 003 004 0006.34 0003.17 0000.50 | return node.lineno
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def changed(self) -> None:
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | if self.was_changed:
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | if self.parent:
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.parent.changed()
0006 0006 0006 0000 0000 0000 0000 03 03 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.was_changed = True
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def remove(self) -> Optional[int]:
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Remove the node from the tree. Returns the position of the node in its
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | parent's children before it was removed.
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if self.parent:
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | for i, node in enumerate(self.parent.children):
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if node is self:
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | del self.parent.children[i]
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.parent.changed()
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.parent.invalidate_sibling_maps()
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.parent = None
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return i
0014 0011 0010 0000 0004 0000 0000 03 04 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return None
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | @property
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | def next_sibling(self) -> Optional[NL]:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | """
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | The node immediately following the invocant in their parent's children
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | list. If the invocant does not have a next sibling, it is None
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | """
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | if self.parent is None:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | return None
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 |
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | if self.parent.next_sibling_map is None:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | self.parent.update_sibling_maps()
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | assert self.parent.next_sibling_map is not None
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | return self.parent.next_sibling_map[id(self)]
0013 0009 0008 0000 0004 0001 0000 03 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | @property
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | def prev_sibling(self) -> Optional[NL]:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | """
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | The node immediately preceding the invocant in their parent's children
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | list. If the invocant does not have a previous sibling, it is None.
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | """
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | if self.parent is None:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | return None
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 |
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | if self.parent.prev_sibling_map is None:
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | self.parent.update_sibling_maps()
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | assert self.parent.prev_sibling_map is not None
0013 0009 0008 0000 0004 0001 0000 03 03 002 003 003 006 005 009 0020.90 0041.79 0002.00 | return self.parent.prev_sibling_map[id(self)]
0013 0009 0008 0000 0004 0001 0000 03 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0003 0000 0000 0000 0000 03 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def leaves(self) -> Iterator["Leaf"]:
0003 0003 0003 0000 0000 0000 0000 03 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for child in self.children:
0003 0003 0003 0000 0000 0000 0000 03 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield from child.leaves()
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0004 0004 0004 0000 0000 0000 0000 03 02 002 004 002 004 006 006 0015.51 0015.51 0001.00 | def depth(self) -> int:
0004 0004 0004 0000 0000 0000 0000 03 02 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if self.parent is None:
0004 0004 0004 0000 0000 0000 0000 03 02 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return 0
0004 0004 0004 0000 0000 0000 0000 03 02 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return 1 + self.parent.depth()
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def get_suffix(self) -> str:
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Return the string immediately following the invocant node. This is
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | effectively equivalent to node.next_sibling.prefix
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | next_sib = self.next_sibling
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if next_sib is None:
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return ""
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | prefix = next_sib.prefix
0010 0007 0006 0000 0004 0000 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return prefix
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | class Node(Base):
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """Concrete implementation for interior nodes."""
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | fixers_applied: Optional[List[Any]]
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | used_names: Optional[Set[str]]
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | def __init__(
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self,
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | type: int,
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | children: List[NL],
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | context: Optional[Any] = None,
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | prefix: Optional[str] = None,
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | fixers_applied: Optional[List[Any]] = None,
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | ) -> None:
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | """
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | Initializer.
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 |
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | Takes a type constant (a symbol number >= 256), a sequence of
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | child nodes, and an optional context keyword argument.
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 |
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | As a side effect, the parent pointers of the children are updated.
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | """
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | assert type >= 256, type
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.type = type
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.children = list(children)
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | for ch in self.children:
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | assert ch.parent is None, repr(ch)
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | ch.parent = self
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.invalidate_sibling_maps()
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | if prefix is not None:
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.prefix = prefix
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | if fixers_applied:
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.fixers_applied = fixers_applied[:]
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | else:
0029 0016 0021 0000 0006 0002 0000 02 04 003 005 003 006 008 009 0027.00 0048.60 0001.80 | self.fixers_applied = None
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __repr__(self) -> str:
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Return a canonical string representation."""
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert self.type is not None
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return "{}({}, {!r})".format(
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.__class__.__name__,
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | type_repr(self.type),
0008 0004 0007 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.children,
0008 0004 0007 0000 0000 0000 0001 02 -- 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def __str__(self) -> str:
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Return a pretty string representation.
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This reproduces the input source exactly.
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return "".join(map(str, self.children))
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _eq(self, other: Base) -> bool:
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Compare two nodes for equality."""
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return (self.type, self.children) == (other.type, other.children)
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def clone(self) -> "Node":
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert self.type is not None
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Return a cloned (deep) copy of self."""
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return Node(
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.type,
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | [ch.clone() for ch in self.children],
0008 0004 0007 0000 0000 0000 0001 02 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | fixers_applied=self.fixers_applied,
0008 0004 0007 0000 0000 0000 0001 02 -- 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def post_order(self) -> Iterator[NL]:
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Return a post-order iterator for the tree."""
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for child in self.children:
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield from child.post_order()
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield self
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def pre_order(self) -> Iterator[NL]:
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Return a pre-order iterator for the tree."""
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield self
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for child in self.children:
0005 0005 0004 0000 0000 0000 0001 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield from child.pre_order()
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | @property
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | def prefix(self) -> str:
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | The whitespace and comments preceding this node in the input.
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | if not self.children:
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | return ""
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | return self.children[0].prefix
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | @prefix.setter
0004 0004 0004 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def prefix(self, prefix: str) -> None:
0004 0004 0004 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | if self.children:
0004 0004 0004 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.children[0].prefix = prefix
0004 0004 0004 0000 0000 0000 0000 02 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def set_child(self, i: int, child: NL) -> None:
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Equivalent to 'node.children[i] = child'. This method also sets the
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | child's parent attribute appropriately.
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | child.parent = self
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.children[i].parent = None
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.children[i] = child
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.changed()
0010 0007 0006 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.invalidate_sibling_maps()
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def insert_child(self, i: int, child: NL) -> None:
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Equivalent to 'node.children.insert(i, child)'. This method also sets
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | the child's parent attribute appropriately.
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | child.parent = self
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.children.insert(i, child)
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.changed()
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.invalidate_sibling_maps()
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def append_child(self, child: NL) -> None:
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Equivalent to 'node.children.append(child)'. This method also sets the
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | child's parent attribute appropriately.
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | child.parent = self
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.children.append(child)
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.changed()
0009 0006 0005 0000 0004 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.invalidate_sibling_maps()
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0005 0003 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def invalidate_sibling_maps(self) -> None:
0003 0005 0003 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.prev_sibling_map: Optional[Dict[int, Optional[NL]]] = None
0003 0005 0003 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.next_sibling_map: Optional[Dict[int, Optional[NL]]] = None
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def update_sibling_maps(self) -> None:
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | _prev: Dict[int, Optional[NL]] = {}
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | _next: Dict[int, Optional[NL]] = {}
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.prev_sibling_map = _prev
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.next_sibling_map = _next
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | previous: Optional[NL] = None
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for current in self.children:
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | _prev[id(current)] = previous
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | _next[id(previous)] = current
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | previous = current
0011 0014 0011 0000 0000 0000 0000 02 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | _next[id(current)] = None
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | class Leaf(Base):
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """Concrete implementation for leaf nodes."""
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | # Default values for instance variables
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | value: str
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | fixers_applied: List[Any]
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | bracket_depth: int
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | # Changed later in brackets.py
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | opening_bracket: Optional["Leaf"] = None
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | used_names: Optional[Set[str]]
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | _prefix = "" # Whitespace and comments preceding this token in the input
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | lineno: int = 0 # Line where this token starts in the input
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | column: int = 0 # Column where this token starts in the input
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | # If not None, this Leaf is created by converting a block of fmt off/skip
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | # code, and `fmt_pass_converted_first_leaf` points to the first Leaf in the
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | # converted code.
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | fmt_pass_converted_first_leaf: Optional["Leaf"] = None
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | def __init__(
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | type: int,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | value: str,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | context: Optional[Context] = None,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | prefix: Optional[str] = None,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | fixers_applied: List[Any] = [],
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | opening_bracket: Optional["Leaf"] = None,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | fmt_pass_converted_first_leaf: Optional["Leaf"] = None,
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | ) -> None:
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | """
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | Initializer.
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 |
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | Takes a type constant (a token number < 256), a string value, and an
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | optional context keyword argument.
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | """
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 |
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | assert 0 <= type < 256, type
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | if context is not None:
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self._prefix, (self.lineno, self.column) = context
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.type = type
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.value = value
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | if prefix is not None:
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self._prefix = prefix
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.fixers_applied: Optional[List[Any]] = fixers_applied[:]
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.children = []
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.opening_bracket = opening_bracket
0028 0014 0021 0000 0005 0002 0000 02 03 003 006 004 007 009 011 0034.87 0061.02 0001.75 | self.fmt_pass_converted_first_leaf = fmt_pass_converted_first_leaf
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __repr__(self) -> str:
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Return a canonical string representation."""
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | from .pgen2.token import tok_name
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert self.type is not None
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return "{}({}, {!r})".format(
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.__class__.__name__,
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | tok_name.get(self.type, self.type),
0010 0005 0008 0000 0000 0001 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.value,
0010 0005 0008 0000 0000 0001 0001 02 -- 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __str__(self) -> str:
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Return a pretty string representation.
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | This reproduces the input source exactly.
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0007 0003 0002 0000 0004 0001 0000 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return self._prefix + str(self.value)
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _eq(self, other: "Leaf") -> bool:
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Compare two nodes for equality."""
0003 0003 0002 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return (self.type, self.value) == (other.type, other.value)
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def clone(self) -> "Leaf":
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert self.type is not None
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Return a cloned (deep) copy of self."""
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return Leaf(
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.type,
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.value,
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | (self.prefix, (self.lineno, self.column)),
0009 0004 0008 0000 0000 0000 0001 02 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | fixers_applied=self.fixers_applied,
0009 0004 0008 0000 0000 0000 0001 02 -- 001 002 001 002 003 003 0004.75 0002.38 0000.50 | )
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0002 0002 0002 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def leaves(self) -> Iterator["Leaf"]:
0002 0002 0002 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield self
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def post_order(self) -> Iterator["Leaf"]:
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Return a post-order iterator for the tree."""
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield self
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def pre_order(self) -> Iterator["Leaf"]:
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Return a pre-order iterator for the tree."""
0003 0003 0002 0000 0000 0000 0001 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | yield self
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | @property
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | def prefix(self) -> str:
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | The whitespace and comments preceding this token in the input.
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | return self._prefix
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 02 -- --- --- --- --- --- --- ------- ------- ------- | @prefix.setter
0004 0004 0004 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def prefix(self, prefix: str) -> None:
0004 0004 0004 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.changed()
0004 0004 0004 0000 0000 0000 0000 02 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self._prefix = prefix
0004 0004 0004 0000 0000 0000 0000 -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | def convert(gr: Grammar, raw_node: RawNode) -> NL:
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | """
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | Convert raw node information to a Node or Leaf instance.
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 |
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | This is passed to the parser driver which calls it whenever a reduction of a
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | grammar rule produces a new complete node, so that the tree is build
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | strictly bottom-up.
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | """
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | type, value, context, children = raw_node
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | if children or type in gr.number2symbol:
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | # If there's exactly one child, return that child instead of
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | # creating a new node.
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | assert children is not None
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | if len(children) == 1:
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | return children[0]
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | return Node(type, children, context=context)
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | else:
0018 0010 0009 0002 0006 0001 0002 -- 05 004 009 005 010 013 015 0055.51 0123.35 0002.22 | return Leaf(type, value or "", context=context)
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | _Results = Dict[str, NL]
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | class BasePattern:
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | A pattern is a tree matching pattern.
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | It looks for a specific node type (token or symbol), and
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | optionally for a specific content.
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | This is an abstract base class. There are three concrete
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | subclasses:
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | - LeafPattern matches a single leaf node;
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | - NodePattern matches a single node (usually non-leaf);
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | - WildcardPattern matches a sequence of nodes of variable length.
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | # Defaults for instance variables
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | type: Optional[int]
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | type = None # Node type (token if < 256, symbol if >= 256)
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | content: Any = None # Optional content matching pattern
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- | name: Optional[str] = None # Optional name used to store match in results dict
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0004 0004 0003 0000 0000 0000 0001 04 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __new__(cls, *args, **kwds):
0004 0004 0003 0000 0000 0000 0001 04 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """Constructor that prevents BasePattern from being instantiated."""
0004 0004 0003 0000 0000 0000 0001 04 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert cls is not BasePattern, "Cannot instantiate BasePattern"
0004 0004 0003 0000 0000 0000 0001 04 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return object.__new__(cls)
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | def __repr__(self) -> str:
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | assert self.type is not None
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | args = [type_repr(self.type), self.content, self.name]
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | while args and args[-1] is None:
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | del args[-1]
0006 0006 0006 0000 0000 0000 0000 04 03 004 006 005 008 010 013 0043.19 0115.16 0002.67 | return "{}({})".format(self.__class__.__name__, ", ".join(map(repr, args)))
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0002 0002 0002 0000 0000 0000 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _submatch(self, node, results=None) -> bool:
0002 0002 0002 0000 0000 0000 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | raise NotImplementedError
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def optimize(self) -> "BasePattern":
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | A subclass can define this as a hook for optimizations.
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Returns either self or another node with the same effect.
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0007 0003 0002 0000 0004 0001 0000 04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return self
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | def match(self, node: NL, results: Optional[_Results] = None) -> bool:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | """
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | Does this pattern exactly match a node?
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 |
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | Returns True if it matches, False if not.
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 |
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | If results is not None, it must be a dict which will be
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | updated with the nodes matching named subpatterns.
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 |
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | Default implementation for non-wildcard patterns.
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | """
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if self.type is not None and node.type != self.type:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | return False
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if self.content is not None:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | r: Optional[_Results] = None
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if results is not None:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | r = {}
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if not self._submatch(node, r):
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | return False
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if r:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | assert results is not None
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | results.update(r)
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | if results is not None and self.name:
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | results[self.name] = node
0025 0017 0015 0000 0007 0003 0000 04 09 004 009 009 017 013 026 0096.21 0363.47 0003.78 | return True
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def match_seq(self, nodes: List[NL], results: Optional[_Results] = None) -> bool:
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Does this pattern exactly match a sequence of nodes?
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Default implementation for non-wildcard patterns.
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if len(nodes) != 1:
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return False
0009 0005 0004 0000 0004 0001 0000 04 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return self.match(nodes[0], results)
---- ---- ---- ---- ---- ---- ---- 04 -- --- --- --- --- --- --- ------- ------- ------- |
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def generate_matches(self, nodes: List[NL]) -> Iterator[Tuple[int, _Results]]:
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Generator yielding all matches for this pattern.
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Default implementation for non-wildcard patterns.
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | r: _Results = {}
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if nodes and self.match(nodes[0], r):
0009 0006 0004 0000 0004 0001 0000 04 03 001 002 001 002 003 003 0004.75 0002.38 0000.50 | yield 1, r
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | class LeafPattern(BasePattern):
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | def __init__(
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self,
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | type: Optional[int] = None,
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | content: Optional[str] = None,
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | name: Optional[str] = None,
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | ) -> None:
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | """
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | Initializer. Takes optional type, content, and name.
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | The type, if given must be a token type (< 256). If not given,
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | this matches any *leaf* node; the content may still be required.
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | The content, if given, must be a string.
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | If a name is given, the matching node is stored in the results
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | dict under that key.
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | """
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | if type is not None:
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | assert 0 <= type < 256, type
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | if content is not None:
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | assert isinstance(content, str), repr(content)
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.type = type
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.content = content
0024 0009 0013 0000 0008 0003 0000 03 03 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.name = name
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0005 0005 0004 0000 0000 0000 0001 03 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | def match(self, node: NL, results=None) -> bool:
0005 0005 0004 0000 0000 0000 0001 03 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | """Override match() to insist on a leaf node."""
0005 0005 0004 0000 0000 0000 0001 03 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | if not isinstance(node, Leaf):
0005 0005 0004 0000 0000 0000 0001 03 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | return False
0005 0005 0004 0000 0000 0000 0001 03 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 | return BasePattern.match(self, node, results)
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def _submatch(self, node, results=None):
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Match the pattern's content to the node's children.
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | This assumes the node type matches and self.content is not None.
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Returns True if it matches, False if not.
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | If results is not None, it must be a dict which will be
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | updated with the nodes matching named subpatterns.
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | When returning False, the results dict may still be updated.
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0014 0003 0002 0000 0008 0004 0000 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return self.content == node.value
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | class NodePattern(BasePattern):
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | wildcards: bool = False
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | def __init__(
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self,
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | type: Optional[int] = None,
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | content: Optional[Iterable[str]] = None,
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | name: Optional[str] = None,
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | ) -> None:
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | """
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | Initializer. Takes optional type, content, and name.
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | The type, if given, must be a symbol type (>= 256). If the
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | type is None this matches *any* single node (leaf or not),
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | except if content is not None, in which it only matches
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | non-leaf nodes that also match the content pattern.
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | The content, if not None, must be a sequence of Patterns that
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | must match the node's children exactly. If the content is
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | given, the type must not be None.
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 |
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | If a name is given, the matching node is stored in the results
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | dict under that key.
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | """
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | if type is not None:
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | assert type >= 256, type
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | if content is not None:
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | assert not isinstance(content, str), repr(content)
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | newcontent = list(content)
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | for i, item in enumerate(newcontent):
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | assert isinstance(item, BasePattern), (i, item)
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | # I don't even think this code is used anywhere, but it does cause
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | # unreachable errors from mypy. This function's signature does look
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | # odd though *shrug*.
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | if isinstance(item, WildcardPattern): # type: ignore[unreachable]
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.wildcards = True # type: ignore[unreachable]
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.type = type
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.content = newcontent # TODO: this is unbound when content is None
0036 0014 0018 0006 0012 0003 0003 08 05 003 005 004 007 008 011 0033.00 0069.30 0002.10 | self.name = name
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | def _submatch(self, node, results=None) -> bool:
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | """
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | Match the pattern's content to the node's children.
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 |
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | This assumes the node type matches and self.content is not None.
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 |
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | Returns True if it matches, False if not.
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 |
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | If results is not None, it must be a dict which will be
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | updated with the nodes matching named subpatterns.
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 |
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | When returning False, the results dict may still be updated.
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | """
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | if self.wildcards:
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | for c, r in generate_matches(self.content, node.children):
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | if c == len(node.children):
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | if results is not None:
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | results.update(r)
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | return True
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | return False
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | if len(self.content) != len(node.children):
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | return False
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | for subpattern, child in zip(self.content, node.children):
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | if not subpattern.match(child, results):
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | return False
0026 0015 0014 0000 0008 0004 0000 08 08 004 007 004 007 011 011 0038.05 0076.11 0002.00 | return True
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | class WildcardPattern(BasePattern):
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | A wildcard pattern can match zero or more nodes.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | This has all the flexibility needed to implement patterns like:
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | .* .+ .? .{m,n}
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | (a b c | d e | f)
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | (...)* (...)+ (...)? (...){m,n}
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | except it always uses non-greedy matching.
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | min: int
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- | max: int
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | def __init__(
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | self,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | content: Optional[str] = None,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min: int = 0,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | max: int = HUGE,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | name: Optional[str] = None,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | ) -> None:
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | """
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | Initializer.
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 |
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | Args:
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | content: optional sequence of subsequences of patterns;
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | if absent, matches one node;
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | if present, each subsequence is an alternative [*]
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min: optional minimum number of times to match, default 0
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | max: optional maximum number of times to match, default HUGE
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | name: optional name assigned to this match
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 |
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | [*] Thus, if content is [[a, b, c], [d, e], [f, g, h]] this is
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | equivalent to (a b c | d e | f g h); if content is None,
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | this is equivalent to '.' in regular expression terms.
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | The min and max parameters work as follows:
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min=0, max=maxint: .*
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min=1, max=maxint: .+
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min=0, max=1: .?
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | min=1, max=1: .
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | If content is not None, replace the dot with the parenthesized
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | list of alternatives, e.g. (a b c | d e | f g h)*
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | """
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | assert 0 <= min <= max <= HUGE, (min, max)
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | if content is not None:
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | f = lambda s: tuple(s)
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | wrapped_content = tuple(map(f, content)) # Protect against alterations
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | # Check sanity of alternatives
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | assert len(wrapped_content), repr(
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | wrapped_content
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | ) # Can't have zero alternatives
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | for alt in wrapped_content:
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | assert len(alt), repr(alt) # Can have empty alternatives
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | self.content = wrapped_content
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | self.min = min
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | self.max = max
0043 0014 0020 0004 0020 0002 0001 08 03 002 006 004 006 008 010 0030.00 0030.00 0001.00 | self.name = name
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | def optimize(self) -> Any:
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | """Optimize certain stacked wildcard patterns."""
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | subpattern = None
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | if (
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | self.content is not None
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | and len(self.content) == 1
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | and len(self.content[0]) == 1
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | ):
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | subpattern = self.content[0][0]
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | if self.min == 1 and self.max == 1:
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | if self.content is None:
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | return NodePattern(name=self.name)
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | if subpattern is not None and self.name == subpattern.name:
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | return subpattern.optimize()
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | if (
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | self.min <= 1
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | and isinstance(subpattern, WildcardPattern)
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | and subpattern.min <= 1
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | and self.name == subpattern.name
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | ):
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | return WildcardPattern(
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | subpattern.content,
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | self.min * subpattern.min,
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | self.max * subpattern.max,
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | subpattern.name,
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | )
0027 0013 0026 0000 0000 0000 0001 08 13 006 020 017 037 026 054 0253.82 1408.72 0005.55 | return self
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0003 0002 0000 0000 0000 0001 08 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def match(self, node, results=None) -> bool:
0003 0003 0002 0000 0000 0000 0001 08 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Does this pattern exactly match a node?"""
0003 0003 0002 0000 0000 0000 0001 08 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return self.match_seq([node], results)
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | def match_seq(self, nodes, results=None) -> bool:
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | """Does this pattern exactly match a sequence of nodes?"""
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | for c, r in self.generate_matches(nodes):
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if c == len(nodes):
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if results is not None:
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results.update(r)
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if self.name:
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results[self.name] = list(nodes)
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return True
0010 0010 0009 0000 0000 0000 0001 08 05 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return False
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | def generate_matches(self, nodes) -> Iterator[Tuple[int, _Results]]:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | """
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | Generator yielding matches for a sequence of nodes.
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 |
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | Args:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | nodes: sequence of nodes
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 |
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | Yields:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | (count, results) tuples where:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | count: the match comprises nodes[:count];
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | results: dict containing named submatches.
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | """
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if self.content is None:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # Shortcut for special case (see __init__.__doc__)
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | for count in range(self.min, 1 + min(len(nodes), self.max)):
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | r = {}
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if self.name:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | r[self.name] = nodes[:count]
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | yield count, r
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | elif self.name == "bare_name":
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | yield self._bare_name_matches(nodes)
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | else:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # The reason for this is that hitting the recursion limit usually
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # results in some ugly messages about how RuntimeErrors are being
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # ignored. We only have to do this on CPython, though, because other
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # implementations don't have this nasty bug in the first place.
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if hasattr(sys, "getrefcount"):
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | save_stderr = sys.stderr
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | sys.stderr = StringIO()
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | try:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | for count, r in self._recursive_matches(nodes, 0):
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if self.name:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | r[self.name] = nodes[:count]
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | yield count, r
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | except RuntimeError:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # We fall back to the iterative pattern matching scheme if the recursive
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | # scheme hits the recursion limit.
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | for count, r in self._iterative_matches(nodes):
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if self.name:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | r[self.name] = nodes[:count]
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | yield count, r
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | finally:
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | if hasattr(sys, "getrefcount"):
0044 0030 0026 0007 0009 0002 0007 08 12 003 006 003 006 009 009 0028.53 0042.79 0001.50 | sys.stderr = save_stderr
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | def _iterative_matches(self, nodes) -> Iterator[Tuple[int, _Results]]:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | """Helper to iteratively yield the matches."""
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | nodelen = len(nodes)
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | if 0 >= self.min:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | yield 0, {}
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 |
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | results = []
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | # generate matches that use just one alt from self.content
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | for alt in self.content:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | for c, r in generate_matches(alt, nodes):
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | yield c, r
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | results.append((c, r))
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 |
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | # for each match, iterate down the nodes
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | while results:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | new_results = []
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | for c0, r0 in results:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | # stop if the entire set of nodes has been matched
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | if c0 < nodelen and c0 <= self.max:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | for alt in self.content:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | for c1, r1 in generate_matches(alt, nodes[c0:]):
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | if c1 > 0:
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | r = {}
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | r.update(r0)
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | r.update(r1)
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | yield c0 + c1, r
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | new_results.append((c0 + c1, r))
0028 0023 0022 0003 0000 0002 0004 08 11 006 008 007 014 014 021 0079.95 0419.76 0005.25 | results = new_results
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | def _bare_name_matches(self, nodes) -> Tuple[int, _Results]:
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | """Special optimized matcher for bare_name."""
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | count = 0
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | r = {} # type: _Results
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | done = False
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | max = len(nodes)
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | while not done and count < max:
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | done = True
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | for leaf in self.content:
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | if leaf[0].match(nodes[count], r):
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | count += 1
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | done = False
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | break
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | assert self.name is not None
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | r[self.name] = nodes[:count]
0016 0017 0015 0001 0000 0000 0001 08 05 005 008 005 009 013 014 0051.81 0145.70 0002.81 | return count, r
---- ---- ---- ---- ---- ---- ---- 08 -- --- --- --- --- --- --- ------- ------- ------- |
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | def _recursive_matches(self, nodes, count) -> Iterator[Tuple[int, _Results]]:
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | """Helper to recursively yield the matches."""
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | assert self.content is not None
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | if count >= self.min:
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | yield 0, {}
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | if count < self.max:
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | for alt in self.content:
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | for c0, r0 in generate_matches(alt, nodes):
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | for c1, r1 in self._recursive_matches(nodes[c0:], count + 1):
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | r = {}
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | r.update(r0)
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | r.update(r1)
0013 0013 0012 0000 0000 0000 0001 08 06 004 008 005 010 012 015 0053.77 0134.44 0002.50 | yield c0 + c1, r
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- | class NegatedPattern(BasePattern):
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def __init__(self, content: Optional[BasePattern] = None) -> None:
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | Initializer.
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | The argument is either a pattern or None. If it is None, this
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | only matches an empty sequence (effectively '$' in regex
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | lingo). If it is not None, this matches whenever the argument
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | pattern doesn't have any matches.
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | """
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | if content is not None:
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | assert isinstance(content, BasePattern), repr(content)
0012 0005 0004 0000 0007 0001 0000 03 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 | self.content = content
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0002 0002 0001 0000 0000 0001 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def match(self, node, results=None) -> bool:
0003 0002 0002 0001 0000 0000 0001 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | # We never match a node in its entirety
0003 0002 0002 0001 0000 0000 0001 03 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return False
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0003 0002 0002 0001 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | def match_seq(self, nodes, results=None) -> bool:
0003 0002 0002 0001 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | # We only match an empty sequence of nodes in its entirety
0003 0002 0002 0001 0000 0000 0001 03 01 001 002 001 002 003 003 0004.75 0002.38 0000.50 | return len(nodes) == 0
---- ---- ---- ---- ---- ---- ---- 03 -- --- --- --- --- --- --- ------- ------- ------- |
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | def generate_matches(self, nodes: List[NL]) -> Iterator[Tuple[int, _Results]]:
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if self.content is None:
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | # Return a match if there is an empty sequence
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if len(nodes) == 0:
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | yield 0, {}
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | else:
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | # Return a match if the argument pattern has no matches
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | for c, r in self.content.generate_matches(nodes):
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return
0010 0008 0008 0002 0000 0000 0002 03 04 002 004 002 004 006 006 0015.51 0015.51 0001.00 | yield 0, {}
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | def generate_matches(
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | patterns: List[BasePattern], nodes: List[NL]
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | ) -> Iterator[Tuple[int, _Results]]:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | """
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | Generator yielding matches for a sequence of patterns and nodes.
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | Args:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | patterns: a sequence of patterns
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | nodes: a sequence of nodes
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | Yields:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | (count, results) tuples where:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | count: the entire sequence of patterns matches nodes[:count];
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | results: dict containing named submatches.
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | """
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | if not patterns:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | yield 0, {}
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | else:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | p, rest = patterns[0], patterns[1:]
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | for c0, r0 in p.generate_matches(nodes):
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | if not rest:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | yield c0, r0
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | else:
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | for c1, r1 in generate_matches(rest, nodes[c0:]):
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | r = {}
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | r.update(r0)
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | r.update(r1)
0028 0016 0016 0000 0010 0002 0000 -- 05 002 004 003 004 006 007 0018.09 0018.09 0001.00 | yield c0 + c1, r