rkelly-remix 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +5 -0
- data/README.rdoc +106 -3
- data/lib/rkelly/constants.rb +1 -1
- data/lib/rkelly/generated_parser.rb +1 -1
- data/lib/rkelly/nodes/node.rb +20 -0
- data/lib/rkelly/tokenizer.rb +8 -4
- data/lib/rkelly/visitors/ecma_visitor.rb +10 -6
- data/test/expressions/test_11_4_6.rb +7 -1
- data/test/test_ecma_visitor.rb +3 -0
- metadata +17 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0735c3a4887540bf2decb0e3212c0402bb0e8a7e
|
4
|
+
data.tar.gz: d546a14e99056db30d3e3f66664f52efbbc733cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d2912446c29a7af0698985a20b87a245f9f310ece9fbde5df6db4e14479699faa7345e9c6f206fc0b46f757fc78b8cc08255001a72230a8be896828b29e46b7
|
7
|
+
data.tar.gz: 9a18576dfb4323215987fd68216c49dd9f32b206f6d52cc74d9bd93a090f0b803cf8646e5475b120df84ed386346283aeb5c01bf07b9dc2adf5126f78f836eee
|
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -1,11 +1,114 @@
|
|
1
1
|
= RKelly Remix
|
2
2
|
|
3
|
+
https://github.com/nene/rkelly-remix
|
4
|
+
|
3
5
|
== DESCRIPTION
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
RKelly Remix is a fork of the
|
8
|
+
RKelly[https://github.com/tenderlove/rkelly] JavaScript parser.
|
9
|
+
|
10
|
+
== Install
|
11
|
+
|
12
|
+
gem install rkelly-remix
|
13
|
+
|
14
|
+
Note that you can't have rkelly and rkelly-remix both installed at the
|
15
|
+
same time. That would cause a conflict since they're both included
|
16
|
+
with:
|
17
|
+
|
18
|
+
require 'rkelly'
|
19
|
+
|
20
|
+
== Example
|
21
|
+
|
22
|
+
# Iterate over and modify a JavaScript AST. Then print the modified
|
23
|
+
# AST as JavaScript.
|
24
|
+
require 'rkelly'
|
25
|
+
|
26
|
+
parser = RKelly::Parser.new
|
27
|
+
ast = parser.parse(
|
28
|
+
"for(var i = 0; i < 10; i++) { var x = 5 + 5; }"
|
29
|
+
)
|
30
|
+
|
31
|
+
ast.each do |node|
|
32
|
+
node.value = 'hello' if node.value == 'i'
|
33
|
+
node.name = 'hello' if node.respond_to?(:name) && node.name == 'i'
|
34
|
+
end
|
35
|
+
puts ast.to_ecma # => awesome javascript
|
36
|
+
|
37
|
+
== Why fork?
|
38
|
+
|
39
|
+
Currently the original RKelly project is unmaintained. The latest
|
40
|
+
release was in late 2012, and since then the author has not responded
|
41
|
+
to bug reports or pull requests.
|
42
|
+
|
43
|
+
I created this fork mainly to satisfy the needs of my
|
44
|
+
JSDuck[https://github.com/senchalabs/jsduck] project, but you too
|
45
|
+
should consider using it, as it fixes several problems in the original
|
46
|
+
RKelly:
|
47
|
+
|
48
|
+
=== Much improved speed
|
49
|
+
|
50
|
+
* 20 x faster in Ruby 1.8.
|
51
|
+
* 2 x faster in Ruby 1.9 and 2.0.
|
52
|
+
|
53
|
+
=== Correct start/end position data for all syntax nodes
|
54
|
+
|
55
|
+
Original RKelly only had a rudimentary support for getting the line
|
56
|
+
number of an AST node, and even that was often wrong.
|
57
|
+
|
58
|
+
In RKelly Remix each AST node has a range property, which contains
|
59
|
+
granular data about the exact location of the node in source code:
|
60
|
+
|
61
|
+
parser = RKelly::Parser.new
|
62
|
+
ast = parser.parse(<<-eojs)
|
63
|
+
function aaron() {
|
64
|
+
var x = 10;
|
65
|
+
return 1 + 1;
|
66
|
+
}
|
67
|
+
eojs
|
68
|
+
|
69
|
+
node = ast.pointcut(ReturnNode).matches.first
|
70
|
+
|
71
|
+
node.range.to_s # <{line:3 char:5 (41)}...{line:3 char:17 (53)}>
|
72
|
+
|
73
|
+
node.range.from.line # 3
|
74
|
+
node.range.from.char # 5
|
75
|
+
node.range.from.index # 41
|
76
|
+
|
77
|
+
node.range.to.line # 3
|
78
|
+
node.range.to.char # 17
|
79
|
+
node.range.to.index # 53
|
80
|
+
|
81
|
+
=== Sensible comments handling
|
82
|
+
|
83
|
+
Original RKelly attempted to associate each comment with a related AST
|
84
|
+
node, but failed to correctly do so, which is understandable, as there
|
85
|
+
is no standard way to do such a mapping. RKelly Remix abandons this
|
86
|
+
and just lists all commenst in the root node, leaving the user with
|
87
|
+
the task of associating them with AST nodes if he desires so (the same
|
88
|
+
approach is taken by another JS parser: Esprima[http://esprima.org] ).
|
89
|
+
|
90
|
+
parser = RKelly::Parser.new
|
91
|
+
ast = parser.parse(<<-eojs)
|
92
|
+
/**
|
93
|
+
* This is an awesome test comment.
|
94
|
+
*/
|
95
|
+
function aaron() { // This is a side comment
|
96
|
+
var x = 10;
|
97
|
+
return 1 + 1; // Equals two!
|
98
|
+
}
|
99
|
+
eojs
|
100
|
+
|
101
|
+
# print out all the comments
|
102
|
+
ast.comments.each do |c|
|
103
|
+
puts c.value
|
104
|
+
end
|
105
|
+
|
106
|
+
=== Improved parser
|
7
107
|
|
8
|
-
*
|
108
|
+
* List of reserved words matches with ECMAScript 5.1.
|
109
|
+
* Keywords are allowed in property names.
|
110
|
+
* Multibyte characters are supported in Ruby >= 1.9.
|
111
|
+
* Correct parsing of regexes like /[/]/
|
9
112
|
|
10
113
|
== License
|
11
114
|
|
data/lib/rkelly/constants.rb
CHANGED
data/lib/rkelly/nodes/node.rb
CHANGED
@@ -27,6 +27,13 @@ module RKelly
|
|
27
27
|
other.is_a?(self.class) && @value === other.value
|
28
28
|
end
|
29
29
|
|
30
|
+
# Matches nodes with the given pattern (usually a class name of
|
31
|
+
# the node) and returns an instance of PointcutVisitor on which
|
32
|
+
# #matches can be invoked to get the list of AST nodes that
|
33
|
+
# matched.
|
34
|
+
#
|
35
|
+
# ast.pointcut(RKelly::Nodes::IfNode).matches --> array of nodes
|
36
|
+
#
|
30
37
|
def pointcut(pattern)
|
31
38
|
case pattern
|
32
39
|
when String
|
@@ -44,14 +51,24 @@ module RKelly
|
|
44
51
|
end
|
45
52
|
alias :/ :pointcut
|
46
53
|
|
54
|
+
# Generates an s-expression data structure like so:
|
55
|
+
#
|
56
|
+
# "var x = 10;" --> [:var, [[:var_decl, :x, [:assign, [:lit, 10]]]]]]
|
57
|
+
#
|
47
58
|
def to_sexp
|
48
59
|
SexpVisitor.new.accept(self)
|
49
60
|
end
|
50
61
|
|
62
|
+
# Generates formatted and intented JavaScript source code.
|
51
63
|
def to_ecma
|
52
64
|
ECMAVisitor.new.accept(self)
|
53
65
|
end
|
54
66
|
|
67
|
+
# Generates a graph description in DOT language. This can be
|
68
|
+
# fed into the dot program to generate a graph of the AST:
|
69
|
+
#
|
70
|
+
# $ dot -Tpng generated-graph.dot -o graph.png
|
71
|
+
#
|
55
72
|
def to_dots
|
56
73
|
visitor = DotVisitor.new
|
57
74
|
visitor.accept(self)
|
@@ -74,10 +91,13 @@ edge [ ];
|
|
74
91
|
"#{header}\n#{nodes}\n#{arrows}\n}"
|
75
92
|
end
|
76
93
|
|
94
|
+
# Loops through all the syntax nodes.
|
77
95
|
def each(&block)
|
78
96
|
EnumerableVisitor.new(block).accept(self)
|
79
97
|
end
|
80
98
|
|
99
|
+
# This CRASHES!
|
100
|
+
# It calls method #s which is nowhere to be found.
|
81
101
|
def to_real_sexp
|
82
102
|
RealSexpVisitor.new.accept(self)
|
83
103
|
end
|
data/lib/rkelly/tokenizer.rb
CHANGED
@@ -12,11 +12,15 @@ module RKelly
|
|
12
12
|
const true false null debugger
|
13
13
|
}.map {|kw| [kw, kw.upcase.to_sym] }]
|
14
14
|
|
15
|
+
# First 6 are always reserved in ECMAScript 5.1
|
16
|
+
# Others are only reserved in strict mode.
|
17
|
+
# http://www.ecma-international.org/ecma-262/5.1/#sec-7.6.1.2
|
18
|
+
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words
|
15
19
|
RESERVED = Hash[%w{
|
16
|
-
|
17
|
-
|
18
|
-
private protected public
|
19
|
-
|
20
|
+
class enum export extends import super
|
21
|
+
|
22
|
+
implements interface package private protected public static
|
23
|
+
let yield
|
20
24
|
}.map {|kw| [kw, true] }]
|
21
25
|
|
22
26
|
LITERALS = {
|
@@ -87,9 +87,7 @@ module RKelly
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def visit_FunctionDeclNode(o)
|
90
|
-
"#{indent}function #{o.value}
|
91
|
-
"#{o.arguments.map { |x| x.accept(self) }.join(', ')})" +
|
92
|
-
"#{o.function_body.accept(self)}"
|
90
|
+
"#{indent}function #{o.value}" + function_params_and_body(o)
|
93
91
|
end
|
94
92
|
|
95
93
|
def visit_ParameterNode(o)
|
@@ -269,15 +267,21 @@ module RKelly
|
|
269
267
|
end
|
270
268
|
|
271
269
|
def visit_GetterPropertyNode(o)
|
272
|
-
"get #{o.name}
|
270
|
+
"get #{o.name}" + function_params_and_body(o.value)
|
273
271
|
end
|
274
272
|
|
275
273
|
def visit_SetterPropertyNode(o)
|
276
|
-
"set #{o.name}
|
274
|
+
"set #{o.name}" + function_params_and_body(o.value)
|
277
275
|
end
|
278
276
|
|
279
277
|
def visit_FunctionExprNode(o)
|
280
|
-
|
278
|
+
name = (o.value == 'function') ? '' : ' '+o.value
|
279
|
+
"function" + name + function_params_and_body(o)
|
280
|
+
end
|
281
|
+
|
282
|
+
# Helper for all the various function nodes
|
283
|
+
def function_params_and_body(o)
|
284
|
+
"(#{o.arguments.map { |x| x.accept(self) }.join(', ')}) " +
|
281
285
|
"#{o.function_body.accept(self)}"
|
282
286
|
end
|
283
287
|
|
@@ -62,7 +62,12 @@ class Expressions_11_4_6_Test < ECMAScriptTestCase
|
|
62
62
|
['1234e-5', 0.01234],
|
63
63
|
]
|
64
64
|
0.upto(9) { |x| @@sign_tests << [x, x] }
|
65
|
-
|
65
|
+
|
66
|
+
# 0x0 needs special treatment as sprintf("%#x", 0) results in "0"
|
67
|
+
@@sign_tests << ["0x0", 0]
|
68
|
+
@@sign_tests << ["0X0", 0]
|
69
|
+
|
70
|
+
1.upto(15) { |x|
|
66
71
|
@@sign_tests << [sprintf("%#x", x), x]
|
67
72
|
@@sign_tests << [sprintf("%#x", x).gsub(/x/, 'X'), x]
|
68
73
|
if sprintf("%#x", x) =~ /[a-f]/
|
@@ -70,6 +75,7 @@ class Expressions_11_4_6_Test < ECMAScriptTestCase
|
|
70
75
|
@@sign_tests << [sprintf("%#x", x).upcase, x]
|
71
76
|
end
|
72
77
|
}
|
78
|
+
|
73
79
|
@@sign_tests.each { |actual, expected|
|
74
80
|
define_method(:"test_num_#{actual.to_s.gsub(/[\.+]/, '_')}") do
|
75
81
|
@runtime.execute("
|
data/test/test_ecma_visitor.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rkelly-remix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Aaron Patterson
|
@@ -10,12 +9,11 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-
|
12
|
+
date: 2013-10-22 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rdoc
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
18
|
- - ~>
|
21
19
|
- !ruby/object:Gem::Version
|
@@ -23,7 +21,6 @@ dependencies:
|
|
23
21
|
type: :development
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
25
|
- - ~>
|
29
26
|
- !ruby/object:Gem::Version
|
@@ -31,25 +28,20 @@ dependencies:
|
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: hoe
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
32
|
- - ~>
|
37
33
|
- !ruby/object:Gem::Version
|
38
|
-
version: '3.
|
34
|
+
version: '3.7'
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
39
|
- - ~>
|
45
40
|
- !ruby/object:Gem::Version
|
46
|
-
version: '3.
|
47
|
-
description:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
* http://rkelly.rubyforge.org/'
|
41
|
+
version: '3.7'
|
42
|
+
description: |-
|
43
|
+
RKelly Remix is a fork of the
|
44
|
+
RKelly[https://github.com/tenderlove/rkelly] JavaScript parser.
|
53
45
|
email:
|
54
46
|
- aaron.patterson@gmail.com
|
55
47
|
- rene.saarsoo@sencha.com
|
@@ -264,8 +256,10 @@ files:
|
|
264
256
|
- test/test_while_node.rb
|
265
257
|
- test/test_with_node.rb
|
266
258
|
- .gemtest
|
267
|
-
homepage:
|
268
|
-
licenses:
|
259
|
+
homepage: https://github.com/nene/rkelly-remix
|
260
|
+
licenses:
|
261
|
+
- MIT
|
262
|
+
metadata: {}
|
269
263
|
post_install_message:
|
270
264
|
rdoc_options:
|
271
265
|
- --main
|
@@ -273,24 +267,22 @@ rdoc_options:
|
|
273
267
|
require_paths:
|
274
268
|
- lib
|
275
269
|
required_ruby_version: !ruby/object:Gem::Requirement
|
276
|
-
none: false
|
277
270
|
requirements:
|
278
|
-
- -
|
271
|
+
- - '>='
|
279
272
|
- !ruby/object:Gem::Version
|
280
273
|
version: '0'
|
281
274
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
282
|
-
none: false
|
283
275
|
requirements:
|
284
|
-
- -
|
276
|
+
- - '>='
|
285
277
|
- !ruby/object:Gem::Version
|
286
278
|
version: '0'
|
287
279
|
requirements: []
|
288
280
|
rubyforge_project: rkelly-remix
|
289
|
-
rubygems_version:
|
281
|
+
rubygems_version: 2.0.3
|
290
282
|
signing_key:
|
291
|
-
specification_version:
|
292
|
-
summary:
|
293
|
-
|
283
|
+
specification_version: 4
|
284
|
+
summary: RKelly Remix is a fork of the RKelly[https://github.com/tenderlove/rkelly]
|
285
|
+
JavaScript parser.
|
294
286
|
test_files:
|
295
287
|
- test/test_parser.rb
|
296
288
|
- test/test_ecma_visitor.rb
|