arst 0.0.1 → 0.0.3
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.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +9 -2
- data/README.md +230 -21
- data/VERSION +1 -1
- data/arst.gemspec +2 -3
- data/examples/Rakefile +5 -0
- data/examples/simple.arst +16 -0
- data/lib/arst.rb +8 -0
- data/lib/arst/generator.rb +14 -0
- data/lib/arst/generator/arst.rb +37 -0
- data/lib/arst/generator/base.rb +29 -0
- data/lib/arst/generator/c.rb +11 -0
- data/lib/arst/generator/ruby.rb +164 -0
- data/lib/arst/helpers.rb +13 -0
- data/lib/arst/node.rb +25 -0
- data/lib/arst/node/base.rb +39 -0
- data/lib/arst/node/class.rb +32 -0
- data/lib/arst/node/extend.rb +14 -0
- data/lib/arst/node/include.rb +14 -0
- data/lib/arst/node/module.rb +14 -0
- data/lib/arst/node/namable.rb +26 -0
- data/lib/arst/node/root.rb +11 -0
- data/lib/arst/parser.rb +64 -0
- data/lib/arst/rake_task.rb +62 -0
- metadata +40 -49
- data/examples/indentation_sensitive.rb +0 -84
- data/examples/simple.rb +0 -31
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14e94c66c9581aa1b34916e7d471a03d72ae29bd
|
4
|
+
data.tar.gz: 26ad558b52a7621a317545033aa039b9b5ce50b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 049fac53c834139edd2bb171b97cd526498d4c5bf8241ba3793998d5f1d8ccd518c6fb5a6e82be2a30efbe4df96e4fe7bc6bf941ee2b9b101ec23d169086fd50
|
7
|
+
data.tar.gz: fe66efb68766698e169712774342a3090af78423e29cf9cff2e8b250a47ebedb82e690a22bbd2f57cdd517965700a11f1058fd98eb78b0a2d2b8e46c3c9adc4a
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
arst (0.0.
|
4
|
+
arst (0.0.3)
|
5
5
|
active_support (~> 3.0.0)
|
6
6
|
parslet (~> 1.5.0)
|
7
|
+
rake (~> 10.0.0)
|
7
8
|
version (~> 1.0.0)
|
8
9
|
|
9
10
|
GEM
|
@@ -40,11 +41,17 @@ GEM
|
|
40
41
|
coderay (~> 1.0.5)
|
41
42
|
method_source (~> 0.8)
|
42
43
|
slop (~> 3.4)
|
44
|
+
pry (0.9.12-x86-mingw32)
|
45
|
+
coderay (~> 1.0.5)
|
46
|
+
method_source (~> 0.8)
|
47
|
+
slop (~> 3.4)
|
48
|
+
win32console (~> 1.3)
|
43
49
|
rake (10.0.4)
|
44
50
|
rb-fsevent (0.9.3)
|
45
51
|
slop (3.4.4)
|
46
52
|
thor (0.18.1)
|
47
53
|
version (1.0.0)
|
54
|
+
win32console (1.3.2-x86-mingw32)
|
48
55
|
|
49
56
|
PLATFORMS
|
50
57
|
ruby
|
@@ -56,5 +63,5 @@ DEPENDENCIES
|
|
56
63
|
cocaine (~> 0.5.0)
|
57
64
|
guard-bundler (~> 1.0.0)
|
58
65
|
guard-shell (~> 0.5.0)
|
59
|
-
|
66
|
+
pry
|
60
67
|
rb-fsevent (~> 0.9.0)
|
data/README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# ARST
|
2
2
|
|
3
|
-
Abstract Ruby Syntax Tree (ARST) is a high-level language syntax denoting the object domain of a Ruby project.
|
3
|
+
Abstract Ruby Syntax Tree (ARST) is a high-level language syntax denoting the object domain of a Ruby project and a polyglot source code generator.
|
4
4
|
|
5
5
|
ARST can be used to generate:
|
6
6
|
|
7
|
-
* Pure Ruby
|
7
|
+
* Pure Ruby code
|
8
8
|
* C Ruby extensions
|
9
|
+
* Java Ruby extensions
|
9
10
|
* Test::Unit, MiniTest::Unit, MiniTest::Spec, or RSpec tests
|
10
11
|
* GraphViz graphs
|
11
12
|
* Custom output
|
@@ -18,15 +19,15 @@ ARST files can also be generated from existing projects which allows:
|
|
18
19
|
|
19
20
|
Integrations:
|
20
21
|
|
21
|
-
*
|
22
|
+
* Rake (baked in)
|
22
23
|
* [Thor](https://github.com/RyanScottLewis/thor-arst)
|
23
24
|
* [Guard](https://github.com/RyanScottLewis/guard-arst)
|
24
25
|
|
25
26
|
Generators:
|
26
27
|
|
27
|
-
* ARST::Generator::Ruby (baked
|
28
|
-
* ARST::Generator::
|
29
|
-
* [ARST::Generator::
|
28
|
+
* ARST::Generator::Ruby (baked in)
|
29
|
+
* ARST::Generator::C (baked in)
|
30
|
+
* [ARST::Generator::Java](https://github.com/RyanScottLewis/arst-generator-java)
|
30
31
|
* [ARST::Generator::Test::Unit](https://github.com/RyanScottLewis/arst-generator-test-unit)
|
31
32
|
* [ARST::Generator::MiniTest::Unit](https://github.com/RyanScottLewis/arst-generator-minitest-unit)
|
32
33
|
* [ARST::Generator::MiniTest::Spec](https://github.com/RyanScottLewis/arst-generator-minitest-spec)
|
@@ -53,6 +54,9 @@ This means that most syntax highlighters for Ruby will also work for ARST.
|
|
53
54
|
* `class ClassName < SuperClassName`
|
54
55
|
* `include ModuleName`
|
55
56
|
* `extend ModuleName`
|
57
|
+
|
58
|
+
**Not Yet Implemented:**
|
59
|
+
|
56
60
|
* `def instance_method(arg1, *other_args)` (and anything else accepted method arguments in Ruby's syntax)
|
57
61
|
* `def self.class_method(arg1, opts={})` (and anything else accepted method arguments in Ruby's syntax)
|
58
62
|
|
@@ -61,42 +65,247 @@ This means that most syntax highlighters for Ruby will also work for ARST.
|
|
61
65
|
ARST is an indentation-sensitive syntax meaning that the following are **not** equivalent:
|
62
66
|
|
63
67
|
<table width="100%"><tr><td>
|
64
|
-
|
68
|
+
<pre>
|
65
69
|
module Foo
|
66
70
|
module Bar
|
67
|
-
|
71
|
+
</pre>
|
68
72
|
</td><td>
|
69
|
-
|
73
|
+
<pre>
|
70
74
|
module Foo
|
71
75
|
module Bar
|
72
|
-
|
73
|
-
</td></tr
|
76
|
+
</pre>
|
77
|
+
</td></tr></table>
|
74
78
|
|
75
|
-
When interpreting the ARST syntax, the parser accepts
|
76
|
-
at the
|
77
|
-
Valid whitespace characters are the space
|
79
|
+
When interpreting the ARST syntax, the parser accepts 2 identical sequential whitespace characters
|
80
|
+
at the start of a line as an "indentation step".
|
81
|
+
Valid whitespace characters are the space and tab characters.
|
78
82
|
|
79
83
|
Once the first indentation step is found while parsing, all subsequent indentation steps must contain the same
|
80
84
|
amount of whitespace characters as the first step:
|
81
85
|
|
82
86
|
<table width="100%"><tr><td>
|
83
|
-
|
84
|
-
|
87
|
+
<b>Valid</b>
|
88
|
+
<pre>
|
85
89
|
module Foo
|
86
90
|
module Bar
|
87
91
|
module Baz
|
88
|
-
|
92
|
+
</pre>
|
89
93
|
</td><td>
|
90
|
-
|
91
|
-
|
94
|
+
<b>Invalid</b>
|
95
|
+
<pre>
|
92
96
|
module Foo
|
93
97
|
module Bar
|
94
98
|
module Baz
|
95
|
-
|
96
|
-
</td></tr
|
99
|
+
</pre>
|
100
|
+
</td></tr></table>
|
97
101
|
|
98
102
|
## Usage
|
99
103
|
|
104
|
+
### Constructing ARST file
|
105
|
+
|
106
|
+
The first step is to create an `.arst` file within your project. There is no convention as to where to place this file,
|
107
|
+
but I like to put it in the root directory and name it the same as my project, like a `.gemspec` file.
|
108
|
+
|
109
|
+
`stupid_record.arst`
|
110
|
+
|
111
|
+
```rb
|
112
|
+
module StupidModel
|
113
|
+
module Validations
|
114
|
+
module Callbacks
|
115
|
+
module Serialization
|
116
|
+
module ClassMethods
|
117
|
+
module InstanceMethods
|
118
|
+
class Base
|
119
|
+
extend Callbacks
|
120
|
+
include Validations
|
121
|
+
include Serialization
|
122
|
+
module StupidRecord
|
123
|
+
module Persistence
|
124
|
+
class Base < StupidModel::Base
|
125
|
+
include Persistence
|
126
|
+
```
|
127
|
+
|
128
|
+
### Setup Rake task
|
129
|
+
|
130
|
+
`Rakefile`
|
131
|
+
|
132
|
+
```rb
|
133
|
+
require 'arst/rake_task'
|
134
|
+
|
135
|
+
ARST::RakeTask.new do |t|
|
136
|
+
t.generate(:ruby, input_path: 'stupid_record.arst', split_files: false, output_path: 'lib/stupid_record.rb')
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
### Generate your code
|
141
|
+
|
142
|
+
### Ruby
|
143
|
+
|
144
|
+
Running `rake arst:ruby` will generate the following Ruby code in the `lib/stupid_record.rb` file:
|
145
|
+
|
146
|
+
```rb
|
147
|
+
module StupidModel
|
148
|
+
module Validations
|
149
|
+
end
|
150
|
+
module Callbacks
|
151
|
+
end
|
152
|
+
module Serialization
|
153
|
+
module ClassMethods
|
154
|
+
end
|
155
|
+
module InstanceMethods
|
156
|
+
end
|
157
|
+
end
|
158
|
+
class Base
|
159
|
+
extend Callbacks
|
160
|
+
include Validations
|
161
|
+
include Serialization
|
162
|
+
end
|
163
|
+
end
|
164
|
+
module StupidRecord
|
165
|
+
module Persistence
|
166
|
+
end
|
167
|
+
class Base < StupidModel::Base
|
168
|
+
include Persistence
|
169
|
+
end
|
170
|
+
end
|
171
|
+
```
|
172
|
+
|
173
|
+
Tasty! We turned 14 lines into 24 lines, like magic! But wait.. this isn't how conventional Ruby projects file hierarchies
|
174
|
+
are structured. The above is great for generating simple example Ruby files, but what about bootstrapping an entire project?
|
175
|
+
|
176
|
+
Let's refactor our Rake task:
|
177
|
+
|
178
|
+
`Rakefile`
|
179
|
+
|
180
|
+
```rb
|
181
|
+
require 'arst/rake_task'
|
182
|
+
|
183
|
+
ARST::RakeTask.new do |t|
|
184
|
+
t.add_generator type: :ruby, input_path: 'stupid_record.arst', output_path: 'stupid_record/lib'
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
> Note: The `:split_files` option is `true` and the `output_path` option is `'lib'` by default in the Ruby generator.
|
189
|
+
> Each generator has it's own set of options.
|
190
|
+
|
191
|
+
Now, when we run the `rake arst:generate` task to generate our code, the project is bootstrapped in a more conventional manner:
|
192
|
+
|
193
|
+
`lib/stupid_model.rb`
|
194
|
+
|
195
|
+
```rb
|
196
|
+
require 'stupid_model/base'
|
197
|
+
|
198
|
+
module StupidModel
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
`lib/stupid_model/validations.rb`
|
203
|
+
|
204
|
+
```rb
|
205
|
+
module StupidModel
|
206
|
+
module Validations
|
207
|
+
end
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
`lib/stupid_model/callbacks.rb`
|
212
|
+
|
213
|
+
```rb
|
214
|
+
module StupidModel
|
215
|
+
module Callbacks
|
216
|
+
end
|
217
|
+
end
|
218
|
+
```
|
219
|
+
|
220
|
+
`lib/stupid_model/serialization.rb`
|
221
|
+
|
222
|
+
```rb
|
223
|
+
require 'stupid_model/serialization/class_methods'
|
224
|
+
require 'stupid_model/serialization/instance_methods'
|
225
|
+
|
226
|
+
module StupidModel
|
227
|
+
module Serialization
|
228
|
+
end
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
`lib/stupid_model/serialization/class_methods.rb`
|
233
|
+
|
234
|
+
```rb
|
235
|
+
module StupidModel
|
236
|
+
module Serialization
|
237
|
+
module ClassMethods
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
243
|
+
`lib/stupid_model/serialization/instance_methods.rb`
|
244
|
+
|
245
|
+
```rb
|
246
|
+
module StupidModel
|
247
|
+
module Serialization
|
248
|
+
module InstanceMethods
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
```
|
253
|
+
|
254
|
+
`lib/stupid_model/base.rb`
|
255
|
+
|
256
|
+
```rb
|
257
|
+
require 'stupid_model/validations'
|
258
|
+
require 'stupid_model/callbacks'
|
259
|
+
require 'stupid_model/serialization'
|
260
|
+
|
261
|
+
module StupidModel
|
262
|
+
class Base
|
263
|
+
extend Callbacks
|
264
|
+
include Validations
|
265
|
+
include Serialization
|
266
|
+
end
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
`lib/stupid_record.rb`
|
271
|
+
|
272
|
+
```rb
|
273
|
+
require 'stupid_record/base'
|
274
|
+
|
275
|
+
module StupidRecord
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
279
|
+
`lib/stupid_record/persistence.rb`
|
280
|
+
|
281
|
+
```rb
|
282
|
+
module StupidRecord
|
283
|
+
module Persistence
|
284
|
+
end
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
288
|
+
`lib/stupid_record/base.rb`
|
289
|
+
|
290
|
+
```rb
|
291
|
+
require 'stupid_model/base'
|
292
|
+
require 'stupid_record/persistence'
|
293
|
+
|
294
|
+
module StupidRecord
|
295
|
+
class Base < StupidModel::Base
|
296
|
+
include Persistence
|
297
|
+
end
|
298
|
+
end
|
299
|
+
```
|
300
|
+
|
301
|
+
Holy Moses! Now we're saving some typing!
|
302
|
+
This may not be exactly the code you were looking to generate, but it's close enough to start working quickly.
|
303
|
+
|
304
|
+
The ARST Ruby generator attempts to be as smart about adding `require` statements as possible.
|
305
|
+
|
306
|
+
> Warning: When we generate the files, they are OVERWRITTEN. Meaning you WILL LOSE CODE if the file already exists.
|
307
|
+
> There are plans in the *far* future for generating only missing nodes in the ARST and removing code that is NOT within the ARST.
|
308
|
+
|
100
309
|
## Copyright
|
101
310
|
|
102
311
|
Copyright © 2013 Ryan Scott Lewis <ryan@rynet.us>.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/arst.gemspec
CHANGED
@@ -11,15 +11,14 @@ Gem::Specification.new do |s|
|
|
11
11
|
# Dependencies
|
12
12
|
s.add_dependency 'active_support', '~> 3.0.0'
|
13
13
|
s.add_dependency 'parslet', '~> 1.5.0'
|
14
|
+
s.add_dependency 'rake', '~> 10.0.0'
|
14
15
|
s.add_dependency 'version', '~> 1.0.0'
|
15
16
|
# s.add_dependency 'polyglot', '~> 0.3.0'
|
16
17
|
s.add_development_dependency 'awesome_print', '~> 1.1.0'
|
17
18
|
s.add_development_dependency 'cocaine', '~> 0.5.0'
|
18
19
|
s.add_development_dependency 'guard-bundler', '~> 1.0.0'
|
19
20
|
s.add_development_dependency 'guard-shell', '~> 0.5.0'
|
20
|
-
s.add_development_dependency 'rake', '~> 10.0.0'
|
21
21
|
s.add_development_dependency 'rb-fsevent', '~> 0.9.0'
|
22
|
-
|
23
22
|
|
24
23
|
# Pragmatically set variables
|
25
24
|
s.homepage = "http://github.com/RyanScottLewis/#{s.name}"
|
@@ -27,7 +26,7 @@ Gem::Specification.new do |s|
|
|
27
26
|
s.description = s.summary
|
28
27
|
s.name = Pathname.new(__FILE__).basename('.gemspec').to_s
|
29
28
|
s.require_paths = ['lib']
|
30
|
-
s.files = Dir['{{Rake,Gem}file{.lock,},README*,VERSION,LICENSE,*.gemspec,lib
|
29
|
+
s.files = Dir['{{Rake,Gem}file{.lock,},README*,VERSION,LICENSE,*.gemspec,{lib,bin,examples,spec,test}/**/*}']
|
31
30
|
s.test_files = Dir['{examples,spec,test}/**/*']
|
32
31
|
|
33
32
|
end
|
data/examples/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module StupidModel
|
2
|
+
module Validations
|
3
|
+
module Callbacks
|
4
|
+
module Serialization
|
5
|
+
module ClassMethods
|
6
|
+
module InstanceMethods
|
7
|
+
module OptionalMethods
|
8
|
+
class Base
|
9
|
+
extend Callbacks
|
10
|
+
include Validations
|
11
|
+
include Serialization
|
12
|
+
module StupidRecord
|
13
|
+
module Persistence
|
14
|
+
class Base < StupidModel::Base
|
15
|
+
include Persistence
|
16
|
+
include StupidModel::OptionalMethods
|
data/lib/arst.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'arst/generator/base'
|
2
|
+
|
3
|
+
module ARST
|
4
|
+
module Generator
|
5
|
+
|
6
|
+
class ARST < Base
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def parse_children(node, options={})
|
11
|
+
output = ''
|
12
|
+
|
13
|
+
node[:children].each do |node|
|
14
|
+
output << (options[:indent_char] * options[:indent_size]) * options[:depth]
|
15
|
+
|
16
|
+
if node[:module]
|
17
|
+
output << "module #{ node[:module] }"
|
18
|
+
elsif node[:class]
|
19
|
+
output << "class #{ node[:class] }"
|
20
|
+
output << " < #{ node[:superclass] }" if node[:superclass]
|
21
|
+
elsif node[:include]
|
22
|
+
output << "include #{ node[:include] }"
|
23
|
+
elsif node[:extend]
|
24
|
+
output << "extend #{ node[:extend] }"
|
25
|
+
end
|
26
|
+
|
27
|
+
output << "\n"
|
28
|
+
output << parse_children( node, options.merge(depth: options[:depth]+1) ) if node.has_key?(:children)
|
29
|
+
end
|
30
|
+
|
31
|
+
output
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|