omghax-einstein 0.1.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/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2008-04-30
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Dray Lacy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,31 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/einstein.rb
9
+ lib/einstein/generated_parser.rb
10
+ lib/einstein/nodes.rb
11
+ lib/einstein/parser.rb
12
+ lib/einstein/tokenizer.rb
13
+ lib/einstein/version.rb
14
+ lib/einstein/visitors.rb
15
+ lib/parser.y
16
+ script/destroy
17
+ script/generate
18
+ script/txt2html
19
+ setup.rb
20
+ tasks/deployment.rake
21
+ tasks/environment.rake
22
+ tasks/website.rake
23
+ test/test_evaluate.rb
24
+ test/test_helper.rb
25
+ test/test_parser.rb
26
+ test/test_pretty_print.rb
27
+ website/index.html
28
+ website/index.txt
29
+ website/javascripts/rounded_corners_lite.inc.js
30
+ website/stylesheets/screen.css
31
+ website/template.rhtml
data/README.txt ADDED
@@ -0,0 +1,60 @@
1
+ = Einstein
2
+
3
+ == Description
4
+
5
+ The Einstein library provides a simple arithmetic parser for Ruby apps. Sure,
6
+ you could just use eval, but then you're opening yourself up to a world of
7
+ hurt when you accept code from untrusted sources (ie. your users). With
8
+ Einstein, you get a safe, "locked-down" arithmetic parser and evaluator that
9
+ can't run system commands or otherwise hose your server in the event of a
10
+ malicious code snippet.
11
+
12
+ Einstein was built as an excercise in language parsing in Ruby. I'm releasing
13
+ it in the hopes that someone will find the code useful, or learn something
14
+ from it...or, better yet, teach me a thing or two about writing parsers :-P
15
+
16
+ == Examples
17
+
18
+ To parse an arithmetic expression:
19
+
20
+ >> Einstein.evaluate("3 + 4")
21
+ => 7
22
+
23
+ You can also use variables:
24
+
25
+ >> Einstein.evaluate("x * 3", :x => 2)
26
+ => 6
27
+
28
+ You can also have Einstein parse the expression and return the syntax tree:
29
+
30
+ >> ast = Einstein.parse("x ** 2")
31
+ => (x ** 2)
32
+
33
+ You can then evaluate this tree for different values of x:
34
+
35
+ >> ast.evaluate(:x => 2)
36
+ => 4
37
+ >> ast.evaluate(:x => 3)
38
+ => 9
39
+
40
+ Or you can return an s-expression representation of the tree:
41
+
42
+ >> ast.to_sexp
43
+ => [:raise, [:resolve, "x"], [:lit, 2]]
44
+
45
+ == Authors
46
+
47
+ Copyright (c) 2008 by Dray Lacy
48
+
49
+ == Acknowledgements
50
+
51
+ Large portions of the parser were taken from the RKelly project by Aaron
52
+ Patterson, which was itself derived from rbnarcissus by Paul Sowden.
53
+
54
+ Thanks Aaron and Paul!
55
+
56
+ == License
57
+
58
+ Einstein is licensed under the MIT License.
59
+
60
+ :include:License.txt
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
5
+
6
+ GENERATED_PARSER = "lib/einstein/generated_parser.rb"
7
+
8
+ file GENERATED_PARSER => "lib/parser.y" do |t|
9
+ if ENV['DEBUG']
10
+ sh "racc -g -v -o #{t.name} #{t.prerequisites.first}"
11
+ else
12
+ sh "racc -o #{t.name} #{t.prerequisites.first}"
13
+ end
14
+ end
15
+
16
+ task :parser => GENERATED_PARSER
17
+
18
+ # make sure the parser's up-to-date when we test
19
+ Rake::Task[:test].prerequisites << :parser
20
+ Rake::Task[:check_manifest].prerequisites << :parser
data/config/hoe.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'einstein/version'
2
+
3
+ AUTHOR = 'Dray Lacy'
4
+ EMAIL = "dray@izea.com"
5
+ DESCRIPTION = "Safe arithmetic parser for Ruby apps"
6
+ GEM_NAME = 'einstein'
7
+ RUBYFORGE_PROJECT = 'einstein'
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ VERS = Einstein::VERSION::STRING + (REV ? ".#{REV}" : "")
33
+ RDOC_OPTS = ['--quiet', '--title', 'einstein documentation',
34
+ "--opname", "index.html",
35
+ "--line-numbers",
36
+ "--main", "README",
37
+ "--inline-source"]
38
+
39
+ class Hoe
40
+ def extra_deps
41
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
42
+ @extra_deps
43
+ end
44
+ end
45
+
46
+ # Generate all the Rake tasks
47
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
48
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
49
+ p.developer(AUTHOR, EMAIL)
50
+ p.description = DESCRIPTION
51
+ p.summary = DESCRIPTION
52
+ p.url = HOMEPATH
53
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
54
+ p.test_globs = ["test/**/test_*.rb"]
55
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
56
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
57
+ end
58
+
59
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
60
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
61
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
62
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'einstein'
@@ -0,0 +1,337 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.5
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require "einstein/nodes"
10
+
11
+ module Einstein
12
+ class GeneratedParser < Racc::Parser
13
+
14
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 79)
15
+ include Einstein::Nodes
16
+ ...end parser.y/module_eval...
17
+ ##### State transition tables begin ###
18
+
19
+ racc_action_table = [
20
+ 8, 10, 12, 19, 14, 16, 1, 8, 10, 12,
21
+ 19, 14, 16, 1, 8, 10, 12, 45, 14, 16,
22
+ 1, 8, 10, 12, 19, 14, 16, 1, 8, 10,
23
+ 12, 19, 14, 16, 1, 8, 10, 12, 44, 14,
24
+ 16, 1, 8, 10, 12, 32, 14, 16, 1, 8,
25
+ 10, 12, 27, 14, 16, 1, 8, 10, 12, 28,
26
+ 14, 16, 1, 8, 10, 12, 30, 14, 16, 1,
27
+ 8, 10, 12, 27, 14, 16, 1, 8, 10, 12,
28
+ 28, 14, 16, 1, 8, 10, 12, nil, 14, 16,
29
+ 1, 8, 10, 12, nil, 14, 16, 1, 8, 10,
30
+ 12, nil, 14, 16, 1, 8, 10, 12, nil, 14,
31
+ 16, 1, 20, 21, 22, 20, 21, 22, 20, 21,
32
+ 22, 23, 24, 23, 24, 23, 24, 25, 26, 25,
33
+ 26 ]
34
+
35
+ racc_action_check = [
36
+ 0, 0, 0, 35, 0, 0, 0, 1, 1, 1,
37
+ 4, 1, 1, 1, 32, 32, 32, 30, 32, 32,
38
+ 32, 28, 28, 28, 36, 28, 28, 28, 27, 27,
39
+ 27, 37, 27, 27, 27, 26, 26, 26, 29, 26,
40
+ 26, 26, 25, 25, 25, 15, 25, 25, 25, 21,
41
+ 21, 21, 9, 21, 21, 21, 12, 12, 12, 11,
42
+ 12, 12, 12, 23, 23, 23, 13, 23, 23, 23,
43
+ 14, 14, 14, 43, 14, 14, 14, 22, 22, 22,
44
+ 46, 22, 22, 22, 16, 16, 16, nil, 16, 16,
45
+ 16, 19, 19, 19, nil, 19, 19, 19, 20, 20,
46
+ 20, nil, 20, 20, 20, 24, 24, 24, nil, 24,
47
+ 24, 24, 38, 38, 38, 5, 5, 5, 39, 39,
48
+ 39, 40, 40, 41, 41, 6, 6, 42, 42, 7,
49
+ 7 ]
50
+
51
+ racc_action_pointer = [
52
+ -5, 2, nil, nil, 6, 103, 116, 127, nil, 37,
53
+ nil, 43, 51, 66, 65, 28, 79, nil, nil, 86,
54
+ 93, 44, 72, 58, 100, 37, 30, 23, 16, 30,
55
+ 17, nil, 9, nil, nil, -1, 20, 27, 100, 106,
56
+ 112, 114, 125, 58, nil, nil, 64 ]
57
+
58
+ racc_action_default = [
59
+ -28, -28, -6, -10, -12, -16, -19, -22, -2, -24,
60
+ -4, -26, -28, -28, -28, -1, -28, -5, -9, -28,
61
+ -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
62
+ -28, -7, -28, -8, -11, -13, -14, -15, -17, -18,
63
+ -20, -21, -23, -25, -3, 47, -27 ]
64
+
65
+ racc_goto_table = [
66
+ 18, 42, 13, 35, 36, 37, 38, 39, 40, 41,
67
+ 43, 46, nil, 31, 29, 33, nil, nil, 34 ]
68
+
69
+ racc_goto_check = [
70
+ 5, 9, 1, 6, 6, 6, 7, 7, 8, 8,
71
+ 10, 11, nil, 5, 1, 5, nil, nil, 5 ]
72
+
73
+ racc_goto_pointer = [
74
+ nil, 2, nil, nil, nil, -1, -17, -17, -17, -26,
75
+ -18, -21 ]
76
+
77
+ racc_goto_default = [
78
+ nil, nil, 15, 17, 2, 3, 4, 5, 6, 7,
79
+ 9, 11 ]
80
+
81
+ racc_reduce_table = [
82
+ 0, 0, :racc_error,
83
+ 1, 19, :_reduce_none,
84
+ 1, 21, :_reduce_2,
85
+ 3, 22, :_reduce_3,
86
+ 1, 22, :_reduce_4,
87
+ 1, 22, :_reduce_none,
88
+ 1, 23, :_reduce_none,
89
+ 2, 23, :_reduce_7,
90
+ 2, 23, :_reduce_8,
91
+ 2, 23, :_reduce_9,
92
+ 1, 24, :_reduce_none,
93
+ 3, 24, :_reduce_11,
94
+ 1, 25, :_reduce_none,
95
+ 3, 25, :_reduce_13,
96
+ 3, 25, :_reduce_14,
97
+ 3, 25, :_reduce_15,
98
+ 1, 26, :_reduce_none,
99
+ 3, 26, :_reduce_17,
100
+ 3, 26, :_reduce_18,
101
+ 1, 27, :_reduce_none,
102
+ 3, 27, :_reduce_20,
103
+ 3, 27, :_reduce_21,
104
+ 1, 28, :_reduce_none,
105
+ 3, 28, :_reduce_23,
106
+ 1, 29, :_reduce_none,
107
+ 3, 29, :_reduce_25,
108
+ 1, 20, :_reduce_none,
109
+ 3, 20, :_reduce_27 ]
110
+
111
+ racc_reduce_n = 28
112
+
113
+ racc_shift_n = 47
114
+
115
+ racc_token_table = {
116
+ false => 0,
117
+ :error => 1,
118
+ :LSHIFT => 2,
119
+ :RSHIFT => 3,
120
+ :RAISE => 4,
121
+ :NUMBER => 5,
122
+ :IDENT => 6,
123
+ "(" => 7,
124
+ ")" => 8,
125
+ "+" => 9,
126
+ "-" => 10,
127
+ "~" => 11,
128
+ "*" => 12,
129
+ "/" => 13,
130
+ "%" => 14,
131
+ "&" => 15,
132
+ "^" => 16,
133
+ "|" => 17 }
134
+
135
+ racc_nt_base = 18
136
+
137
+ racc_use_result_var = true
138
+
139
+ Racc_arg = [
140
+ racc_action_table,
141
+ racc_action_check,
142
+ racc_action_default,
143
+ racc_action_pointer,
144
+ racc_goto_table,
145
+ racc_goto_check,
146
+ racc_goto_default,
147
+ racc_goto_pointer,
148
+ racc_nt_base,
149
+ racc_reduce_table,
150
+ racc_token_table,
151
+ racc_shift_n,
152
+ racc_reduce_n,
153
+ racc_use_result_var ]
154
+
155
+ Racc_token_to_s_table = [
156
+ "$end",
157
+ "error",
158
+ "LSHIFT",
159
+ "RSHIFT",
160
+ "RAISE",
161
+ "NUMBER",
162
+ "IDENT",
163
+ "\"(\"",
164
+ "\")\"",
165
+ "\"+\"",
166
+ "\"-\"",
167
+ "\"~\"",
168
+ "\"*\"",
169
+ "\"/\"",
170
+ "\"%\"",
171
+ "\"&\"",
172
+ "\"^\"",
173
+ "\"|\"",
174
+ "$start",
175
+ "Statement",
176
+ "BitwiseOrExpr",
177
+ "Literal",
178
+ "PrimaryExpr",
179
+ "UnaryExpr",
180
+ "ExponentExpr",
181
+ "MultiplicativeExpr",
182
+ "AdditiveExpr",
183
+ "ShiftExpr",
184
+ "BitwiseAndExpr",
185
+ "BitwiseXorExpr" ]
186
+
187
+ Racc_debug_parser = false
188
+
189
+ ##### State transition tables end #####
190
+
191
+ # reduce 0 omitted
192
+
193
+ # reduce 1 omitted
194
+
195
+ module_eval(<<'.,.,', 'parser.y', 19)
196
+ def _reduce_2(val, _values, result)
197
+ result = NumberNode.new(val.first)
198
+ result
199
+ end
200
+ .,.,
201
+
202
+ module_eval(<<'.,.,', 'parser.y', 23)
203
+ def _reduce_3(val, _values, result)
204
+ result = val[1]
205
+ result
206
+ end
207
+ .,.,
208
+
209
+ module_eval(<<'.,.,', 'parser.y', 24)
210
+ def _reduce_4(val, _values, result)
211
+ result = ResolveNode.new(val.first)
212
+ result
213
+ end
214
+ .,.,
215
+
216
+ # reduce 5 omitted
217
+
218
+ # reduce 6 omitted
219
+
220
+ module_eval(<<'.,.,', 'parser.y', 30)
221
+ def _reduce_7(val, _values, result)
222
+ result = UnaryPlusNode.new(val[1])
223
+ result
224
+ end
225
+ .,.,
226
+
227
+ module_eval(<<'.,.,', 'parser.y', 31)
228
+ def _reduce_8(val, _values, result)
229
+ result = UnaryMinusNode.new(val[1])
230
+ result
231
+ end
232
+ .,.,
233
+
234
+ module_eval(<<'.,.,', 'parser.y', 32)
235
+ def _reduce_9(val, _values, result)
236
+ result = BitwiseNotNode.new(val[1])
237
+ result
238
+ end
239
+ .,.,
240
+
241
+ # reduce 10 omitted
242
+
243
+ module_eval(<<'.,.,', 'parser.y', 37)
244
+ def _reduce_11(val, _values, result)
245
+ result = ExponentNode.new(val[0], val[2])
246
+ result
247
+ end
248
+ .,.,
249
+
250
+ # reduce 12 omitted
251
+
252
+ module_eval(<<'.,.,', 'parser.y', 42)
253
+ def _reduce_13(val, _values, result)
254
+ result = MultiplyNode.new(val[0], val[2])
255
+ result
256
+ end
257
+ .,.,
258
+
259
+ module_eval(<<'.,.,', 'parser.y', 43)
260
+ def _reduce_14(val, _values, result)
261
+ result = DivideNode.new(val[0], val[2])
262
+ result
263
+ end
264
+ .,.,
265
+
266
+ module_eval(<<'.,.,', 'parser.y', 44)
267
+ def _reduce_15(val, _values, result)
268
+ result = ModulusNode.new(val[0], val[2])
269
+ result
270
+ end
271
+ .,.,
272
+
273
+ # reduce 16 omitted
274
+
275
+ module_eval(<<'.,.,', 'parser.y', 49)
276
+ def _reduce_17(val, _values, result)
277
+ result = AddNode.new(val[0], val[2])
278
+ result
279
+ end
280
+ .,.,
281
+
282
+ module_eval(<<'.,.,', 'parser.y', 50)
283
+ def _reduce_18(val, _values, result)
284
+ result = SubtractNode.new(val[0], val[2])
285
+ result
286
+ end
287
+ .,.,
288
+
289
+ # reduce 19 omitted
290
+
291
+ module_eval(<<'.,.,', 'parser.y', 55)
292
+ def _reduce_20(val, _values, result)
293
+ result = LeftShiftNode.new(val[0], val[2])
294
+ result
295
+ end
296
+ .,.,
297
+
298
+ module_eval(<<'.,.,', 'parser.y', 56)
299
+ def _reduce_21(val, _values, result)
300
+ result = RightShiftNode.new(val[0], val[2])
301
+ result
302
+ end
303
+ .,.,
304
+
305
+ # reduce 22 omitted
306
+
307
+ module_eval(<<'.,.,', 'parser.y', 61)
308
+ def _reduce_23(val, _values, result)
309
+ result = BitwiseAndNode.new(val[0], val[2])
310
+ result
311
+ end
312
+ .,.,
313
+
314
+ # reduce 24 omitted
315
+
316
+ module_eval(<<'.,.,', 'parser.y', 66)
317
+ def _reduce_25(val, _values, result)
318
+ result = BitwiseXorNode.new(val[0], val[2])
319
+ result
320
+ end
321
+ .,.,
322
+
323
+ # reduce 26 omitted
324
+
325
+ module_eval(<<'.,.,', 'parser.y', 71)
326
+ def _reduce_27(val, _values, result)
327
+ result = BitwiseOrNode.new(val[0], val[2])
328
+ result
329
+ end
330
+ .,.,
331
+
332
+ def _reduce_none(val, _values, result)
333
+ val[0]
334
+ end
335
+
336
+ end # class GeneratedParser
337
+ end # module Einstein