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.
Files changed (121) hide show
  1. data/lib/simply_stored/class_methods_base.rb +31 -0
  2. data/lib/simply_stored/couch/belongs_to.rb +117 -0
  3. data/lib/simply_stored/couch/ext/couch_potato.rb +16 -0
  4. data/lib/simply_stored/couch/has_many.rb +148 -0
  5. data/lib/simply_stored/couch/has_one.rb +93 -0
  6. data/lib/simply_stored/couch/validations.rb +74 -0
  7. data/lib/simply_stored/couch/views/array_property_view_spec.rb +22 -0
  8. data/lib/simply_stored/couch/views.rb +1 -0
  9. data/lib/simply_stored/couch.rb +278 -0
  10. data/lib/simply_stored/instance_methods.rb +143 -0
  11. data/lib/simply_stored/simpledb/associations.rb +196 -0
  12. data/lib/simply_stored/simpledb/attributes.rb +173 -0
  13. data/lib/simply_stored/simpledb/storag.rb +85 -0
  14. data/lib/simply_stored/simpledb/validations.rb +88 -0
  15. data/lib/simply_stored/simpledb.rb +212 -0
  16. data/lib/simply_stored/storage.rb +93 -0
  17. data/lib/simply_stored.rb +9 -0
  18. data/test/custom_views_test.rb +33 -0
  19. data/test/fixtures/couch.rb +182 -0
  20. data/test/fixtures/simpledb/item.rb +11 -0
  21. data/test/fixtures/simpledb/item_daddy.rb +8 -0
  22. data/test/fixtures/simpledb/log_item.rb +3 -0
  23. data/test/fixtures/simpledb/namespace_bar.rb +5 -0
  24. data/test/fixtures/simpledb/namespace_foo.rb +7 -0
  25. data/test/fixtures/simpledb/protected_item.rb +3 -0
  26. data/test/simply_stored_couch_test.rb +1684 -0
  27. data/test/simply_stored_simpledb_test.rb +1341 -0
  28. data/test/test_helper.rb +22 -0
  29. data/test/vendor/dhaka-2.2.1/lib/dhaka/dot/dot.rb +29 -0
  30. data/test/vendor/dhaka-2.2.1/lib/dhaka/evaluator/evaluator.rb +133 -0
  31. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/closure_hash.rb +15 -0
  32. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar.rb +240 -0
  33. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar_symbol.rb +27 -0
  34. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/precedence.rb +19 -0
  35. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/production.rb +36 -0
  36. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/accept_actions.rb +36 -0
  37. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/alphabet.rb +21 -0
  38. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/compiled_lexer.rb +46 -0
  39. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/dfa.rb +121 -0
  40. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexeme.rb +32 -0
  41. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer.rb +70 -0
  42. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer_run.rb +78 -0
  43. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_grammar.rb +392 -0
  44. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_parser.rb +2010 -0
  45. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_tokenizer.rb +14 -0
  46. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/specification.rb +96 -0
  47. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state.rb +68 -0
  48. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state_machine.rb +37 -0
  49. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/action.rb +55 -0
  50. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/channel.rb +58 -0
  51. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/compiled_parser.rb +51 -0
  52. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/conflict.rb +54 -0
  53. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/item.rb +42 -0
  54. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_result.rb +50 -0
  55. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_tree.rb +66 -0
  56. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser.rb +165 -0
  57. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_methods.rb +11 -0
  58. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_run.rb +39 -0
  59. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_state.rb +74 -0
  60. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/token.rb +22 -0
  61. data/test/vendor/dhaka-2.2.1/lib/dhaka/runtime.rb +51 -0
  62. data/test/vendor/dhaka-2.2.1/lib/dhaka/tokenizer/tokenizer.rb +190 -0
  63. data/test/vendor/dhaka-2.2.1/lib/dhaka.rb +62 -0
  64. data/test/vendor/dhaka-2.2.1/test/all_tests.rb +5 -0
  65. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator.rb +64 -0
  66. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator_test.rb +43 -0
  67. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar.rb +41 -0
  68. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar_test.rb +9 -0
  69. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_test_methods.rb +9 -0
  70. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer.rb +39 -0
  71. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer_test.rb +38 -0
  72. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_evaluator.rb +43 -0
  73. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +24 -0
  74. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar_test.rb +30 -0
  75. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_lexer_specification.rb +23 -0
  76. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +33 -0
  77. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_grammar.rb +23 -0
  78. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_tokenizer.rb +22 -0
  79. data/test/vendor/dhaka-2.2.1/test/brackets/brackets_test.rb +28 -0
  80. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver.rb +46 -0
  81. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver_test.rb +276 -0
  82. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator.rb +284 -0
  83. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator_test.rb +38 -0
  84. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_grammar.rb +104 -0
  85. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer.rb +109 -0
  86. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_specification.rb +37 -0
  87. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_test.rb +58 -0
  88. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser.rb +879 -0
  89. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser_test.rb +55 -0
  90. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_test.rb +170 -0
  91. data/test/vendor/dhaka-2.2.1/test/core/another_lalr_but_not_slr_grammar.rb +20 -0
  92. data/test/vendor/dhaka-2.2.1/test/core/compiled_parser_test.rb +44 -0
  93. data/test/vendor/dhaka-2.2.1/test/core/dfa_test.rb +170 -0
  94. data/test/vendor/dhaka-2.2.1/test/core/evaluator_test.rb +22 -0
  95. data/test/vendor/dhaka-2.2.1/test/core/grammar_test.rb +83 -0
  96. data/test/vendor/dhaka-2.2.1/test/core/lalr_but_not_slr_grammar.rb +19 -0
  97. data/test/vendor/dhaka-2.2.1/test/core/lexer_test.rb +139 -0
  98. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar.rb +7 -0
  99. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar_test.rb +8 -0
  100. data/test/vendor/dhaka-2.2.1/test/core/nullable_grammar.rb +21 -0
  101. data/test/vendor/dhaka-2.2.1/test/core/parse_result_test.rb +44 -0
  102. data/test/vendor/dhaka-2.2.1/test/core/parser_state_test.rb +24 -0
  103. data/test/vendor/dhaka-2.2.1/test/core/parser_test.rb +131 -0
  104. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar.rb +17 -0
  105. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar_test.rb +9 -0
  106. data/test/vendor/dhaka-2.2.1/test/core/rr_conflict_grammar.rb +21 -0
  107. data/test/vendor/dhaka-2.2.1/test/core/simple_grammar.rb +22 -0
  108. data/test/vendor/dhaka-2.2.1/test/core/sr_conflict_grammar.rb +16 -0
  109. data/test/vendor/dhaka-2.2.1/test/dhaka_test_helper.rb +17 -0
  110. data/test/vendor/dhaka-2.2.1/test/fake_logger.rb +17 -0
  111. data/test/vendor/simplerdb-0.2/lib/simplerdb/client_exception.rb +10 -0
  112. data/test/vendor/simplerdb-0.2/lib/simplerdb/db.rb +146 -0
  113. data/test/vendor/simplerdb-0.2/lib/simplerdb/query_language.rb +266 -0
  114. data/test/vendor/simplerdb-0.2/lib/simplerdb/server.rb +33 -0
  115. data/test/vendor/simplerdb-0.2/lib/simplerdb/servlet.rb +191 -0
  116. data/test/vendor/simplerdb-0.2/lib/simplerdb.rb +3 -0
  117. data/test/vendor/simplerdb-0.2/test/functional_test.rb +81 -0
  118. data/test/vendor/simplerdb-0.2/test/query_evaluator_test.rb +73 -0
  119. data/test/vendor/simplerdb-0.2/test/query_parser_test.rb +64 -0
  120. data/test/vendor/simplerdb-0.2/test/simplerdb_test.rb +80 -0
  121. 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