sourcify 0.5.0 → 0.6.0.rc1
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/.gitignore +1 -0
- data/HISTORY.txt +5 -0
- data/README.rdoc +86 -3
- data/Rakefile +47 -15
- data/lib/sourcify.rb +13 -0
- data/lib/sourcify/common/parser/converter.rb +29 -0
- data/lib/sourcify/common/parser/raw_scanner/comment.rb +23 -0
- data/lib/sourcify/common/parser/raw_scanner/counter.rb +43 -0
- data/lib/sourcify/common/parser/raw_scanner/dstring.rb +60 -0
- data/lib/sourcify/common/parser/raw_scanner/extensions.rb +121 -0
- data/lib/sourcify/common/parser/raw_scanner/heredoc.rb +26 -0
- data/lib/sourcify/common/parser/source_code.rb +33 -0
- data/lib/sourcify/common/ragel/common.rl +5 -0
- data/lib/sourcify/common/ragel/expressions.rl +38 -0
- data/lib/sourcify/{proc/scanner.rl → common/ragel/machines.rl} +10 -178
- data/lib/sourcify/errors.rb +4 -0
- data/lib/sourcify/method.rb +134 -0
- data/lib/sourcify/method/methods.rb +3 -0
- data/lib/sourcify/method/methods/to_raw_source.rb +30 -0
- data/lib/sourcify/method/methods/to_sexp.rb +30 -0
- data/lib/sourcify/method/methods/to_source.rb +30 -0
- data/lib/sourcify/method/parser.rb +104 -0
- data/lib/sourcify/method/parser/converter.rb +8 -0
- data/lib/sourcify/method/parser/raw_scanner.rb +2494 -0
- data/lib/sourcify/method/parser/raw_scanner.rl +144 -0
- data/lib/sourcify/method/parser/raw_scanner_extensions.rb +64 -0
- data/lib/sourcify/method/parser/scanner.rb +48 -0
- data/lib/sourcify/method/parser/source_code.rb +8 -0
- data/lib/sourcify/proc.rb +0 -2
- data/lib/sourcify/proc/parser.rb +2 -5
- data/lib/sourcify/proc/parser/converter.rb +2 -23
- data/lib/sourcify/proc/{scanner.rb → parser/raw_scanner.rb} +808 -806
- data/lib/sourcify/proc/parser/raw_scanner.rl +149 -0
- data/lib/sourcify/proc/parser/raw_scanner_extensions.rb +72 -0
- data/lib/sourcify/proc/parser/{code_scanner.rb → scanner.rb} +9 -5
- data/lib/sourcify/proc/parser/source_code.rb +2 -27
- data/lib/sourcify/version.rb +1 -1
- data/spec/method/others_from_def_end_block_spec.rb +49 -0
- data/spec/method/others_from_define_method_spec.rb +62 -0
- data/spec/method/raw_scanner/block_comment_spec.rb +8 -0
- data/spec/method/raw_scanner/double_colons_spec.rb +8 -0
- data/spec/method/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/spec/method/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/spec/method/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/spec/method/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/spec/method/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/spec/method/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/spec/method/raw_scanner/per_line_comment_spec.rb +8 -0
- data/spec/method/raw_scanner/single_quote_str_spec.rb +8 -0
- data/spec/method/raw_scanner/slash_operator_spec.rb +8 -0
- data/spec/method/raw_scanner/spec_helper.rb +80 -0
- data/spec/method/spec_helper.rb +1 -0
- data/spec/method/to_raw_source_spec.rb +31 -0
- data/spec/method/to_raw_source_w_specified_strip_enclosure_spec.rb +148 -0
- data/spec/method/to_sexp_from_def_end_block_w_variables_spec.rb +46 -0
- data/spec/method/to_sexp_from_def_end_block_within_irb_spec.rb +38 -0
- data/spec/method/to_sexp_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +56 -0
- data/spec/method/to_sexp_from_define_method_w_variables_spec.rb +52 -0
- data/spec/method/to_sexp_from_define_method_within_irb_spec.rb +42 -0
- data/spec/method/to_sexp_w_specified_strip_enclosure_spec.rb +74 -0
- data/spec/method/to_source_from_def_end_block_w_19_extras_spec.rb +23 -0
- data/spec/method/to_source_from_def_end_block_w_nested_begin_spec.rb +35 -0
- data/spec/method/to_source_from_def_end_block_w_nested_case_spec.rb +35 -0
- data/spec/method/to_source_from_def_end_block_w_nested_class_spec.rb +51 -0
- data/spec/method/to_source_from_def_end_block_w_nested_do_end_block_spec.rb +33 -0
- data/spec/method/to_source_from_def_end_block_w_nested_for_spec.rb +126 -0
- data/spec/method/to_source_from_def_end_block_w_nested_if_spec.rb +82 -0
- data/spec/method/to_source_from_def_end_block_w_nested_literal_keyword_spec.rb +141 -0
- data/spec/method/to_source_from_def_end_block_w_nested_method_spec.rb +33 -0
- data/spec/method/to_source_from_def_end_block_w_nested_module_spec.rb +59 -0
- data/spec/method/to_source_from_def_end_block_w_nested_unless_spec.rb +82 -0
- data/spec/method/to_source_from_def_end_block_w_nested_until_spec.rb +179 -0
- data/spec/method/to_source_from_def_end_block_w_nested_while_spec.rb +179 -0
- data/spec/method/to_source_from_def_end_block_w_singleton_method_spec.rb +19 -0
- data/spec/method/to_source_from_def_end_block_within_irb_spec.rb +30 -0
- data/spec/method/to_source_from_def_end_w_multi_blocks_and_many_matches_spec.rb +30 -0
- data/spec/method/to_source_from_def_end_w_multi_blocks_and_single_match_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_w_braced_block_spec.rb +113 -0
- data/spec/method/to_source_from_define_method_w_do_end_block_spec.rb +145 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_many_matches_spec.rb +56 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_single_match_spec.rb +73 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_many_matches_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_no_match_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_single_match_spec.rb +28 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +103 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_many_matches_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_no_match_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_single_match_spec.rb +28 -0
- data/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_ignore_nested_spec.rb +36 -0
- data/spec/method/to_source_from_define_method_within_irb_spec.rb +32 -0
- data/spec/method/to_source_magic_file_var_spec.rb +176 -0
- data/spec/method/to_source_magic_line_var_spec.rb +298 -0
- data/spec/method/to_source_w_specified_strip_enclosure_spec.rb +39 -0
- data/spec/no_method/unsupported_platform_spec.rb +26 -0
- data/spec/proc/raw_scanner/block_comment_spec.rb +8 -0
- data/spec/proc/raw_scanner/double_colons_spec.rb +8 -0
- data/spec/proc/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/spec/proc/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/spec/proc/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/spec/proc/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/spec/proc/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/spec/proc/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/spec/proc/raw_scanner/per_line_comment_spec.rb +8 -0
- data/spec/proc/raw_scanner/single_quote_str_spec.rb +8 -0
- data/spec/proc/raw_scanner/slash_operator_spec.rb +8 -0
- data/spec/proc/raw_scanner/spec_helper.rb +63 -0
- data/spec/{proc_scanner/block_comment_spec.rb → raw_scanner/block_comment_shared_spec.rb} +1 -5
- data/spec/{proc_scanner/double_colons_spec.rb → raw_scanner/double_colons_shared_spec.rb} +1 -5
- data/spec/{proc_scanner/double_quote_str_w_interpolation_spec.rb → raw_scanner/double_quote_str_w_interpolation_shared_spec.rb} +1 -5
- data/spec/{proc_scanner/double_quote_str_wo_interpolation_spec.rb → raw_scanner/double_quote_str_wo_interpolation_shared_spec.rb} +1 -5
- data/spec/raw_scanner/heredoc_w_indent_shared_spec.rb +69 -0
- data/spec/raw_scanner/heredoc_wo_indent_shared_spec.rb +70 -0
- data/spec/{proc_scanner/kw_do_alias1_spec.rb → raw_scanner/kw_block_start_alias1_shared_spec.rb} +10 -26
- data/spec/{proc_scanner/kw_do_alias2_spec.rb → raw_scanner/kw_block_start_alias2_shared_spec.rb} +10 -25
- data/spec/{proc_scanner/per_line_comment_spec.rb → raw_scanner/per_line_comment_shared_spec.rb} +1 -5
- data/spec/raw_scanner/shared_specs.rb +3 -0
- data/spec/{proc_scanner/single_quote_str_spec.rb → raw_scanner/single_quote_str_shared_spec.rb} +1 -5
- data/spec/{proc_scanner/slash_operator_spec.rb → raw_scanner/slash_operator_shared_spec.rb} +1 -5
- data/spec/run_spec.sh +7 -1
- data/spec/spec_helper.rb +8 -25
- metadata +204 -47
- data/.rvmrc +0 -1
- data/VERSION +0 -1
- data/lib/sourcify/proc/scanner/comment.rb +0 -21
- data/lib/sourcify/proc/scanner/counter.rb +0 -44
- data/lib/sourcify/proc/scanner/dstring.rb +0 -59
- data/lib/sourcify/proc/scanner/extensions.rb +0 -171
- data/lib/sourcify/proc/scanner/heredoc.rb +0 -24
- data/spec/proc_scanner/heredoc_spec.rb +0 -144
- data/spec/proc_scanner/spec_helper.rb +0 -33
data/.gitignore
CHANGED
data/HISTORY.txt
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
=== Current (pre 0.6.0)
|
|
2
|
+
|
|
3
|
+
* adds Method#to_source, Method#to_sexp & Method#to_raw_source to MRI-1.9.2 (issue#3)
|
|
4
|
+
* extensive refactoring to existing proc support to support the above
|
|
5
|
+
|
|
1
6
|
=== 0.5.0 (May 2, 2011)
|
|
2
7
|
|
|
3
8
|
* adds Proc#to_raw_source that supports extracting of raw code, as it is written in
|
data/README.rdoc
CHANGED
|
@@ -20,6 +20,7 @@ uses a home-baked ragel-generated scanner to extract the proc code. Further proc
|
|
|
20
20
|
with RubyParser & Ruby2Ruby to ensure 100% with ParseTree (yup, there is no denying that
|
|
21
21
|
i really like ParseTree).
|
|
22
22
|
|
|
23
|
+
|
|
23
24
|
== Installing It
|
|
24
25
|
|
|
25
26
|
The religiously standard way:
|
|
@@ -30,9 +31,8 @@ Or on 1.9.* or JRuby:
|
|
|
30
31
|
|
|
31
32
|
$ gem install ruby_parser file-tail sourcify
|
|
32
33
|
|
|
33
|
-
== Using It
|
|
34
34
|
|
|
35
|
-
Sourcify adds 4 methods to Proc
|
|
35
|
+
== Sourcify adds 4 methods to Proc
|
|
36
36
|
|
|
37
37
|
=== 1. Proc#to_source
|
|
38
38
|
|
|
@@ -101,6 +101,83 @@ consistency under 1.8.*:
|
|
|
101
101
|
lambda { x + y }.source_location
|
|
102
102
|
# >> ["/tmp/test.rb", 5]
|
|
103
103
|
|
|
104
|
+
|
|
105
|
+
== Sourcify adds 3 methods to Method
|
|
106
|
+
|
|
107
|
+
*IMPORTANT*: These only work for MRI-1.9.2, as currently, only it supports
|
|
108
|
+
(1) discovering of the original source location with Method#source_location,
|
|
109
|
+
and (2) reliably determinig a method's parameters with Method#parameters.
|
|
110
|
+
Attempting to use these methods on other rubies will raise
|
|
111
|
+
Sourcify::PlatformNotSupportedError.
|
|
112
|
+
|
|
113
|
+
*NOTE*: The following works for methods defined using both def .. end &
|
|
114
|
+
Module#define_method. However, when a method is defined using the later
|
|
115
|
+
approach, sourcify uses Proc#to_source to handle the processing, thus, the
|
|
116
|
+
usual gotchas related to proc source extraction apply.
|
|
117
|
+
|
|
118
|
+
=== 1. Method#to_source
|
|
119
|
+
|
|
120
|
+
Returns the code representation of the method:
|
|
121
|
+
|
|
122
|
+
require 'sourcify'
|
|
123
|
+
|
|
124
|
+
class MyMath
|
|
125
|
+
def self.sum(x, y)
|
|
126
|
+
x + y # (blah)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
MyMath.method(:sum).to_source
|
|
131
|
+
# >> "def sum(x, y)
|
|
132
|
+
# >> (x + y)
|
|
133
|
+
# >> end"
|
|
134
|
+
|
|
135
|
+
Just like the Proc#to_source equivalent, u can set :strip_enclosure => true
|
|
136
|
+
to extract only the body within.
|
|
137
|
+
|
|
138
|
+
=== 2. Method#to_sexp
|
|
139
|
+
|
|
140
|
+
Returns the S-expression of the method:
|
|
141
|
+
|
|
142
|
+
require 'sourcify'
|
|
143
|
+
|
|
144
|
+
class MyMath
|
|
145
|
+
def self.sum(x, y)
|
|
146
|
+
x + y # (blah)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
MyMath.method(:sum).to_sexp
|
|
151
|
+
>> s(:defn,
|
|
152
|
+
>> :sum,
|
|
153
|
+
>> s(:args, :x, :y),
|
|
154
|
+
>> s(:scope, s(:block, s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))))
|
|
155
|
+
|
|
156
|
+
Just like the Proc#to_sexp equivalent, u can set :strip_enclosure => true
|
|
157
|
+
to extract only the body within.
|
|
158
|
+
|
|
159
|
+
=== 3. Method#to_raw_source
|
|
160
|
+
|
|
161
|
+
Unlike Method#to_source, which returns code that retains only functional aspects,
|
|
162
|
+
fetching of raw source returns the method's raw code, including fluff like comments:
|
|
163
|
+
|
|
164
|
+
require 'sourcify'
|
|
165
|
+
|
|
166
|
+
class MyMath
|
|
167
|
+
def self.sum(x, y)
|
|
168
|
+
x + y # (blah)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
MyMath.method(:sum).to_source
|
|
173
|
+
# >> "def sum(x, y)
|
|
174
|
+
# >> x + y # (blah)
|
|
175
|
+
# >> end"
|
|
176
|
+
|
|
177
|
+
Just like the Proc#to_raw_source equivalent, u can set :strip_enclosure => true
|
|
178
|
+
to extract only the body within.
|
|
179
|
+
|
|
180
|
+
|
|
104
181
|
== Performance
|
|
105
182
|
|
|
106
183
|
Performance is embarassing for now, benchmarking results for processing 500 procs
|
|
@@ -117,6 +194,7 @@ probably become better & faster as my knowlegde & skills with ragel improve. Als
|
|
|
117
194
|
instead of generating a pure ruby scanner, we can generate native code (eg. C or java, or
|
|
118
195
|
whatever) instead. As i'm a C & java noob, this will probably take some time to realize.
|
|
119
196
|
|
|
197
|
+
|
|
120
198
|
== Gotchas
|
|
121
199
|
|
|
122
200
|
Nothing beats ParseTree's ability to access the runtime AST, it is a very powerful feature.
|
|
@@ -210,6 +288,7 @@ Under the hood, sourcify relies on RubyParser to yield s-expression, and since R
|
|
|
210
288
|
does not yet fully handle 1.8.7 & 1.9.* syntax, you will get a nasty Racc::ParseError when
|
|
211
289
|
you have any code that is not compatible with 1.8.6.
|
|
212
290
|
|
|
291
|
+
|
|
213
292
|
== Is it really working ??
|
|
214
293
|
|
|
215
294
|
Sourcify spec suite currently passes in the following rubies:
|
|
@@ -226,6 +305,7 @@ For projects:
|
|
|
226
305
|
|
|
227
306
|
(TODO: the more the merrier)
|
|
228
307
|
|
|
308
|
+
|
|
229
309
|
== Projects using it
|
|
230
310
|
|
|
231
311
|
Projects using sourcify include:
|
|
@@ -233,6 +313,7 @@ Projects using sourcify include:
|
|
|
233
313
|
* ruote[http://ruote.rubyforge.org/]
|
|
234
314
|
* dm-ambition[https://github.com/dkubb/dm-ambition]
|
|
235
315
|
|
|
316
|
+
|
|
236
317
|
== Additional Resources
|
|
237
318
|
|
|
238
319
|
Sourcify is heavily inspired by many ideas gathered from the ruby community:
|
|
@@ -243,8 +324,9 @@ Sourcify is heavily inspired by many ideas gathered from the ruby community:
|
|
|
243
324
|
The sad fact that Proc#to_source wouldn't be available in the near future:
|
|
244
325
|
* http://redmine.ruby-lang.org/issues/show/2080
|
|
245
326
|
|
|
327
|
+
|
|
246
328
|
== Note on Patches/Pull Requests
|
|
247
|
-
|
|
329
|
+
|
|
248
330
|
* Fork the project.
|
|
249
331
|
* Make your feature addition or bug fix.
|
|
250
332
|
* Add tests for it. This is important so I don't break it in a
|
|
@@ -253,6 +335,7 @@ The sad fact that Proc#to_source wouldn't be available in the near future:
|
|
|
253
335
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
|
254
336
|
* Send me a pull request. Bonus points for topic branches.
|
|
255
337
|
|
|
338
|
+
|
|
256
339
|
== Copyright
|
|
257
340
|
|
|
258
341
|
Copyright (c) 2010 NgTzeYang. See LICENSE for details.
|
data/Rakefile
CHANGED
|
@@ -8,20 +8,38 @@ task :default => :spec
|
|
|
8
8
|
|
|
9
9
|
RUBIES = {
|
|
10
10
|
:parsetree => [
|
|
11
|
-
'ruby-1.8.6-p420@sourcify-parsetree',
|
|
12
|
-
'ruby-1.8.7-p334@sourcify-parsetree',
|
|
13
|
-
'ree-1.8.7-2011.03@sourcify-parsetree'
|
|
11
|
+
[nil, 'ruby-1.8.6-p420@sourcify-parsetree'],
|
|
12
|
+
[nil, 'ruby-1.8.7-p334@sourcify-parsetree'],
|
|
13
|
+
[nil, 'ree-1.8.7-2011.03@sourcify-parsetree']
|
|
14
14
|
],
|
|
15
15
|
:static => [
|
|
16
|
-
'ruby-1.8.6-p420@sourcify',
|
|
17
|
-
'ruby-1.8.7-p334@sourcify',
|
|
18
|
-
'ree-1.8.7-2011.03@sourcify',
|
|
19
|
-
'jruby-1.6.
|
|
20
|
-
'ruby-1.9.1-p378@sourcify',
|
|
21
|
-
'ruby-1.9.2-
|
|
16
|
+
[nil, 'ruby-1.8.6-p420@sourcify'],
|
|
17
|
+
[nil, 'ruby-1.8.7-p334@sourcify'],
|
|
18
|
+
[nil, 'ree-1.8.7-2011.03@sourcify'],
|
|
19
|
+
[nil, 'jruby-1.6.3@sourcify'],
|
|
20
|
+
[nil, 'ruby-1.9.1-p378@sourcify'],
|
|
21
|
+
['METHOD_TO_SOURCE=true', 'ruby-1.9.2-p290@sourcify'],
|
|
22
|
+
|
|
23
|
+
# NOTE: This doesn't support Method#to_source (& friends) yet yet due to
|
|
24
|
+
# jruby's Method#parameters bug, see http://jira.codehaus.org/browse/JRUBY-5954
|
|
25
|
+
['JRUBY_OPTS="--1.9"', 'jruby-1.6.3@sourcify'],
|
|
26
|
+
|
|
22
27
|
]
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
def run_spec_script_for(envs_and_rubies)
|
|
31
|
+
envs_and_rubies.group_by{|arry| arry[0..-2] }.each do |envs, arry|
|
|
32
|
+
rubies = arry.map(&:last)
|
|
33
|
+
declared_envs = ['export MUTE_BACON=true']
|
|
34
|
+
declared_envs << envs.map{|env| env ? "export #{env}" : nil }.compact
|
|
35
|
+
|
|
36
|
+
system [
|
|
37
|
+
declared_envs.flatten.join('; '),
|
|
38
|
+
"rvm #{rubies.join(',')} exec #{SPEC_SCRIPT}"
|
|
39
|
+
].join('; ')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
25
43
|
# ///////////////////////////////////////////////////////////
|
|
26
44
|
# Running Specs
|
|
27
45
|
# ///////////////////////////////////////////////////////////
|
|
@@ -32,20 +50,34 @@ end
|
|
|
32
50
|
|
|
33
51
|
desc "Run specs in all rubies (both ParseTree & static scanner modes)"
|
|
34
52
|
task :'spec:all' do
|
|
35
|
-
|
|
36
|
-
RUBIES.values.flatten.join(',') + ' exec ' + SPEC_SCRIPT
|
|
53
|
+
run_spec_script_for RUBIES.values.flatten(1)
|
|
37
54
|
end
|
|
38
55
|
|
|
39
56
|
desc "Run specs in rubies supporting ParseTree mode"
|
|
40
57
|
task :'spec:parsetree' do
|
|
41
|
-
|
|
42
|
-
RUBIES[:parsetree].join(',') + ' exec ' + SPEC_SCRIPT
|
|
58
|
+
run_spec_script_for RUBIES[:parsetree]
|
|
43
59
|
end
|
|
44
60
|
|
|
45
61
|
desc "Run specs in rubies supporting static scanner mode"
|
|
46
62
|
task :'spec:static' do
|
|
47
|
-
|
|
48
|
-
|
|
63
|
+
run_spec_script_for RUBIES[:static]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# ///////////////////////////////////////////////////////////
|
|
67
|
+
# Build ruby files from ragel definitions
|
|
68
|
+
# ///////////////////////////////////////////////////////////
|
|
69
|
+
desc "Run ragel to generate ruby scanner files from ragel definitions"
|
|
70
|
+
task :ragel do
|
|
71
|
+
%w{method proc}.each do |m|
|
|
72
|
+
common_dir = File.expand_path('../lib/sourcify/common/ragel', __FILE__)
|
|
73
|
+
ragel_dir = File.expand_path("../lib/sourcify/#{m}/parser", __FILE__)
|
|
74
|
+
ragel_file = File.join(ragel_dir, 'raw_scanner.rl')
|
|
75
|
+
ruby_file = File.join(ragel_dir, 'raw_scanner.rb')
|
|
76
|
+
File.delete(ruby_file) rescue nil
|
|
77
|
+
puts 'Processing %s -> %s' %
|
|
78
|
+
[ragel_file, ruby_file].map{|f| f.sub(File.expand_path('../', __FILE__) + '/', '')}
|
|
79
|
+
system("ragel -I #{common_dir} -R #{ragel_file}")
|
|
80
|
+
end
|
|
49
81
|
end
|
|
50
82
|
|
|
51
83
|
# ///////////////////////////////////////////////////////////
|
data/lib/sourcify.rb
CHANGED
|
@@ -12,6 +12,17 @@ rescue LoadError
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
module Sourcify #:nodoc:
|
|
15
|
+
|
|
16
|
+
IS_19x = RUBY_VERSION.include?('1.9.')
|
|
17
|
+
|
|
18
|
+
HAS_RIPPER =
|
|
19
|
+
begin
|
|
20
|
+
require 'ripper'
|
|
21
|
+
true
|
|
22
|
+
rescue LoadError
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
15
26
|
class << self
|
|
16
27
|
|
|
17
28
|
def require_rb(*args)
|
|
@@ -27,5 +38,7 @@ module Sourcify #:nodoc:
|
|
|
27
38
|
end
|
|
28
39
|
|
|
29
40
|
Sourcify.require_rb('facets')
|
|
41
|
+
Sourcify.require_rb('errors')
|
|
30
42
|
Sourcify.require_rb('version')
|
|
31
43
|
Sourcify.require_rb('proc')
|
|
44
|
+
Sourcify.require_rb('method')
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Sourcify
|
|
2
|
+
module Common
|
|
3
|
+
class Parser #:nodoc:all
|
|
4
|
+
class Converter
|
|
5
|
+
class << self
|
|
6
|
+
|
|
7
|
+
RUBY_PARSER = RubyParser.new
|
|
8
|
+
RUBY_2_RUBY = Ruby2Ruby.new
|
|
9
|
+
|
|
10
|
+
def to_sexp(code, file = nil)
|
|
11
|
+
retried = false
|
|
12
|
+
begin
|
|
13
|
+
RUBY_PARSER.reset
|
|
14
|
+
(retried ? RubyParser.new : RUBY_PARSER).parse(*[code, file].compact)
|
|
15
|
+
rescue Racc::ParseError, SyntaxError
|
|
16
|
+
return nil if retried
|
|
17
|
+
retried = true; retry
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_code(sexp)
|
|
22
|
+
RUBY_2_RUBY.process(Sexp.from_array(sexp.to_a))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Sourcify
|
|
2
|
+
module Common
|
|
3
|
+
class Parser
|
|
4
|
+
module RawScanner #:nodoc:all
|
|
5
|
+
class Comment
|
|
6
|
+
|
|
7
|
+
def <<(content)
|
|
8
|
+
(@contents ||= []) << content
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
@contents.join
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def closed?
|
|
16
|
+
@contents[-1].split("\n")[-1].strip == '=end'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Sourcify
|
|
2
|
+
module Common
|
|
3
|
+
class Parser
|
|
4
|
+
module RawScanner #:nodoc:all
|
|
5
|
+
class Counter
|
|
6
|
+
|
|
7
|
+
attr_reader :counts
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@counts = [0,0]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def started?
|
|
14
|
+
@counts.any?(&:nonzero?)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def just_started?
|
|
18
|
+
@counts.any?{|count| count == 1 }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def balanced?
|
|
22
|
+
@counts.any?(&:zero?)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def decrement
|
|
26
|
+
(0..1).each{|i| @counts[i] -= 1 unless @counts[i].zero? }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def increment(val = 1)
|
|
30
|
+
if val.is_a?(Range)
|
|
31
|
+
@counts[0] += val.first
|
|
32
|
+
@counts[1] += val.last
|
|
33
|
+
else
|
|
34
|
+
(0..1).each{|i| @counts[i] += 1 }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Sourcify
|
|
2
|
+
module Common
|
|
3
|
+
class Parser
|
|
4
|
+
module RawScanner #:nodoc:all
|
|
5
|
+
class DString < Struct.new(:tag)
|
|
6
|
+
|
|
7
|
+
# To suppress 'warning: Object#type is deprecated; use Object#class' when
|
|
8
|
+
# evaluating string
|
|
9
|
+
attr_reader :type
|
|
10
|
+
|
|
11
|
+
def <<(content)
|
|
12
|
+
(@contents ||= []) << content
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
@contents.join
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def closed?
|
|
20
|
+
evaluable? && parsable?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
CLOSING_TAGS = {'(' => ')', '[' => ']', '<' => '>', '{' => '}'}
|
|
26
|
+
|
|
27
|
+
def evaluable?
|
|
28
|
+
@contents[-1][-1].chr == end_tag
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parsable?
|
|
32
|
+
begin
|
|
33
|
+
RubyParser.new.parse(safe_contents)
|
|
34
|
+
true
|
|
35
|
+
rescue Exception
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def safe_contents
|
|
41
|
+
# NOTE: %x & ` strings are dangerous to eval cos they execute shell commands,
|
|
42
|
+
# thus we convert them to normal strings 1st
|
|
43
|
+
to_s.gsub(/(%x)(\W|\_)/, '%Q\2').gsub(/.{0,2}(`)/) do |s|
|
|
44
|
+
s =~ /^(%Q|%W|%r|%x|.?%|.?\\)/ ? s : s.sub(/`$/,'%Q`')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def start_tag
|
|
49
|
+
@start_tag ||= tag[-1].chr
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def end_tag
|
|
53
|
+
@end_tag ||= (CLOSING_TAGS[start_tag] || start_tag)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
%w{heredoc comment dstring counter}.each do |f|
|
|
2
|
+
Sourcify.require_rb('common', 'parser', 'raw_scanner', f)
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module Sourcify
|
|
6
|
+
module Common
|
|
7
|
+
class Parser
|
|
8
|
+
module RawScanner #:nodoc:all
|
|
9
|
+
module Extensions
|
|
10
|
+
|
|
11
|
+
class Escape < Exception; end
|
|
12
|
+
|
|
13
|
+
def process(data, opts={})
|
|
14
|
+
begin
|
|
15
|
+
@start_pattern = opts[:start_pattern] || /.*/
|
|
16
|
+
@body_matcher = opts[:body_matcher] || lambda{|_| true }
|
|
17
|
+
@stop_on_newline = opts[:stop_on_newline]
|
|
18
|
+
@results, @data = [], data.unpack("c*")
|
|
19
|
+
reset_attributes
|
|
20
|
+
execute!
|
|
21
|
+
rescue Escape
|
|
22
|
+
@results
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def data_frag(range)
|
|
27
|
+
@data[range].pack('c*')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def push(key, ts, te)
|
|
31
|
+
@tokens << [key, data_frag(ts .. te.pred)]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def push_dstring(ts, te)
|
|
35
|
+
data = data_frag(ts .. te.pred)
|
|
36
|
+
@dstring ||= DString.new(data[%r{^("|`|/|%(?:Q|W|r|x|)(?:\W|_))},1])
|
|
37
|
+
@dstring << data
|
|
38
|
+
return true unless @dstring.closed?
|
|
39
|
+
@tokens << [:dstring, @dstring.to_s]
|
|
40
|
+
@dstring = nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def push_comment(ts, te)
|
|
44
|
+
data = data_frag(ts .. te.pred)
|
|
45
|
+
@comment ||= Comment.new
|
|
46
|
+
@comment << data
|
|
47
|
+
return true unless @comment.closed?
|
|
48
|
+
@tokens << [:comment, @comment.to_s]
|
|
49
|
+
@comment = nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def push_heredoc(ts, te)
|
|
53
|
+
data = data_frag(ts .. te.pred)
|
|
54
|
+
unless @heredoc
|
|
55
|
+
indented, tag = data.match(/\<\<(\-?)['"]?(\w+)['"]?$/)[1..3]
|
|
56
|
+
@heredoc = Heredoc.new(tag, !indented.empty?)
|
|
57
|
+
end
|
|
58
|
+
@heredoc << data
|
|
59
|
+
return true unless @heredoc.closed?(data_frag(te .. te))
|
|
60
|
+
@tokens << [:heredoc, @heredoc.to_s]
|
|
61
|
+
@heredoc = nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def push_label(ts, te)
|
|
65
|
+
# NOTE: 1.9.* supports label key, which RubyParser cannot handle, thus
|
|
66
|
+
# conversion is needed.
|
|
67
|
+
@tokens << [:symbol, ':' + data_frag(ts .. te - 2)]
|
|
68
|
+
@tokens << [:space, ' ']
|
|
69
|
+
@tokens << [:assoc, '=>']
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def preceded_with?(*args)
|
|
73
|
+
prev_token = @tokens[-1][0] == :space ? @tokens[-2] : @tokens[-1]
|
|
74
|
+
!([args].flatten & prev_token).empty? rescue nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def increment_lineno
|
|
78
|
+
@lineno += 1
|
|
79
|
+
raise Escape \
|
|
80
|
+
if @stop_on_newline || !@results.empty? || (@results.empty? && @rejecting_block)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def codified_tokens
|
|
84
|
+
@tokens.map(&:last).join
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def reset_attributes
|
|
88
|
+
@tokens, @lineno = [], 1
|
|
89
|
+
@heredoc, @dstring, @comment, @rejecting_block = nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def offset_attributes
|
|
93
|
+
@lineno = 1 # Fixing JRuby's lineno bug (see http://jira.codehaus.org/browse/JRUBY-5014)
|
|
94
|
+
@tokens = [@tokens[-1]] unless @tokens.empty?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if HAS_RIPPER
|
|
98
|
+
|
|
99
|
+
def valid?(snippet, validate_as = nil)
|
|
100
|
+
sexp = Ripper.sexp(snippet)
|
|
101
|
+
|
|
102
|
+
case validate_as
|
|
103
|
+
when :hash then sexp[-1][0][0] == :hash
|
|
104
|
+
when nil then sexp && true
|
|
105
|
+
else raise ArgumentError
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
else
|
|
110
|
+
|
|
111
|
+
def valid?(snippet, _ = nil)
|
|
112
|
+
RubyParser.new.parse("#{snippet}") rescue false
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|