simply_stored 0.1.4
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/lib/simply_stored/class_methods_base.rb +31 -0
- data/lib/simply_stored/couch/belongs_to.rb +117 -0
- data/lib/simply_stored/couch/ext/couch_potato.rb +16 -0
- data/lib/simply_stored/couch/has_many.rb +148 -0
- data/lib/simply_stored/couch/has_one.rb +93 -0
- data/lib/simply_stored/couch/validations.rb +74 -0
- data/lib/simply_stored/couch/views/array_property_view_spec.rb +22 -0
- data/lib/simply_stored/couch/views.rb +1 -0
- data/lib/simply_stored/couch.rb +278 -0
- data/lib/simply_stored/instance_methods.rb +143 -0
- data/lib/simply_stored/simpledb/associations.rb +196 -0
- data/lib/simply_stored/simpledb/attributes.rb +173 -0
- data/lib/simply_stored/simpledb/storag.rb +85 -0
- data/lib/simply_stored/simpledb/validations.rb +88 -0
- data/lib/simply_stored/simpledb.rb +212 -0
- data/lib/simply_stored/storage.rb +93 -0
- data/lib/simply_stored.rb +9 -0
- data/test/custom_views_test.rb +33 -0
- data/test/fixtures/couch.rb +182 -0
- data/test/fixtures/simpledb/item.rb +11 -0
- data/test/fixtures/simpledb/item_daddy.rb +8 -0
- data/test/fixtures/simpledb/log_item.rb +3 -0
- data/test/fixtures/simpledb/namespace_bar.rb +5 -0
- data/test/fixtures/simpledb/namespace_foo.rb +7 -0
- data/test/fixtures/simpledb/protected_item.rb +3 -0
- data/test/simply_stored_couch_test.rb +1684 -0
- data/test/simply_stored_simpledb_test.rb +1341 -0
- data/test/test_helper.rb +22 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/dot/dot.rb +29 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/evaluator/evaluator.rb +133 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/closure_hash.rb +15 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar.rb +240 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar_symbol.rb +27 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/precedence.rb +19 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/production.rb +36 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/accept_actions.rb +36 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/alphabet.rb +21 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/compiled_lexer.rb +46 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/dfa.rb +121 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexeme.rb +32 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer.rb +70 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer_run.rb +78 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_grammar.rb +392 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_parser.rb +2010 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_tokenizer.rb +14 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/specification.rb +96 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state.rb +68 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state_machine.rb +37 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/action.rb +55 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/channel.rb +58 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/compiled_parser.rb +51 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/conflict.rb +54 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/item.rb +42 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_result.rb +50 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_tree.rb +66 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser.rb +165 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_methods.rb +11 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_run.rb +39 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_state.rb +74 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/token.rb +22 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/runtime.rb +51 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka/tokenizer/tokenizer.rb +190 -0
- data/test/vendor/dhaka-2.2.1/lib/dhaka.rb +62 -0
- data/test/vendor/dhaka-2.2.1/test/all_tests.rb +5 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator.rb +64 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator_test.rb +43 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar.rb +41 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar_test.rb +9 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_test_methods.rb +9 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer.rb +39 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer_test.rb +38 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_evaluator.rb +43 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +24 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar_test.rb +30 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_lexer_specification.rb +23 -0
- data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +33 -0
- data/test/vendor/dhaka-2.2.1/test/brackets/bracket_grammar.rb +23 -0
- data/test/vendor/dhaka-2.2.1/test/brackets/bracket_tokenizer.rb +22 -0
- data/test/vendor/dhaka-2.2.1/test/brackets/brackets_test.rb +28 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver.rb +46 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver_test.rb +276 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator.rb +284 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator_test.rb +38 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_grammar.rb +104 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer.rb +109 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_specification.rb +37 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_test.rb +58 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser.rb +879 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser_test.rb +55 -0
- data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_test.rb +170 -0
- data/test/vendor/dhaka-2.2.1/test/core/another_lalr_but_not_slr_grammar.rb +20 -0
- data/test/vendor/dhaka-2.2.1/test/core/compiled_parser_test.rb +44 -0
- data/test/vendor/dhaka-2.2.1/test/core/dfa_test.rb +170 -0
- data/test/vendor/dhaka-2.2.1/test/core/evaluator_test.rb +22 -0
- data/test/vendor/dhaka-2.2.1/test/core/grammar_test.rb +83 -0
- data/test/vendor/dhaka-2.2.1/test/core/lalr_but_not_slr_grammar.rb +19 -0
- data/test/vendor/dhaka-2.2.1/test/core/lexer_test.rb +139 -0
- data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar.rb +7 -0
- data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar_test.rb +8 -0
- data/test/vendor/dhaka-2.2.1/test/core/nullable_grammar.rb +21 -0
- data/test/vendor/dhaka-2.2.1/test/core/parse_result_test.rb +44 -0
- data/test/vendor/dhaka-2.2.1/test/core/parser_state_test.rb +24 -0
- data/test/vendor/dhaka-2.2.1/test/core/parser_test.rb +131 -0
- data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar.rb +17 -0
- data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar_test.rb +9 -0
- data/test/vendor/dhaka-2.2.1/test/core/rr_conflict_grammar.rb +21 -0
- data/test/vendor/dhaka-2.2.1/test/core/simple_grammar.rb +22 -0
- data/test/vendor/dhaka-2.2.1/test/core/sr_conflict_grammar.rb +16 -0
- data/test/vendor/dhaka-2.2.1/test/dhaka_test_helper.rb +17 -0
- data/test/vendor/dhaka-2.2.1/test/fake_logger.rb +17 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb/client_exception.rb +10 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb/db.rb +146 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb/query_language.rb +266 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb/server.rb +33 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb/servlet.rb +191 -0
- data/test/vendor/simplerdb-0.2/lib/simplerdb.rb +3 -0
- data/test/vendor/simplerdb-0.2/test/functional_test.rb +81 -0
- data/test/vendor/simplerdb-0.2/test/query_evaluator_test.rb +73 -0
- data/test/vendor/simplerdb-0.2/test/query_parser_test.rb +64 -0
- data/test/vendor/simplerdb-0.2/test/simplerdb_test.rb +80 -0
- metadata +182 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + "/chittagong_grammar"
|
|
3
|
+
require File.dirname(__FILE__) + "/chittagong_lexer_specification"
|
|
4
|
+
begin
|
|
5
|
+
require File.dirname(__FILE__) + "/chittagong_parser"
|
|
6
|
+
require File.dirname(__FILE__) + "/chittagong_lexer"
|
|
7
|
+
rescue LoadError
|
|
8
|
+
puts "Please run the rake command in the root folder to generate the lexer and parser required for this test."
|
|
9
|
+
exit
|
|
10
|
+
end
|
|
11
|
+
require File.dirname(__FILE__) + "/chittagong_driver"
|
|
12
|
+
|
|
13
|
+
class TestChittagongDriver < Test::Unit::TestCase
|
|
14
|
+
def setup
|
|
15
|
+
@driver = ChittagongDriver.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_return_statement_not_allowed_in_main
|
|
19
|
+
# Programs with problems
|
|
20
|
+
program = "
|
|
21
|
+
|
|
22
|
+
if 1 > 2
|
|
23
|
+
return 5
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
print 2
|
|
27
|
+
"
|
|
28
|
+
assert_equal(
|
|
29
|
+
"Unexpected token return:
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if 1 > 2
|
|
33
|
+
>>>return 5
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
print 2
|
|
37
|
+
", @driver.run(program))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_catches_unexpected_end_of_input
|
|
41
|
+
program = "
|
|
42
|
+
def"
|
|
43
|
+
assert_equal("Unexpected end of file.", @driver.run(program))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_catches_unexpected_characters
|
|
47
|
+
program = "
|
|
48
|
+
print 2
|
|
49
|
+
def #}
|
|
50
|
+
"
|
|
51
|
+
assert_equal(
|
|
52
|
+
"Unexpected character #:
|
|
53
|
+
|
|
54
|
+
print 2
|
|
55
|
+
def >>>#}
|
|
56
|
+
", @driver.run(program))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_catches_undefined_variables
|
|
60
|
+
program = "
|
|
61
|
+
x = 1
|
|
62
|
+
y = 2
|
|
63
|
+
def foo(n)
|
|
64
|
+
return 2
|
|
65
|
+
end
|
|
66
|
+
foo(1)
|
|
67
|
+
|
|
68
|
+
if x > y
|
|
69
|
+
print 999
|
|
70
|
+
print 777
|
|
71
|
+
else
|
|
72
|
+
print 66
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
print x
|
|
76
|
+
print y
|
|
77
|
+
print 2*3+c
|
|
78
|
+
print 888
|
|
79
|
+
|
|
80
|
+
"
|
|
81
|
+
|
|
82
|
+
assert_equal(
|
|
83
|
+
"66.0
|
|
84
|
+
1.0
|
|
85
|
+
2.0
|
|
86
|
+
Undefined variable c:
|
|
87
|
+
|
|
88
|
+
x = 1
|
|
89
|
+
y = 2
|
|
90
|
+
def foo(n)
|
|
91
|
+
return 2
|
|
92
|
+
end
|
|
93
|
+
foo(1)
|
|
94
|
+
|
|
95
|
+
if x > y
|
|
96
|
+
print 999
|
|
97
|
+
print 777
|
|
98
|
+
else
|
|
99
|
+
print 66
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
print x
|
|
103
|
+
print y
|
|
104
|
+
print 2*3+>>>c
|
|
105
|
+
print 888
|
|
106
|
+
|
|
107
|
+
", @driver.run(program))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_catches_undefined_functions
|
|
111
|
+
program = "
|
|
112
|
+
|
|
113
|
+
def foo(n)
|
|
114
|
+
bar(x)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
foo(2)
|
|
118
|
+
|
|
119
|
+
"
|
|
120
|
+
assert_equal(
|
|
121
|
+
"Undefined function bar:
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def foo(n)
|
|
125
|
+
>>>bar(x)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
foo(2)
|
|
129
|
+
|
|
130
|
+
", @driver.run(program))
|
|
131
|
+
end
|
|
132
|
+
# lipi:variable_scoping
|
|
133
|
+
def test_variable_scope
|
|
134
|
+
program = "
|
|
135
|
+
x = 1
|
|
136
|
+
|
|
137
|
+
def bar(n)
|
|
138
|
+
print 999
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def foo(n)
|
|
142
|
+
bar(x)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
foo(2)
|
|
146
|
+
|
|
147
|
+
"
|
|
148
|
+
assert_equal(
|
|
149
|
+
"Undefined variable x:
|
|
150
|
+
|
|
151
|
+
x = 1
|
|
152
|
+
|
|
153
|
+
def bar(n)
|
|
154
|
+
print 999
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def foo(n)
|
|
158
|
+
bar(>>>x)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
foo(2)
|
|
162
|
+
|
|
163
|
+
", @driver.run(program))
|
|
164
|
+
end
|
|
165
|
+
# lipi:variable_scoping
|
|
166
|
+
|
|
167
|
+
def test_nested_function_calls
|
|
168
|
+
|
|
169
|
+
program = "
|
|
170
|
+
|
|
171
|
+
def foo(a)
|
|
172
|
+
return a + 2
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def bar(b, c)
|
|
176
|
+
return b + c
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def baz(x, y, z)
|
|
180
|
+
return foo(y) + bar(x, z)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
print baz(foo(1), bar(2, 3), bar(6, 2))
|
|
184
|
+
|
|
185
|
+
"
|
|
186
|
+
assert_equal("18.0", @driver.run(program))
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_wrong_number_of_arguments
|
|
190
|
+
|
|
191
|
+
program = "
|
|
192
|
+
|
|
193
|
+
def whatever(a, b)
|
|
194
|
+
return a + b
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
whatever(1, 2, 3)
|
|
198
|
+
|
|
199
|
+
"
|
|
200
|
+
assert_equal(
|
|
201
|
+
"Wrong number of arguments:
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def whatever(a, b)
|
|
205
|
+
return a + b
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
whatever>>>(1, 2, 3)
|
|
209
|
+
|
|
210
|
+
", @driver.run(program))
|
|
211
|
+
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def test_an_empty_program
|
|
215
|
+
program = ""
|
|
216
|
+
assert_equal("Unexpected end of file.", @driver.run(program))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_associating_equality_tests_should_show_an_error
|
|
220
|
+
program = "
|
|
221
|
+
def foo()
|
|
222
|
+
print 999
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
foo()
|
|
226
|
+
print 1 == 1 == 1"
|
|
227
|
+
|
|
228
|
+
assert_equal("Unexpected token ==:
|
|
229
|
+
|
|
230
|
+
def foo()
|
|
231
|
+
print 999
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
foo()
|
|
235
|
+
print 1 == 1 >>>== 1", @driver.run(program))
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def test_catches_bad_decimal_points
|
|
239
|
+
program = "
|
|
240
|
+
a = .234
|
|
241
|
+
c = 23.523
|
|
242
|
+
b = 20..2
|
|
243
|
+
"
|
|
244
|
+
|
|
245
|
+
assert_equal("Unexpected character .:
|
|
246
|
+
|
|
247
|
+
a = .234
|
|
248
|
+
c = 23.523
|
|
249
|
+
b = 20.>>>.2
|
|
250
|
+
", @driver.run(program))
|
|
251
|
+
end
|
|
252
|
+
# lipi:recursive_fib
|
|
253
|
+
def test_recursive_fibonacci
|
|
254
|
+
program = "
|
|
255
|
+
|
|
256
|
+
def fib(n)
|
|
257
|
+
if n == 0
|
|
258
|
+
return 1
|
|
259
|
+
end
|
|
260
|
+
if n == 1
|
|
261
|
+
return 1
|
|
262
|
+
end
|
|
263
|
+
return fib(n-1) + fib(n-2)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
x = 0
|
|
267
|
+
while x < 9
|
|
268
|
+
print fib(x)
|
|
269
|
+
x = x + 1
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
"
|
|
273
|
+
assert_equal(["1.0", "1.0", "2.0", "3.0", "5.0", "8.0", "13.0", "21.0", "34.0"].join("\n"), @driver.run(program))
|
|
274
|
+
end
|
|
275
|
+
# lipi:recursive_fib
|
|
276
|
+
end
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/chittagong_grammar'
|
|
2
|
+
|
|
3
|
+
class ChittagongEvaluator < Dhaka::Evaluator
|
|
4
|
+
|
|
5
|
+
self.grammar = ChittagongGrammar
|
|
6
|
+
|
|
7
|
+
define_evaluation_rules do
|
|
8
|
+
|
|
9
|
+
# No-ops
|
|
10
|
+
['no_terms', 'multiple_terms', 'single_term', 'some_terms'].each {|production_name| eval("for_#{production_name} do end")}
|
|
11
|
+
|
|
12
|
+
for_program do
|
|
13
|
+
evaluate(child_nodes[1])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
for_multiple_main_body_statements do
|
|
17
|
+
first = evaluate(child_nodes[0])
|
|
18
|
+
return first if first.exception
|
|
19
|
+
evaluate(child_nodes[2])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
for_multiple_function_body_statements do
|
|
23
|
+
first = evaluate(child_nodes[0])
|
|
24
|
+
return first if (first.exception || first.result)
|
|
25
|
+
evaluate(child_nodes[2])
|
|
26
|
+
end
|
|
27
|
+
# lipi:function_defs
|
|
28
|
+
for_function_definition do
|
|
29
|
+
function_name = evaluate(child_nodes[1])
|
|
30
|
+
arg_declarations = evaluate(child_nodes[3])
|
|
31
|
+
body = child_nodes[6]
|
|
32
|
+
@function_table[function_name] = Function.new(arg_declarations, body)
|
|
33
|
+
ChittagongSuccessResult.new(nil)
|
|
34
|
+
end
|
|
35
|
+
# lipi:function_defs
|
|
36
|
+
|
|
37
|
+
for_main_body_if_statement do
|
|
38
|
+
checked_if_statement
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
for_function_body_if_statement do
|
|
42
|
+
checked_if_statement
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def checked_if_statement
|
|
46
|
+
condition_eval = evaluate(child_nodes[1])
|
|
47
|
+
return condition_eval if condition_eval.exception
|
|
48
|
+
return evaluate(child_nodes[3]) if condition_eval.result
|
|
49
|
+
ChittagongSuccessResult.new(nil)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
for_main_body_if_else_statement do
|
|
53
|
+
checked_if_else_statement
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
for_function_body_if_else_statement do
|
|
57
|
+
checked_if_else_statement
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def checked_if_else_statement
|
|
61
|
+
condition_eval = evaluate(child_nodes[1])
|
|
62
|
+
return condition_eval if condition_eval.exception
|
|
63
|
+
if condition_eval.result
|
|
64
|
+
evaluate(child_nodes[3])
|
|
65
|
+
else
|
|
66
|
+
evaluate(child_nodes[7])
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
for_main_body_while_statement do
|
|
71
|
+
checked_while_statement
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
for_function_body_while_statement do
|
|
75
|
+
checked_while_statement
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def checked_while_statement
|
|
79
|
+
loop do
|
|
80
|
+
condition_eval = evaluate(child_nodes[1])
|
|
81
|
+
return condition_eval if condition_eval.exception
|
|
82
|
+
break unless condition_eval.result
|
|
83
|
+
body_eval = evaluate(child_nodes[3])
|
|
84
|
+
return body_eval if (body_eval.exception || body_eval.result)
|
|
85
|
+
end
|
|
86
|
+
ChittagongSuccessResult.new(nil)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
for_assignment_statement do
|
|
90
|
+
rhs = evaluate(child_nodes[2])
|
|
91
|
+
return rhs if rhs.exception
|
|
92
|
+
@stack[-1][evaluate(child_nodes[0])] = rhs.result
|
|
93
|
+
ChittagongSuccessResult.new(nil)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
for_print_statement do
|
|
97
|
+
rhs = evaluate(child_nodes[1])
|
|
98
|
+
return rhs if rhs.exception
|
|
99
|
+
@output_stream << rhs.result.to_s
|
|
100
|
+
ChittagongSuccessResult.new(nil)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
for_function_call_statement do
|
|
104
|
+
checked_function_call
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
for_function_call_expression do
|
|
108
|
+
checked_function_call
|
|
109
|
+
end
|
|
110
|
+
# lipi:checked_function_call
|
|
111
|
+
def checked_function_call
|
|
112
|
+
function_name = evaluate(child_nodes[0])
|
|
113
|
+
return ChittagongExceptionResult.new("Undefined function #{function_name}",
|
|
114
|
+
child_nodes[0]) unless @function_table.has_key?(function_name)
|
|
115
|
+
|
|
116
|
+
arg_values = evaluate(child_nodes[2])
|
|
117
|
+
return arg_values if arg_values.exception
|
|
118
|
+
|
|
119
|
+
function = @function_table[function_name]
|
|
120
|
+
return ChittagongExceptionResult.new(
|
|
121
|
+
"Wrong number of arguments", child_nodes[1]
|
|
122
|
+
) unless function.args.size == arg_values.result.size
|
|
123
|
+
new_frame = {}
|
|
124
|
+
|
|
125
|
+
function.args.zip(arg_values.result).each do |arg_name, arg_value|
|
|
126
|
+
new_frame[arg_name] = arg_value
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
@stack << new_frame
|
|
130
|
+
result = evaluate(function.body)
|
|
131
|
+
@stack.pop
|
|
132
|
+
|
|
133
|
+
result
|
|
134
|
+
end
|
|
135
|
+
# lipi:checked_function_call
|
|
136
|
+
|
|
137
|
+
for_return_statement do
|
|
138
|
+
checked_unary_operation(child_nodes[1]){|x| x}
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
for_single_arg_declaration do
|
|
142
|
+
[evaluate(child_nodes[0])]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
for_no_arg_decl do
|
|
146
|
+
[]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
for_multiple_arg_declarations do
|
|
150
|
+
evaluate(child_nodes[0]) + [evaluate(child_nodes[2])]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
for_no_args do
|
|
154
|
+
ChittagongSuccessResult.new([])
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
for_single_arg do
|
|
158
|
+
checked_unary_operation(child_nodes[0]) {|x| [x]}
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
for_multiple_args do
|
|
162
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]) {|a, b| a + [b]}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
for_variable_reference do
|
|
166
|
+
variable_name = evaluate(child_nodes[0])
|
|
167
|
+
return ChittagongExceptionResult.new("Undefined variable #{variable_name}", child_nodes[0]) unless @stack[-1].has_key? variable_name
|
|
168
|
+
ChittagongSuccessResult.new(@stack[-1][variable_name])
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
for_subtraction do
|
|
172
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a - b}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
for_addition do
|
|
176
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a + b}
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
for_division do
|
|
180
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a.to_f / b}
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
for_multiplication do
|
|
184
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a * b}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
for_power do
|
|
188
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a ** b}
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
for_less_than_comparison do
|
|
192
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a < b}
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
for_greater_than_comparison do
|
|
196
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a > b}
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
for_equality_comparison do
|
|
200
|
+
checked_binary_operation(child_nodes[0], child_nodes[2]){|a, b| a == b}
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def checked_binary_operation node1, node2
|
|
204
|
+
node1_eval = evaluate(node1)
|
|
205
|
+
node2_eval = evaluate(node2)
|
|
206
|
+
return node1_eval if node1_eval.exception
|
|
207
|
+
return node2_eval if node2_eval.exception
|
|
208
|
+
ChittagongSuccessResult.new(yield(node1_eval.result, node2_eval.result))
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
for_negated_expression do
|
|
212
|
+
checked_unary_operation(child_nodes[1]){|x| -x}
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
for_negation do
|
|
216
|
+
checked_unary_operation(child_nodes[1]){|b| !b}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
for_parenthetized_expression do
|
|
220
|
+
checked_unary_operation(child_nodes[1]){|x| x}
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def checked_unary_operation node
|
|
224
|
+
node_eval = evaluate(node)
|
|
225
|
+
return node_eval if node_eval.exception
|
|
226
|
+
ChittagongSuccessResult.new(yield(node_eval.result))
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
for_function_name do
|
|
230
|
+
token_value
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
for_variable_name do
|
|
234
|
+
token_value
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
for_arg_declaration do
|
|
238
|
+
token_value
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
for_literal do
|
|
242
|
+
ChittagongSuccessResult.new(token_value.to_f)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def token_value
|
|
246
|
+
child_nodes.first.token.value
|
|
247
|
+
end
|
|
248
|
+
# lipi:initialize
|
|
249
|
+
def initialize(stack, output_stream)
|
|
250
|
+
@stack = stack
|
|
251
|
+
@function_table = {}
|
|
252
|
+
@output_stream = output_stream
|
|
253
|
+
end
|
|
254
|
+
# lipi:initialize
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
class ChittagongResult
|
|
260
|
+
attr_reader :exception
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
class ChittagongSuccessResult < ChittagongResult
|
|
264
|
+
attr_reader :result
|
|
265
|
+
def initialize(result)
|
|
266
|
+
@result = result
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
class ChittagongExceptionResult < ChittagongResult
|
|
271
|
+
attr_reader :node
|
|
272
|
+
def initialize(exception, node)
|
|
273
|
+
@exception = exception
|
|
274
|
+
@node = node
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
class Function
|
|
279
|
+
attr_reader :args, :body
|
|
280
|
+
def initialize(args, body)
|
|
281
|
+
@args = args
|
|
282
|
+
@body = body
|
|
283
|
+
end
|
|
284
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + "/chittagong_evaluator"
|
|
3
|
+
begin
|
|
4
|
+
require File.dirname(__FILE__) + "/chittagong_parser"
|
|
5
|
+
rescue LoadError
|
|
6
|
+
puts "Please run the rake command in the root folder to generate the lexer and parser required for this test."
|
|
7
|
+
exit
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class TestChittagongEvaluator < Test::Unit::TestCase
|
|
11
|
+
def test_evaluates_a_simple_program
|
|
12
|
+
token_stream = build_tokens(
|
|
13
|
+
['newline'],
|
|
14
|
+
['word_literal', 'x'], ['='], ['numeric_literal', 23], ['newline'],
|
|
15
|
+
['print'], ['word_literal', 'x'], ['newline'],
|
|
16
|
+
['newline'],
|
|
17
|
+
['word_literal', 'y'], ['='], ['word_literal', 'x'], ['+'], ['word_literal', 'x'], ['newline'],
|
|
18
|
+
['print'], ['word_literal', 'y'], ['*'], ['word_literal', 'x'], ['newline'],
|
|
19
|
+
['if'], ['word_literal', 'x'], ['>'], ['word_literal', 'y'], ['newline'],
|
|
20
|
+
['print'], ['word_literal', 'x'], ['newline'],
|
|
21
|
+
['else'], ['newline'],
|
|
22
|
+
['print'], ['word_literal', 'y'], ['newline'],
|
|
23
|
+
['end'], ['newline'],
|
|
24
|
+
['newline'],
|
|
25
|
+
[Dhaka::END_SYMBOL_NAME]
|
|
26
|
+
)
|
|
27
|
+
stack = [{}]
|
|
28
|
+
output_stream = []
|
|
29
|
+
ChittagongEvaluator.new(stack, output_stream).evaluate(ChittagongParser.parse(token_stream))
|
|
30
|
+
assert_equal(23, stack[0]['x'])
|
|
31
|
+
assert_equal(46, stack[0]['y'])
|
|
32
|
+
assert_equal(["23.0", "1058.0", "46.0"], output_stream)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def build_tokens *tokens
|
|
36
|
+
tokens.collect {|token| Dhaka::Token.new(token[0], token[1], nil)}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
class ChittagongGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
precedences do
|
|
4
|
+
nonassoc %w| == |
|
|
5
|
+
nonassoc %w| < > |
|
|
6
|
+
left %w| + - |
|
|
7
|
+
left %w| * / |
|
|
8
|
+
nonassoc %w| ^ |
|
|
9
|
+
nonassoc %w| ! |
|
|
10
|
+
end
|
|
11
|
+
# lipi:grammar_overview
|
|
12
|
+
|
|
13
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
14
|
+
program %w| opt_terms main_body opt_terms |
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
for_symbol('main_body') do
|
|
18
|
+
single_main_body_statement %w| main_body_statement |
|
|
19
|
+
multiple_main_body_statements %w| main_body terms main_body_statement |
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
for_symbol('main_body_statement') do
|
|
23
|
+
main_body_simple_statement %w| simple_statement |
|
|
24
|
+
function_definition %w| def function_name ( arg_declarations ) terms
|
|
25
|
+
function_body terms end |
|
|
26
|
+
main_body_if_statement %w| if expression terms main_body terms end |
|
|
27
|
+
main_body_if_else_statement %w| if expression terms main_body terms else terms main_body
|
|
28
|
+
terms end |
|
|
29
|
+
main_body_while_statement %w| while expression terms main_body terms end |
|
|
30
|
+
end
|
|
31
|
+
# lipi:grammar_overview
|
|
32
|
+
|
|
33
|
+
for_symbol('simple_statement') do
|
|
34
|
+
assignment_statement %w| var_name = expression |
|
|
35
|
+
print_statement %w| print expression |
|
|
36
|
+
function_call_statement %w| function_name ( arg_list ) |
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
for_symbol('function_body') do
|
|
40
|
+
single_function_body_statement %w| function_body_statement |
|
|
41
|
+
multiple_function_body_statements %w| function_body terms function_body_statement |
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
for_symbol('function_body_statement') do
|
|
45
|
+
function_body_simple_statement %w| simple_statement |
|
|
46
|
+
return_statement %w| return expression |
|
|
47
|
+
function_body_if_statement %w| if expression terms function_body terms end |
|
|
48
|
+
function_body_if_else_statement %w| if expression terms function_body terms else terms function_body terms end |
|
|
49
|
+
function_body_while_statement %w| while expression terms function_body terms end |
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
for_symbol('function_name') do
|
|
53
|
+
function_name %w| word_literal |
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
for_symbol('var_name') do
|
|
57
|
+
variable_name %w| word_literal |
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
for_symbol('arg_declarations') do
|
|
61
|
+
no_arg_decl %w| |
|
|
62
|
+
single_arg_declaration %w| arg_decl |
|
|
63
|
+
multiple_arg_declarations %w| arg_declarations , arg_decl |
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
for_symbol('arg_decl') do
|
|
67
|
+
arg_declaration %w| word_literal |
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
for_symbol('arg_list') do
|
|
71
|
+
no_args %w| |
|
|
72
|
+
single_arg %w| expression |
|
|
73
|
+
multiple_args %w| arg_list , expression |
|
|
74
|
+
end
|
|
75
|
+
# lipi:expressions
|
|
76
|
+
for_symbol('expression') do
|
|
77
|
+
negation %w| ! expression |
|
|
78
|
+
equality_comparison %w| expression == expression |
|
|
79
|
+
greater_than_comparison %w| expression > expression |
|
|
80
|
+
less_than_comparison %w| expression < expression |
|
|
81
|
+
addition %w| expression + expression |
|
|
82
|
+
subtraction %w| expression - expression |
|
|
83
|
+
multiplication %w| expression * expression |
|
|
84
|
+
division %w| expression / expression |
|
|
85
|
+
power %w| expression ^ expression |
|
|
86
|
+
literal %w| numeric_literal |
|
|
87
|
+
function_call_expression %w| function_name ( arg_list ) |
|
|
88
|
+
variable_reference %w| var_name |
|
|
89
|
+
parenthetized_expression %w| ( expression ) |
|
|
90
|
+
negated_expression %w| - expression |, :prec => '*'
|
|
91
|
+
end
|
|
92
|
+
# lipi:expressions
|
|
93
|
+
|
|
94
|
+
for_symbol('terms') do
|
|
95
|
+
single_term %w| newline |
|
|
96
|
+
multiple_terms %w| terms newline |
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
for_symbol('opt_terms') do
|
|
100
|
+
some_terms %w| terms |
|
|
101
|
+
no_terms %w| |
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|