antlr3 1.2.4 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/antlr4ruby +1 -13
- data/java/RubyTarget.java +8 -125
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3/constants.rb +2 -0
- data/lib/antlr3/dfa.rb +18 -15
- data/lib/antlr3/error.rb +3 -3
- data/lib/antlr3/main.rb +8 -9
- data/lib/antlr3/modes/ast-builder.rb +24 -4
- data/lib/antlr3/recognizers.rb +17 -16
- data/lib/antlr3/task.rb +13 -0
- data/lib/antlr3/token.rb +53 -17
- data/lib/antlr3/tree.rb +491 -561
- data/lib/antlr3/tree/wizard.rb +139 -127
- data/lib/antlr3/util.rb +7 -1
- data/lib/antlr3/version.rb +4 -4
- data/samples/{Cpp.g → CPP.g} +1 -1
- data/templates/AST.stg +1 -1
- data/templates/Ruby.stg +29 -42
- data/test/functional/ast-output/auto-ast.rb +3 -3
- data/test/functional/ast-output/tree-rewrite.rb +1 -1
- data/test/functional/debugging/debug-mode.rb +2 -2
- data/test/unit/test-tree-wizard.rb +115 -156
- data/test/unit/test-trees.rb +66 -77
- metadata +4 -5
- data/lib/antlr3/test/config.rb +0 -23
- data/lib/antlr3/test/diff.rb +0 -165
data/test/unit/test-trees.rb
CHANGED
@@ -26,7 +26,7 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
26
26
|
|
27
27
|
found.should == expecting
|
28
28
|
|
29
|
-
expecting = '101'
|
29
|
+
expecting = '<UNKNOWN: 101>'
|
30
30
|
found = stream.inspect
|
31
31
|
|
32
32
|
found.should == expecting
|
@@ -68,7 +68,7 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
68
68
|
found = nodes_only_string(stream)
|
69
69
|
found.should == expecting
|
70
70
|
|
71
|
-
expecting = "101
|
71
|
+
expecting = "<UNKNOWN: 101> <DOWN> <UNKNOWN: 102> <DOWN> <UNKNOWN: 103> <UP> <UNKNOWN: 104> <UP>"
|
72
72
|
found = stream.inspect
|
73
73
|
found.should == expecting
|
74
74
|
end
|
@@ -91,7 +91,7 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
91
91
|
found = nodes_only_string(stream)
|
92
92
|
found.should == expecting
|
93
93
|
|
94
|
-
expecting = "101
|
94
|
+
expecting = "<UNKNOWN: 101> <DOWN> <UNKNOWN: 102> <DOWN> <UNKNOWN: 103> <UP> <UNKNOWN: 104> <UP> <UNKNOWN: 105>"
|
95
95
|
found = stream.inspect
|
96
96
|
found.should == expecting
|
97
97
|
end
|
@@ -103,13 +103,13 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
103
103
|
root.add_child(CommonTree.new(CommonToken[102]))
|
104
104
|
root.add_child(CommonTree.new(CommonToken[103]))
|
105
105
|
|
106
|
-
stream = CommonTreeNodeStream.new(root)
|
106
|
+
stream = CommonTreeNodeStream.new( root )
|
107
107
|
|
108
108
|
expecting = '101 102 103'
|
109
109
|
found = nodes_only_string(stream)
|
110
110
|
found.should == expecting
|
111
111
|
|
112
|
-
expecting = '101 102 103'
|
112
|
+
expecting = '<UNKNOWN: 101> <UNKNOWN: 102> <UNKNOWN: 103>'
|
113
113
|
found = stream.inspect
|
114
114
|
found.should == expecting
|
115
115
|
end
|
@@ -125,7 +125,7 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
125
125
|
found = nodes_only_string(stream)
|
126
126
|
found.should == expecting
|
127
127
|
|
128
|
-
expecting =
|
128
|
+
expecting = "<UNKNOWN: 101>"
|
129
129
|
found = stream.inspect
|
130
130
|
found.should == expecting
|
131
131
|
end
|
@@ -139,7 +139,7 @@ class TestTreeNodeStream < Test::Unit::TestCase
|
|
139
139
|
found = nodes_only_string(stream)
|
140
140
|
found.should == expecting
|
141
141
|
|
142
|
-
expecting = '101
|
142
|
+
expecting = '<UNKNOWN: 101> <DOWN> <UNKNOWN: 102> <UP>'
|
143
143
|
found = stream.inspect
|
144
144
|
found.should == expecting
|
145
145
|
end
|
@@ -335,7 +335,9 @@ class TestCommonTreeNodeStream < Test::Unit::TestCase
|
|
335
335
|
r0.add_child new_node( new_token 109 )
|
336
336
|
|
337
337
|
stream = CommonTreeNodeStream.new(r0)
|
338
|
-
expecting = '101
|
338
|
+
expecting = '<UNKNOWN: 101> <DOWN> <UNKNOWN: 102> <DOWN> <UNKNOWN: 103> <UP> <UNKNOWN: 104> ' +
|
339
|
+
'<DOWN> <UNKNOWN: 105> <UP> <UNKNOWN: 106> <DOWN> <UNKNOWN: 107> <UP> ' +
|
340
|
+
'<UNKNOWN: 108> <UNKNOWN: 109> <UP>'
|
339
341
|
found = stream.inspect
|
340
342
|
found.should == expecting
|
341
343
|
|
@@ -557,10 +559,10 @@ class TestCommonTree < Test::Unit::TestCase
|
|
557
559
|
r0.add_child( new_node( new_token 104 ) )
|
558
560
|
r0.add_child( new_node( new_token 105 ) )
|
559
561
|
|
560
|
-
dup = @adaptor.copy_tree(r0)
|
562
|
+
dup = @adaptor.copy_tree( r0 )
|
561
563
|
assert_nil dup.parent
|
562
564
|
dup.child_index.should == -1
|
563
|
-
dup.
|
565
|
+
dup.sanity_check
|
564
566
|
end
|
565
567
|
|
566
568
|
def test_become_root
|
@@ -572,7 +574,7 @@ class TestCommonTree < Test::Unit::TestCase
|
|
572
574
|
old_root.add_child( new_node( new_token 103 ) )
|
573
575
|
|
574
576
|
@adaptor.become_root(new_root, old_root)
|
575
|
-
new_root.
|
577
|
+
new_root.sanity_check
|
576
578
|
end
|
577
579
|
|
578
580
|
def test_become_root2
|
@@ -583,7 +585,7 @@ class TestCommonTree < Test::Unit::TestCase
|
|
583
585
|
old_root.add_child( new_node( new_token 103 ) )
|
584
586
|
|
585
587
|
@adaptor.become_root(new_root, old_root)
|
586
|
-
new_root.
|
588
|
+
new_root.sanity_check
|
587
589
|
end
|
588
590
|
|
589
591
|
def test_become_root3
|
@@ -596,7 +598,7 @@ class TestCommonTree < Test::Unit::TestCase
|
|
596
598
|
old_root.add_child( new_node( new_token 103 ) )
|
597
599
|
|
598
600
|
@adaptor.become_root(new_root, old_root)
|
599
|
-
new_root.
|
601
|
+
new_root.sanity_check
|
600
602
|
end
|
601
603
|
|
602
604
|
def test_become_root5
|
@@ -608,7 +610,7 @@ class TestCommonTree < Test::Unit::TestCase
|
|
608
610
|
old_root.add_child( new_node( new_token 103 ) )
|
609
611
|
|
610
612
|
@adaptor.become_root(new_root, old_root)
|
611
|
-
new_root.
|
613
|
+
new_root.sanity_check
|
612
614
|
end
|
613
615
|
|
614
616
|
def test_become_root6
|
@@ -618,7 +620,7 @@ class TestCommonTree < Test::Unit::TestCase
|
|
618
620
|
|
619
621
|
@adaptor.add_child( root_1, new_node( new_token 6 ) )
|
620
622
|
@adaptor.add_child( root_0, root_1 )
|
621
|
-
root_0.
|
623
|
+
root_0.sanity_check
|
622
624
|
end
|
623
625
|
|
624
626
|
def test_replace_with_no_children
|
@@ -638,8 +640,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
638
640
|
new_child = new_node( new_token 99, :text => 'c' )
|
639
641
|
t.replace_children(0,0,new_child)
|
640
642
|
|
641
|
-
t.
|
642
|
-
t.
|
643
|
+
t.inspect.should == '(a c)'
|
644
|
+
t.sanity_check
|
643
645
|
|
644
646
|
end
|
645
647
|
def test_replace_in_middle
|
@@ -650,8 +652,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
650
652
|
|
651
653
|
new_child = new_node( new_token 99, :text => 'x' )
|
652
654
|
t.replace_children(1, 1, new_child)
|
653
|
-
t.
|
654
|
-
t.
|
655
|
+
t.inspect.should == '(a b x d)'
|
656
|
+
t.sanity_check
|
655
657
|
end
|
656
658
|
|
657
659
|
def test_replace_at_left
|
@@ -662,8 +664,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
662
664
|
|
663
665
|
new_child = new_node( new_token 99, :text => 'x' )
|
664
666
|
t.replace_children(0, 0, new_child)
|
665
|
-
t.
|
666
|
-
t.
|
667
|
+
t.inspect.should == '(a x c d)'
|
668
|
+
t.sanity_check
|
667
669
|
end
|
668
670
|
|
669
671
|
def test_replace_at_left
|
@@ -674,8 +676,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
674
676
|
|
675
677
|
new_child = new_node( new_token 99, :text => 'x' )
|
676
678
|
t.replace_children(2, 2, new_child)
|
677
|
-
t.
|
678
|
-
t.
|
679
|
+
t.inspect.should == '(a b c x)'
|
680
|
+
t.sanity_check
|
679
681
|
end
|
680
682
|
|
681
683
|
def test_replace_one_with_two_at_left
|
@@ -689,8 +691,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
689
691
|
new_children.add_child new_node( new_token 99, :text => 'y' )
|
690
692
|
|
691
693
|
t.replace_children(0, 0, new_children)
|
692
|
-
t.
|
693
|
-
t.
|
694
|
+
t.inspect.should == '(a x y c d)'
|
695
|
+
t.sanity_check
|
694
696
|
end
|
695
697
|
|
696
698
|
def test_replace_one_with_two_at_right
|
@@ -704,8 +706,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
704
706
|
new_children.add_child new_node( new_token 99, :text => 'y' )
|
705
707
|
|
706
708
|
t.replace_children(2, 2, new_children)
|
707
|
-
t.
|
708
|
-
t.
|
709
|
+
t.inspect.should == '(a b c x y)'
|
710
|
+
t.sanity_check
|
709
711
|
end
|
710
712
|
|
711
713
|
def test_replace_one_with_two_in_middle
|
@@ -719,8 +721,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
719
721
|
new_children.add_child new_node( new_token 99, :text => 'y' )
|
720
722
|
|
721
723
|
t.replace_children(1, 1, new_children)
|
722
|
-
t.
|
723
|
-
t.
|
724
|
+
t.inspect.should == '(a b x y d)'
|
725
|
+
t.sanity_check
|
724
726
|
end
|
725
727
|
|
726
728
|
def test_replace_two_with_one_at_left
|
@@ -732,8 +734,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
732
734
|
new_child = new_node( new_token 99, :text => 'x' )
|
733
735
|
|
734
736
|
t.replace_children(0, 1, new_child)
|
735
|
-
t.
|
736
|
-
t.
|
737
|
+
t.inspect.should == '(a x d)'
|
738
|
+
t.sanity_check
|
737
739
|
end
|
738
740
|
|
739
741
|
def test_replace_two_with_one_at_right
|
@@ -745,8 +747,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
745
747
|
new_child = new_node( new_token 99, :text => 'x' )
|
746
748
|
|
747
749
|
t.replace_children(1, 2, new_child)
|
748
|
-
t.
|
749
|
-
t.
|
750
|
+
t.inspect.should == '(a b x)'
|
751
|
+
t.sanity_check
|
750
752
|
end
|
751
753
|
|
752
754
|
def test_replace_all_with_one
|
@@ -758,8 +760,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
758
760
|
new_child = new_node( new_token 99, :text => 'x' )
|
759
761
|
|
760
762
|
t.replace_children(0, 2, new_child)
|
761
|
-
t.
|
762
|
-
t.
|
763
|
+
t.inspect.should == '(a x)'
|
764
|
+
t.sanity_check
|
763
765
|
end
|
764
766
|
|
765
767
|
def test_replace_all_with_two
|
@@ -773,8 +775,8 @@ class TestCommonTree < Test::Unit::TestCase
|
|
773
775
|
new_children.add_child new_node( new_token 99, :text => 'y' )
|
774
776
|
|
775
777
|
t.replace_children(0, 1, new_children)
|
776
|
-
t.
|
777
|
-
t.
|
778
|
+
t.inspect.should == '(a x y d)'
|
779
|
+
t.sanity_check
|
778
780
|
end
|
779
781
|
|
780
782
|
def new_token(type, opts = {})
|
@@ -792,9 +794,12 @@ class TestTreeContext < Test::Unit::TestCase
|
|
792
794
|
<invalid> <EOR> <DOWN> <UP> VEC ASSIGN PRINT
|
793
795
|
PLUS MULT DOT ID INT WS '[' ',' ']'
|
794
796
|
)
|
797
|
+
Tokens = TokenScheme.build( TOKEN_NAMES )
|
798
|
+
|
795
799
|
def setup
|
796
|
-
|
800
|
+
@wizard = Wizard.new( :token_scheme => Tokens )
|
797
801
|
end
|
802
|
+
|
798
803
|
def teardown
|
799
804
|
# after-each-test code
|
800
805
|
end
|
@@ -802,53 +807,37 @@ class TestTreeContext < Test::Unit::TestCase
|
|
802
807
|
# vvvvvvvv tests vvvvvvvvv
|
803
808
|
|
804
809
|
def test_simple_parent
|
805
|
-
tree =
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
labels = {}
|
811
|
-
|
812
|
-
valid = wiz.parse(t,
|
813
|
-
"(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))",
|
814
|
-
labels
|
810
|
+
tree = @wizard.create(
|
811
|
+
"(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
|
812
|
+
)
|
813
|
+
labels = @wizard.match( tree,
|
814
|
+
"(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))"
|
815
815
|
)
|
816
|
-
assert(valid)
|
817
|
-
node = labels['x']
|
818
816
|
|
819
|
-
|
817
|
+
assert_kind_of( Hash, labels )
|
818
|
+
@wizard.in_context?( labels.fetch( 'x' ), 'VEC' ).should be_true
|
820
819
|
end
|
821
820
|
|
822
821
|
def test_no_parent
|
823
|
-
tree =
|
824
|
-
|
825
|
-
wiz = Wizard.new(adaptor, TOKEN_NAMES)
|
826
|
-
t = wiz.create(tree)
|
827
|
-
|
828
|
-
labels = {}
|
829
|
-
valid = wiz.parse(t,
|
830
|
-
"(%x:PRINT (MULT ID (VEC INT INT INT)))",
|
831
|
-
labels
|
822
|
+
tree = @wizard.create(
|
823
|
+
'(PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3])))'
|
832
824
|
)
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
825
|
+
|
826
|
+
labels = @wizard.match( tree, "(%x:PRINT (MULT ID (VEC INT INT INT)))" )
|
827
|
+
assert_kind_of( Hash, labels )
|
828
|
+
@wizard.in_context?( labels.fetch( 'x' ), 'VEC' ).should be_false
|
837
829
|
end
|
838
830
|
|
839
831
|
def test_parent_with_wildcard
|
840
|
-
tree =
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
node
|
850
|
-
|
851
|
-
assert_equal true,
|
852
|
-
TreeParser.in_context?(adaptor, TOKEN_NAMES, node, 'VEC ...')
|
832
|
+
tree = @wizard.create(
|
833
|
+
"(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID[x] (VEC INT[1] INT[2] INT[3]))))"
|
834
|
+
)
|
835
|
+
|
836
|
+
labels = @wizard.match( tree,
|
837
|
+
"(nil (ASSIGN ID[x] INT[3]) (PRINT (MULT ID (VEC INT %x:INT INT))))"
|
838
|
+
)
|
839
|
+
assert_kind_of( Hash, labels )
|
840
|
+
node = labels.fetch( 'x' )
|
841
|
+
@wizard.in_context?( node, 'VEC ...' ).should be_true
|
853
842
|
end
|
854
843
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: antlr3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Yetter
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-02 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -72,18 +72,17 @@ files:
|
|
72
72
|
- lib/antlr3/version.rb
|
73
73
|
- lib/antlr3/error.rb
|
74
74
|
- lib/antlr3/tree.rb
|
75
|
-
- lib/antlr3/test/diff.rb
|
76
75
|
- lib/antlr3/test/functional.rb
|
77
76
|
- lib/antlr3/test/call-stack.rb
|
78
77
|
- lib/antlr3/test/grammar.rb
|
79
78
|
- lib/antlr3/test/core-extensions.rb
|
80
|
-
- lib/antlr3/test/config.rb
|
81
79
|
- lib/antlr3/dfa.rb
|
82
80
|
- lib/antlr3/profile.rb
|
83
81
|
- lib/antlr3/tree/visitor.rb
|
84
82
|
- lib/antlr3/tree/debug.rb
|
85
83
|
- lib/antlr3/tree/wizard.rb
|
86
84
|
- lib/antlr3/token.rb
|
85
|
+
- lib/antlr3/task.rb
|
87
86
|
- lib/antlr3/constants.rb
|
88
87
|
- lib/antlr3/util.rb
|
89
88
|
- lib/antlr3.rb
|
@@ -131,7 +130,7 @@ files:
|
|
131
130
|
- templates/Dbg.stg
|
132
131
|
- templates/ASTParser.stg
|
133
132
|
- templates/ASTTreeParser.stg
|
134
|
-
- samples/
|
133
|
+
- samples/CPP.g
|
135
134
|
- samples/ANTLRv3Grammar.g
|
136
135
|
- README.txt
|
137
136
|
- ANTLR-LICENSE.txt
|
data/lib/antlr3/test/config.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
=begin ::about::
|
5
|
-
author: Kyle Yetter <kcy5b@yahoo.com>
|
6
|
-
created on: October 11, 2009
|
7
|
-
=end
|
8
|
-
|
9
|
-
module ANTLR3
|
10
|
-
module Test
|
11
|
-
|
12
|
-
require 'rbconfig'
|
13
|
-
path_sep = RbConfig::CONFIG['PATH_SEPARATOR']
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
exec_path = ENV['PATH'].split(path_sep)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
data/lib/antlr3/test/diff.rb
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
module ANTLR3
|
5
|
-
module Test
|
6
|
-
module Diff
|
7
|
-
module_function
|
8
|
-
|
9
|
-
# trim common head and tail elements of the two lists
|
10
|
-
def width
|
11
|
-
screen_width - 20
|
12
|
-
end
|
13
|
-
|
14
|
-
def column_width
|
15
|
-
width / 2 - 1
|
16
|
-
end
|
17
|
-
|
18
|
-
def segment(list_a, list_b)
|
19
|
-
# trim leading common elements
|
20
|
-
common_head = 0
|
21
|
-
list_a.zip(list_b) do |a, b|
|
22
|
-
a == b ? (common_head += 1) : break
|
23
|
-
end
|
24
|
-
head = list_a[0...common_head]
|
25
|
-
list_a = list_a[common_head..-1].reverse!
|
26
|
-
list_b = list_b[common_head..-1].reverse!
|
27
|
-
|
28
|
-
|
29
|
-
common_tail = 0
|
30
|
-
list_a.zip(list_b) { |a,b| a == b ? (common_tail += 1) : break }
|
31
|
-
tail = list_a[0...common_tail].reverse!
|
32
|
-
list_a = list_a[common_tail..-1].reverse!
|
33
|
-
list_b = list_b[common_tail..-1].reverse!
|
34
|
-
|
35
|
-
return [head, tail, list_a, list_b]
|
36
|
-
end
|
37
|
-
|
38
|
-
def max(a,b)
|
39
|
-
case a <=> b
|
40
|
-
when -1 then b
|
41
|
-
else a
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def colorize(text, color)
|
46
|
-
lines = text.split("\n")
|
47
|
-
escape =
|
48
|
-
case color
|
49
|
-
when :white then "\e[37m"
|
50
|
-
when :magenta then "\e[35m"
|
51
|
-
when :yellow then "\e[33m"
|
52
|
-
when :green then "\e[32m"
|
53
|
-
when :black then "\e[30m"
|
54
|
-
when :red then "\e[31m"
|
55
|
-
when :cyan then "\e[36m"
|
56
|
-
when :blue then "\e[34m"
|
57
|
-
end
|
58
|
-
lines.map! { |ln| escape + ln << "\e[\0m" }.join("\n")
|
59
|
-
end
|
60
|
-
|
61
|
-
def display_shared(item)
|
62
|
-
colorize(pair(item, item), :green)
|
63
|
-
end
|
64
|
-
def display_addition(item)
|
65
|
-
colorize(pair(nil, item), :magenta)
|
66
|
-
end
|
67
|
-
def display_subtraction(item)
|
68
|
-
colorize(pair(item, nil), :red)
|
69
|
-
end
|
70
|
-
def wrapped_inspect(list)
|
71
|
-
width = column_width
|
72
|
-
list = list.map { |i| i.inspect }
|
73
|
-
list[-1] << ' ]'
|
74
|
-
|
75
|
-
lines, line, joint = [], '[ ', ''
|
76
|
-
|
77
|
-
add_line = proc do |l|
|
78
|
-
lines << l.ljust(width)
|
79
|
-
' '
|
80
|
-
end
|
81
|
-
|
82
|
-
for item in list
|
83
|
-
line << joint
|
84
|
-
leftover = width - line.length
|
85
|
-
if item.length > leftover
|
86
|
-
i = item.rindex(/\s+/, leftover - 1) || leftover
|
87
|
-
if
|
88
|
-
line = add_line[line << item[0, i]]
|
89
|
-
item = item[i..-1]
|
90
|
-
else
|
91
|
-
|
92
|
-
end
|
93
|
-
end
|
94
|
-
line << item
|
95
|
-
|
96
|
-
d = item.length + 2
|
97
|
-
if line.length + d > width
|
98
|
-
line << ','
|
99
|
-
lines << line
|
100
|
-
line, joint = ' ', ''
|
101
|
-
else
|
102
|
-
joint = ", "
|
103
|
-
end
|
104
|
-
end
|
105
|
-
lines << line
|
106
|
-
|
107
|
-
lines.join("\n")
|
108
|
-
end
|
109
|
-
|
110
|
-
def pair(x, y)
|
111
|
-
x = x ? wrapped_inspect(x).split("\n") : []
|
112
|
-
y = y ? wrapped_inspect(y).split("\n") : []
|
113
|
-
line_count = max(x.length, y.length)
|
114
|
-
x.pad!(line_count, '')
|
115
|
-
y.pad!(line_count, '')
|
116
|
-
|
117
|
-
x.zip(y).map! { |pair| pair.map! { |i| i.ljust(column_width) }.join(' ') }.join("\n")
|
118
|
-
end
|
119
|
-
|
120
|
-
def compute_lcs(list_a, list_b)
|
121
|
-
m, n = list_a.length, list_b.length
|
122
|
-
lcs_matrix = Array.new(m + 1) do |row|
|
123
|
-
Array.new(n + 1, 0)
|
124
|
-
end
|
125
|
-
m.times do |i| n.times do |j|
|
126
|
-
if list_a[i] == list_b[j] then lcs_matrix[i+1][j+1] = lcs_matrix[i][j] + 1
|
127
|
-
else lcs_matrix[i+1][j+1] = max(lcs_matrix[i+1][j], lcs_matrix[i][j+1])
|
128
|
-
end
|
129
|
-
end end
|
130
|
-
return lcs_matrix
|
131
|
-
end
|
132
|
-
|
133
|
-
def partial_diff(out, a, b, lcs, i = a.length, j = b.length)
|
134
|
-
if i > 0 and j > 0 and a[i-1] == b[j-1]
|
135
|
-
partial_diff(out, a, b, lcs, i-1, j-1)
|
136
|
-
out << display_shared(a[i-1])
|
137
|
-
else
|
138
|
-
if j > 0 and i.zero? || lcs[i][j-1] >= lcs[i-1][j]
|
139
|
-
partial_diff(out,a,b,lcs,i,j-1)
|
140
|
-
out << display_addition(b[j-1])
|
141
|
-
elsif i > 0 and j.zero? || lcs[i][j-1] < lcs[i-1][j]
|
142
|
-
partial_diff(out, a,b,lcs,i-1,j)
|
143
|
-
out << display_subtraction(a[i-1])
|
144
|
-
end
|
145
|
-
end
|
146
|
-
return out
|
147
|
-
end
|
148
|
-
|
149
|
-
def diff(a, b, options = {})
|
150
|
-
head, tail, a, b = segment(a, b)
|
151
|
-
lcs = compute_lcs(a,b)
|
152
|
-
out = []
|
153
|
-
out << %w(Expected Got).map! { |w| w.ljust(column_width) }.join(' ')
|
154
|
-
head.each do |item|
|
155
|
-
out << display_shared(item)
|
156
|
-
end
|
157
|
-
partial_diff(out, a, b, lcs)
|
158
|
-
tail.each do |item|
|
159
|
-
out << display_shared(item)
|
160
|
-
end
|
161
|
-
out.join("\n")
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|