ruby_parser 3.8.4 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.rdoc +29 -0
- data/Manifest.txt +5 -0
- data/README.rdoc +12 -0
- data/Rakefile +128 -69
- data/compare/normalize.rb +146 -0
- data/lib/rp_extensions.rb +77 -0
- data/lib/rp_stringscanner.rb +64 -0
- data/lib/ruby18_parser.rb +2180 -2175
- data/lib/ruby18_parser.y +17 -13
- data/lib/ruby19_parser.rb +2250 -2241
- data/lib/ruby19_parser.y +18 -14
- data/lib/ruby20_parser.rb +2498 -2503
- data/lib/ruby20_parser.y +18 -29
- data/lib/ruby21_parser.rb +2287 -2275
- data/lib/ruby21_parser.y +18 -24
- data/lib/ruby22_parser.rb +2573 -2560
- data/lib/ruby22_parser.y +18 -24
- data/lib/ruby23_parser.rb +2498 -2494
- data/lib/ruby23_parser.y +18 -24
- data/lib/ruby24_parser.rb +6797 -0
- data/lib/ruby24_parser.y +2367 -0
- data/lib/ruby_lexer.rb +11 -16
- data/lib/ruby_parser.rb +86 -7
- data/lib/ruby_parser.yy +57 -53
- data/lib/ruby_parser_extras.rb +34 -237
- data/test/test_ruby_lexer.rb +54 -41
- data/test/test_ruby_parser.rb +776 -700
- data/test/test_ruby_parser_extras.rb +4 -6
- metadata +7 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db3aec0f342263aec6c4bc598f2af937d889219b
|
4
|
+
data.tar.gz: 0a7300cfcb5109443168aa3432eefb0b103a07a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c26c726384052dc9ea43d9cb29f982ed03768458c1ff0e64a515026c721be346f009ead616d18c499d449fbf9a6c23234a4c637afb14cf28fb74035a33a743db
|
7
|
+
data.tar.gz: 4f3d570afe84856c5275be5a9eaf9277168a89db5bd3dea605cc86cf8c38492d9ee0b5ec2d32c3413124c068ff57e24a5241d8474463e15018376328fff024ec
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/History.rdoc
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
=== 3.9.0 / 2017-04-13
|
2
|
+
|
3
|
+
* 1 major enhancement:
|
4
|
+
|
5
|
+
* Added tentative ruby 2.4 support. Probably missing things.
|
6
|
+
|
7
|
+
* 13 minor enhancements:
|
8
|
+
|
9
|
+
* Added RubyParser.latest.
|
10
|
+
* Added RubyParser::Parser.version to make version range comparisons easier
|
11
|
+
* Changed superclasses of all parsers to RubyParser::Parser
|
12
|
+
* Cleaned up a lot of the version specific code to be more generic/flexible.
|
13
|
+
* Documented how to add new versions in README.
|
14
|
+
* Moved RubyParser from ruby_parser_extras.rb into ruby_parser.rb to fix bootstrap issues.
|
15
|
+
* Renamed RubyParserStuff#get_match_node to new_match. Aliased and deprecated.
|
16
|
+
* Renamed RubyParserStuff#logop to logical_op. Aliased and deprecated.
|
17
|
+
* Renamed RubyParserStuff#node_assign to new_assign. Aliased and deprecated.
|
18
|
+
* Renamed all parsers to RubyParser::V##.
|
19
|
+
* Revamped grammar preprocessing to make adding new versions easier.
|
20
|
+
* RubyParser.for_current_ruby falls back to latest if current not available.
|
21
|
+
* Subclasses of RubyParser::Parser register themselves into RubyParser::VERSIONS.
|
22
|
+
|
23
|
+
* 4 bug fixes:
|
24
|
+
|
25
|
+
* Fixed `&.` after newline. (presidentbeef)
|
26
|
+
* Fixed bug setting line number for hash literals to line of opening brace.
|
27
|
+
* Fixed grammar preprocessing bug.
|
28
|
+
* Properly handle kDO with no-parens stabby lambda. (presidentbeef)
|
29
|
+
|
1
30
|
=== 3.8.4 / 2017-01-13
|
2
31
|
|
3
32
|
* 3 bug fixes:
|
data/Manifest.txt
CHANGED
@@ -5,7 +5,10 @@ README.rdoc
|
|
5
5
|
Rakefile
|
6
6
|
bin/ruby_parse
|
7
7
|
bin/ruby_parse_extract_error
|
8
|
+
compare/normalize.rb
|
8
9
|
lib/.document
|
10
|
+
lib/rp_extensions.rb
|
11
|
+
lib/rp_stringscanner.rb
|
9
12
|
lib/ruby18_parser.rb
|
10
13
|
lib/ruby18_parser.y
|
11
14
|
lib/ruby19_parser.rb
|
@@ -18,6 +21,8 @@ lib/ruby22_parser.rb
|
|
18
21
|
lib/ruby22_parser.y
|
19
22
|
lib/ruby23_parser.rb
|
20
23
|
lib/ruby23_parser.y
|
24
|
+
lib/ruby24_parser.rb
|
25
|
+
lib/ruby24_parser.y
|
21
26
|
lib/ruby_lexer.rb
|
22
27
|
lib/ruby_lexer.rex
|
23
28
|
lib/ruby_lexer.rex.rb
|
data/README.rdoc
CHANGED
@@ -57,6 +57,18 @@ You can also use Ruby19Parser, Ruby18Parser, or RubyParser.for_current_ruby:
|
|
57
57
|
RubyParser.for_current_ruby.parse "1+1"
|
58
58
|
# => s(:call, s(:lit, 1), :+, s(:lit, 1))
|
59
59
|
|
60
|
+
== DEVELOPER NOTES:
|
61
|
+
|
62
|
+
To add a new version:
|
63
|
+
|
64
|
+
* New parser should be generated from lib/ruby_parser.yy.
|
65
|
+
* Extend lib/ruby_parser.yy with new class name.
|
66
|
+
* Add new version number to Rakefile for rule creation.
|
67
|
+
* Require generated parser in lib/ruby_parser.rb.
|
68
|
+
* Add empty TestRubyParserShared##Plus module and TestRubyParserV## to test/test_ruby_parser.rb.
|
69
|
+
* Extend Manifest.txt with generated file names.
|
70
|
+
* Extend sexp_processor's pt_testcase.rb to match version
|
71
|
+
|
60
72
|
== REQUIREMENTS:
|
61
73
|
|
62
74
|
* ruby. woot.
|
data/Rakefile
CHANGED
@@ -14,6 +14,10 @@ Hoe.add_include_dirs "../../sexp_processor/dev/lib"
|
|
14
14
|
Hoe.add_include_dirs "../../minitest/dev/lib"
|
15
15
|
Hoe.add_include_dirs "../../oedipus_lex/dev/lib"
|
16
16
|
|
17
|
+
V1 = %w[18 19]
|
18
|
+
V2 = %w[20 21 22 23 24]
|
19
|
+
V1_2 = V1 + V2
|
20
|
+
|
17
21
|
Hoe.spec "ruby_parser" do
|
18
22
|
developer "Ryan Davis", "ryand-ruby@zenspider.com"
|
19
23
|
|
@@ -24,45 +28,35 @@ Hoe.spec "ruby_parser" do
|
|
24
28
|
dependency "oedipus_lex", "~> 2.1", :developer
|
25
29
|
|
26
30
|
if plugin? :perforce then # generated files
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self.perforce_ignore << "lib/ruby20_parser.y"
|
31
|
-
self.perforce_ignore << "lib/ruby21_parser.rb"
|
32
|
-
self.perforce_ignore << "lib/ruby21_parser.y"
|
33
|
-
self.perforce_ignore << "lib/ruby22_parser.rb"
|
34
|
-
self.perforce_ignore << "lib/ruby22_parser.y"
|
35
|
-
self.perforce_ignore << "lib/ruby23_parser.rb"
|
36
|
-
self.perforce_ignore << "lib/ruby23_parser.y"
|
37
|
-
self.perforce_ignore << "lib/ruby_lexer.rex.rb"
|
38
|
-
end
|
31
|
+
V1_2.each do |n|
|
32
|
+
self.perforce_ignore << "lib/ruby#{n}_parser.rb"
|
33
|
+
end
|
39
34
|
|
40
|
-
|
41
|
-
|
35
|
+
V2.each do |n|
|
36
|
+
self.perforce_ignore << "lib/ruby#{n}_parser.y"
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
39
|
+
self.perforce_ignore << "lib/ruby_lexer.rex.rb"
|
40
|
+
end
|
46
41
|
|
47
|
-
|
48
|
-
|
42
|
+
if plugin?(:racc)
|
43
|
+
self.racc_flags << " -t" if ENV["DEBUG"]
|
44
|
+
self.racc_flags << " --superclass RubyParser::Parser"
|
45
|
+
# self.racc_flags << " --runtime ruby_parser" # TODO: broken in racc
|
46
|
+
end
|
49
47
|
end
|
50
48
|
|
51
|
-
|
52
|
-
|
49
|
+
V2.each do |n|
|
50
|
+
file "lib/ruby#{n}_parser.y" => "lib/ruby_parser.yy" do |t|
|
51
|
+
cmd = 'unifdef -tk -DV=%s -UDEAD %s > %s || true' % [n, t.source, t.name]
|
52
|
+
sh cmd
|
53
|
+
end
|
53
54
|
end
|
54
55
|
|
55
|
-
|
56
|
-
|
56
|
+
V1_2.each do |n|
|
57
|
+
file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
|
57
58
|
end
|
58
59
|
|
59
|
-
|
60
|
-
file "lib/ruby18_parser.rb" => "lib/ruby18_parser.y"
|
61
|
-
file "lib/ruby19_parser.rb" => "lib/ruby19_parser.y"
|
62
|
-
file "lib/ruby20_parser.rb" => "lib/ruby20_parser.y"
|
63
|
-
file "lib/ruby21_parser.rb" => "lib/ruby21_parser.y"
|
64
|
-
file "lib/ruby22_parser.rb" => "lib/ruby22_parser.y"
|
65
|
-
file "lib/ruby23_parser.rb" => "lib/ruby23_parser.y"
|
66
60
|
file "lib/ruby_lexer.rex.rb" => "lib/ruby_lexer.rex"
|
67
61
|
|
68
62
|
task :clean do
|
@@ -94,32 +88,110 @@ end
|
|
94
88
|
|
95
89
|
task :isolate => :phony
|
96
90
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
91
|
+
def in_compare
|
92
|
+
Dir.chdir "compare" do
|
93
|
+
yield
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def dl v
|
98
|
+
dir = v[/^\d+\.\d+/]
|
99
|
+
url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.bz2"
|
100
|
+
path = File.basename url
|
101
|
+
unless File.exist? path then
|
102
|
+
system "curl -O #{url}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def ruby_parse version
|
107
|
+
v = version[/^\d+\.\d+/].delete "."
|
108
|
+
rp_txt = "rp#{v}.txt"
|
109
|
+
mri_txt = "mri#{v}.txt"
|
110
|
+
parse_y = "parse#{v}.y"
|
111
|
+
tarball = "ruby-#{version}.tar.bz2"
|
112
|
+
ruby_dir = "ruby-#{version}"
|
113
|
+
diff = "diff#{v}.diff"
|
114
|
+
rp_out = "lib/ruby#{v}_parser.output"
|
115
|
+
|
116
|
+
c_diff = "compare/#{diff}"
|
117
|
+
c_rp_txt = "compare/#{rp_txt}"
|
118
|
+
c_mri_txt = "compare/#{mri_txt}"
|
119
|
+
c_parse_y = "compare/#{parse_y}"
|
120
|
+
c_tarball = "compare/#{tarball}"
|
121
|
+
|
122
|
+
file tarball do
|
123
|
+
in_compare do
|
124
|
+
dl version
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
file c_parse_y => c_tarball do
|
129
|
+
in_compare do
|
130
|
+
system "tar yxf #{tarball} #{ruby_dir}/{id.h,parse.y,tool/{id2token.rb,vpath.rb}}"
|
131
|
+
Dir.chdir ruby_dir do
|
132
|
+
if File.exist? "tool/id2token.rb" then
|
133
|
+
sh "ruby tool/id2token.rb --path-separator=.:./ id.h parse.y > ../#{parse_y}"
|
134
|
+
else
|
135
|
+
cp "parse.y", "../#{parse_y}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
sh "rm -rf #{ruby_dir}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
file c_mri_txt => c_parse_y do
|
143
|
+
in_compare do
|
144
|
+
sh "bison -r all #{parse_y}"
|
145
|
+
sh "./normalize.rb parse#{v}.output > #{mri_txt}"
|
146
|
+
rm ["parse#{v}.output", "parse#{v}.tab.c"]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
file rp_out => :parser
|
151
|
+
|
152
|
+
file c_rp_txt => rp_out do
|
153
|
+
in_compare do
|
154
|
+
sh "./normalize.rb ../#{rp_out} > #{rp_txt}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
compare = "compare#{v}"
|
159
|
+
|
160
|
+
desc "Compare all grammars to MRI"
|
161
|
+
task :compare => compare
|
162
|
+
|
163
|
+
task c_diff => [c_mri_txt, c_rp_txt] do
|
164
|
+
in_compare do
|
165
|
+
system "diff -du #{mri_txt} #{rp_txt} > #{diff}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
desc "Compare #{v} grammar to MRI #{version}"
|
170
|
+
task compare => c_diff do
|
171
|
+
in_compare do
|
172
|
+
system "wc -l #{diff}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
task :clean do
|
177
|
+
rm_f Dir[c_parse_y, c_mri_txt, c_rp_txt]
|
178
|
+
end
|
179
|
+
|
180
|
+
task :realclean do
|
181
|
+
rm_f Dir[tarball]
|
118
182
|
end
|
119
183
|
end
|
120
184
|
|
185
|
+
ruby_parse "1.8.7-p374"
|
186
|
+
ruby_parse "1.9.3-p551"
|
187
|
+
ruby_parse "2.0.0-p648"
|
188
|
+
ruby_parse "2.1.9"
|
189
|
+
ruby_parse "2.2.6"
|
190
|
+
ruby_parse "2.3.3"
|
191
|
+
# TODO ruby_parse "2.4.0"
|
192
|
+
|
121
193
|
task :debug => :isolate do
|
122
|
-
ENV["V"] ||=
|
194
|
+
ENV["V"] ||= V1_2.last
|
123
195
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
124
196
|
Rake.application[:lexer].invoke # this way we can have DEBUG set
|
125
197
|
|
@@ -127,22 +199,9 @@ task :debug => :isolate do
|
|
127
199
|
require "ruby_parser"
|
128
200
|
require "pp"
|
129
201
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
when "19" then
|
134
|
-
Ruby19Parser.new
|
135
|
-
when "20" then
|
136
|
-
Ruby20Parser.new
|
137
|
-
when "21" then
|
138
|
-
Ruby21Parser.new
|
139
|
-
when "22" then
|
140
|
-
Ruby22Parser.new
|
141
|
-
when "23" then
|
142
|
-
Ruby23Parser.new
|
143
|
-
else
|
144
|
-
raise "Unsupported version #{ENV["V"]}"
|
145
|
-
end
|
202
|
+
klass = Object.const_get("Ruby#{ENV["V"]}Parser") rescue nil
|
203
|
+
raise "Unsupported version #{ENV["V"]}" unless klass
|
204
|
+
parser = klass.new
|
146
205
|
|
147
206
|
time = (ENV["RP_TIMEOUT"] || 10).to_i
|
148
207
|
|
@@ -173,7 +232,7 @@ task :debug_ruby do
|
|
173
232
|
end
|
174
233
|
|
175
234
|
task :extract => :isolate do
|
176
|
-
ENV["V"] ||=
|
235
|
+
ENV["V"] ||= V1_2.last
|
177
236
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
178
237
|
|
179
238
|
file = ENV["F"] || ENV["FILE"]
|
@@ -0,0 +1,146 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
good = false
|
4
|
+
|
5
|
+
rules = Hash.new { |h,k| h[k] = [] }
|
6
|
+
rule = nil
|
7
|
+
order = []
|
8
|
+
|
9
|
+
def munge s
|
10
|
+
renames = [
|
11
|
+
"'='", "tEQL",
|
12
|
+
"'!'", "tBANG",
|
13
|
+
"'%'", "tPERCENT",
|
14
|
+
"'&'", "tAMPER2",
|
15
|
+
"'('", "tLPAREN2",
|
16
|
+
"')'", "tRPAREN",
|
17
|
+
"'*'", "tSTAR2",
|
18
|
+
"'+'", "tPLUS",
|
19
|
+
"','", "tCOMMA",
|
20
|
+
"'-'", "tMINUS",
|
21
|
+
"'.'", "tDOT",
|
22
|
+
"'/'", "tDIVIDE",
|
23
|
+
"';'", "tSEMI",
|
24
|
+
"':'", "tCOLON",
|
25
|
+
"'<'", "tLT",
|
26
|
+
"'>'", "tGT",
|
27
|
+
"'?'", "tEH",
|
28
|
+
"'['", "tLBRACK",
|
29
|
+
"'\\n'", "tNL",
|
30
|
+
"']'", "tRBRACK",
|
31
|
+
"'^'", "tCARET",
|
32
|
+
"'`'", "tBACK_REF2",
|
33
|
+
"'{'", "tLCURLY",
|
34
|
+
"'|'", "tPIPE",
|
35
|
+
"'}'", "tRCURLY",
|
36
|
+
"'~'", "tTILDE",
|
37
|
+
'"["', "tLBRACK",
|
38
|
+
|
39
|
+
# 2.0 changes?
|
40
|
+
'"<=>"', "tCMP",
|
41
|
+
'"=="', "tEQ",
|
42
|
+
'"==="', "tEQQ",
|
43
|
+
'"!~"', "tNMATCH",
|
44
|
+
'"=~"', "tMATCH",
|
45
|
+
'">="', "tGEQ",
|
46
|
+
'"<="', "tLEQ",
|
47
|
+
'"!="', "tNEQ",
|
48
|
+
'"<<"', "tLSHFT",
|
49
|
+
'">>"', "tRSHFT",
|
50
|
+
'"*"', "tSTAR",
|
51
|
+
|
52
|
+
'".."', "tDOT2",
|
53
|
+
|
54
|
+
'"&"', "tAMPER",
|
55
|
+
'"&&"', "tANDOP",
|
56
|
+
'"||"', "tOROP",
|
57
|
+
|
58
|
+
'"..."', "tDOT3",
|
59
|
+
'"**"', "tPOW",
|
60
|
+
'"unary+"', "tUPLUS",
|
61
|
+
'"unary-"', "tUMINUS",
|
62
|
+
'"[]"', "tAREF",
|
63
|
+
'"[]="', "tASET",
|
64
|
+
'"::"', "tCOLON2",
|
65
|
+
'"{ arg"', "tLBRACE_ARG",
|
66
|
+
'"( arg"', "tLPAREN_ARG",
|
67
|
+
'"("', "tLPAREN",
|
68
|
+
'rparen', "tRPAREN",
|
69
|
+
'"{"', "tLBRACE",
|
70
|
+
'"=>"', "tASSOC",
|
71
|
+
'"->"', "tLAMBDA",
|
72
|
+
'":: at EXPR_BEG"', "tCOLON3",
|
73
|
+
'"**arg"', "tDSTAR",
|
74
|
+
'","', "tCOMMA",
|
75
|
+
|
76
|
+
# other
|
77
|
+
|
78
|
+
'tLBRACK2', "tLBRACK", # HACK
|
79
|
+
|
80
|
+
"' '", "tSPACE", # needs to be later to avoid bad hits
|
81
|
+
|
82
|
+
"/* empty */", "none",
|
83
|
+
/^\s*$/, "none",
|
84
|
+
"keyword_BEGIN", "klBEGIN",
|
85
|
+
"keyword_END", "klEND",
|
86
|
+
/keyword_(\w+)/, proc { "k#{$1.upcase}" },
|
87
|
+
/\bk_([a-z_]+)/, proc { "k#{$1.upcase}" },
|
88
|
+
/modifier_(\w+)/, proc { "k#{$1.upcase}_MOD" },
|
89
|
+
"kVARIABLE", "keyword_variable", # ugh
|
90
|
+
|
91
|
+
/@(\d+)\s+/, "",
|
92
|
+
]
|
93
|
+
|
94
|
+
renames.each_slice(2) do |(a, b)|
|
95
|
+
if Proc === b then
|
96
|
+
s.gsub!(a, &b)
|
97
|
+
else
|
98
|
+
s.gsub!(a, b)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
s.strip
|
103
|
+
end
|
104
|
+
|
105
|
+
ARGF.each_line do |line|
|
106
|
+
next unless good or line =~ /^-* ?Grammar|\$accept : /
|
107
|
+
|
108
|
+
case line.strip
|
109
|
+
when /^$/ then
|
110
|
+
when /^(\d+) (\$?\w+): (.*)/ then # yacc
|
111
|
+
rule = $2
|
112
|
+
order << rule unless rules.has_key? rule
|
113
|
+
rules[rule] << munge($3)
|
114
|
+
when /^(\d+) \s+\| (.*)/ then # yacc
|
115
|
+
rules[rule] << munge($2)
|
116
|
+
when /^(\d+) (@\d+): (.*)/ then # yacc
|
117
|
+
rule = $2
|
118
|
+
order << rule unless rules.has_key? rule
|
119
|
+
rules[rule] << munge($3)
|
120
|
+
when /^rule (\d+) (@?\w+):(.*)/ then # racc
|
121
|
+
rule = $2
|
122
|
+
order << rule unless rules.has_key? rule
|
123
|
+
rules[rule] << munge($3)
|
124
|
+
when /\$accept/ then # byacc?
|
125
|
+
good = true
|
126
|
+
when /Grammar/ then # both
|
127
|
+
good = true
|
128
|
+
when /^-+ Symbols/ then # racc
|
129
|
+
break
|
130
|
+
when /^Terminals/ then # yacc
|
131
|
+
break
|
132
|
+
when /^\cL/ then # byacc
|
133
|
+
break
|
134
|
+
else
|
135
|
+
warn "unparsed: #{$.}: #{line.chomp}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
require 'yaml'
|
140
|
+
|
141
|
+
order.each do |k|
|
142
|
+
next if k =~ /@/
|
143
|
+
puts
|
144
|
+
puts "#{k}:"
|
145
|
+
puts rules[k].map { |r| " #{r}" }.join "\n"
|
146
|
+
end
|