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,139 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestLexer < Test::Unit::TestCase
|
|
4
|
+
class LexerSpec < Dhaka::LexerSpecification
|
|
5
|
+
|
|
6
|
+
for_pattern 'zz' do
|
|
7
|
+
"two zs"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
for_pattern '\w(\w|\d)*' do
|
|
11
|
+
"word #{current_lexeme.value}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# can optionally use Regexps as well
|
|
15
|
+
for_pattern(/(\d)*(\.\d+)?/) do
|
|
16
|
+
"number #{current_lexeme.value}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
for_pattern '<.*>' do
|
|
20
|
+
"tag #{current_lexeme.value}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
for_pattern ' +' do
|
|
24
|
+
#ignores whitespace
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
for_pattern "\n+" do
|
|
28
|
+
"newline"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
for_pattern "\r+" do
|
|
32
|
+
"carriage return"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_lexer_with_valid_input
|
|
38
|
+
lexer = Dhaka::Lexer.new(LexerSpec)
|
|
39
|
+
eval(lexer.compile_to_ruby_source_as(:SomeLexer))
|
|
40
|
+
input = "these are words a z zz caPITALIZED word \r
|
|
41
|
+
this is a float 12.00 an integer 134 a float without a leading digit .2335 another word1"
|
|
42
|
+
results = SomeLexer.lex(input).collect
|
|
43
|
+
assert_equal(
|
|
44
|
+
["word these",
|
|
45
|
+
"word are",
|
|
46
|
+
"word words",
|
|
47
|
+
"word a",
|
|
48
|
+
"word z",
|
|
49
|
+
"two zs",
|
|
50
|
+
"word caPITALIZED",
|
|
51
|
+
"word word",
|
|
52
|
+
"carriage return",
|
|
53
|
+
"newline",
|
|
54
|
+
"word this",
|
|
55
|
+
"word is",
|
|
56
|
+
"word a",
|
|
57
|
+
"word float",
|
|
58
|
+
"number 12.00",
|
|
59
|
+
"word an",
|
|
60
|
+
"word integer",
|
|
61
|
+
"number 134",
|
|
62
|
+
"word a",
|
|
63
|
+
"word float",
|
|
64
|
+
"word without",
|
|
65
|
+
"word a",
|
|
66
|
+
"word leading",
|
|
67
|
+
"word digit",
|
|
68
|
+
"number .2335",
|
|
69
|
+
"word another",
|
|
70
|
+
"word word1"], results[0..-2])
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_lexer_with_invalid_input
|
|
74
|
+
lexer = Dhaka::Lexer.new(LexerSpec)
|
|
75
|
+
result = lexer.lex("this will cause an error here 123.").each do |result|
|
|
76
|
+
end
|
|
77
|
+
assert(result.has_error?)
|
|
78
|
+
assert_equal(34, result.unexpected_char_index)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_lexer_with_greedy_character_consumption
|
|
82
|
+
lexer = Dhaka::Lexer.new(LexerSpec)
|
|
83
|
+
results = lexer.lex("<html></html>this is a word").collect
|
|
84
|
+
assert_equal(["tag <html></html>",
|
|
85
|
+
"word this",
|
|
86
|
+
"word is",
|
|
87
|
+
"word a",
|
|
88
|
+
"word word"], results[0..-2])
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class LexerWithLookaheadsSpec < Dhaka::LexerSpecification
|
|
92
|
+
|
|
93
|
+
for_pattern '\s+' do
|
|
94
|
+
# ignore whitespace
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
for_pattern ':/\w+' do
|
|
98
|
+
"a symbol qualifier"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
for_pattern(":/[^a-zA-Z \n\r\t]*") do
|
|
102
|
+
"a colon"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
for_pattern "ab/cd" do
|
|
106
|
+
"ab followed by cd: #{current_lexeme.value}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
for_pattern "abc/e" do
|
|
110
|
+
"abc followed by e: #{current_lexeme.value}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
for_pattern '\w+' do
|
|
114
|
+
"word #{current_lexeme.value}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
for_pattern '\d+' do
|
|
118
|
+
"number #{current_lexeme.value}"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_lexer_with_regexes_that_use_lookaheads
|
|
124
|
+
lexer = Dhaka::Lexer.new(LexerWithLookaheadsSpec)
|
|
125
|
+
eval(lexer.compile_to_ruby_source_as(:LexerWithTrickyLookaheads))
|
|
126
|
+
results = LexerWithTrickyLookaheads.lex("234 : :whatever :1934 abcd ::").collect
|
|
127
|
+
assert_equal(["number 234",
|
|
128
|
+
"a colon",
|
|
129
|
+
"a symbol qualifier",
|
|
130
|
+
"word whatever",
|
|
131
|
+
"a colon",
|
|
132
|
+
"number 1934",
|
|
133
|
+
"ab followed by cd: ab",
|
|
134
|
+
"word cd",
|
|
135
|
+
"a colon",
|
|
136
|
+
"a colon"], results[0..-2])
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + "/malformed_grammar"
|
|
3
|
+
|
|
4
|
+
class TestMalformedGrammar < Test::Unit::TestCase
|
|
5
|
+
def test_must_have_a_start_symbol_in_order_to_generate_a_parser
|
|
6
|
+
assert_raises(Dhaka::NoStartProductionsError) {Dhaka::Parser.new(MalformedGrammar)}
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class NullableGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
4
|
+
tuple %w| Tuple |
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
for_symbol('Tuple') do
|
|
8
|
+
element_list %w| ( Elements ) |
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
for_symbol('Elements') do
|
|
12
|
+
empty_element_list %w| |
|
|
13
|
+
concatenate_element_lists %w| Character Elements |
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
for_symbol('Character') do
|
|
17
|
+
literal_a %w| a |
|
|
18
|
+
literal_b %w| b |
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + '/simple_grammar'
|
|
3
|
+
|
|
4
|
+
class TestParseSuccessResult < Test::Unit::TestCase
|
|
5
|
+
include Dhaka
|
|
6
|
+
|
|
7
|
+
def composite_node(production, child_nodes, dot_name)
|
|
8
|
+
node = ParseTreeCompositeNode.new(SimpleGrammar.production_named(production))
|
|
9
|
+
node.child_nodes.concat child_nodes
|
|
10
|
+
node.stubs(:object_id).returns(dot_name)
|
|
11
|
+
node
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def leaf_node(token, value, dot_name)
|
|
15
|
+
node = ParseTreeLeafNode.new(Token.new(token, value, nil))
|
|
16
|
+
node.stubs(:object_id).returns(dot_name)
|
|
17
|
+
node
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_parse_tree_can_be_exported_to_dot_format
|
|
21
|
+
first_term = composite_node('literal', [leaf_node('n', 1, "literal_1")], "first_term")
|
|
22
|
+
second_term = composite_node('literal', [leaf_node('n', 2, "literal_2")], "second_term")
|
|
23
|
+
addition_term = leaf_node('-', nil, "subtraction_operator")
|
|
24
|
+
tree = composite_node('subtraction', [first_term, addition_term, second_term], "expression")
|
|
25
|
+
result = ParseSuccessResult.new(tree)
|
|
26
|
+
assert_equal(
|
|
27
|
+
%(digraph x {
|
|
28
|
+
node [fontsize="10" shape="box" size="5"]
|
|
29
|
+
expression [label="subtraction E ::= E - T"]
|
|
30
|
+
expression -> first_term
|
|
31
|
+
first_term [label="literal T ::= n"]
|
|
32
|
+
first_term -> literal_1
|
|
33
|
+
literal_1 [label="n : 1"]
|
|
34
|
+
expression -> subtraction_operator
|
|
35
|
+
subtraction_operator [label="-"]
|
|
36
|
+
expression -> second_term
|
|
37
|
+
second_term [label="literal T ::= n"]
|
|
38
|
+
second_term -> literal_2
|
|
39
|
+
literal_2 [label="n : 2"]
|
|
40
|
+
}),
|
|
41
|
+
result.to_dot)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestParserState < Test::Unit::TestCase
|
|
4
|
+
include Dhaka
|
|
5
|
+
def test_unique_identifier
|
|
6
|
+
states = (0...5).collect {|i| ParserState.new(nil, {})}
|
|
7
|
+
ids = Set.new
|
|
8
|
+
states.each do |state|
|
|
9
|
+
assert(/^State(\d+)$/ =~ state.unique_name)
|
|
10
|
+
ids << $1.to_i
|
|
11
|
+
end
|
|
12
|
+
assert_equal(5, ids.size)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_to_s_method
|
|
16
|
+
options = {:some_option => true}
|
|
17
|
+
item1 = mock()
|
|
18
|
+
item1.stubs(:to_s).with(options).returns("i'm item 1")
|
|
19
|
+
item2 = mock()
|
|
20
|
+
item2.stubs(:to_s).with(options).returns("i'm item 2")
|
|
21
|
+
state = ParserState.new(nil, {item1 => item1, item2 => item2})
|
|
22
|
+
assert_equal(["i'm item 1", "i'm item 2"], state.to_s(options).split("\n").sort)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + '/simple_grammar'
|
|
3
|
+
require File.dirname(__FILE__) + '/nullable_grammar'
|
|
4
|
+
require File.dirname(__FILE__) + '/lalr_but_not_slr_grammar'
|
|
5
|
+
require File.dirname(__FILE__) + '/another_lalr_but_not_slr_grammar'
|
|
6
|
+
require File.dirname(__FILE__) + '/rr_conflict_grammar'
|
|
7
|
+
require File.dirname(__FILE__) + '/sr_conflict_grammar'
|
|
8
|
+
|
|
9
|
+
class ParserTest < Test::Unit::TestCase
|
|
10
|
+
def build_tokens(token_symbol_names)
|
|
11
|
+
token_symbol_names.collect {|symbol_name| Dhaka::Token.new(symbol_name, nil, nil)}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def setup
|
|
15
|
+
@grammar = SimpleGrammar
|
|
16
|
+
@parser = Dhaka::Parser.new(@grammar)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def contains(given_member, set)
|
|
20
|
+
set.inject(false) {|result, member| result ||= (Set.new(member) == Set.new(given_member))}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def assert_collection_equal(expected, actual)
|
|
24
|
+
assert_equal(expected.size, actual.size)
|
|
25
|
+
actual.each do |actual_member|
|
|
26
|
+
assert(contains(actual_member, expected), "Should have found #{actual_member} in expected set.")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_parser_generates_states_with_correct_items
|
|
31
|
+
expected_states = [
|
|
32
|
+
['_Start_ ::= -> S # [_End_]',
|
|
33
|
+
'S ::= -> E [#]',
|
|
34
|
+
'E ::= -> E - T [#-]',
|
|
35
|
+
'E ::= -> T [#-]',
|
|
36
|
+
'T ::= -> n [#-]',
|
|
37
|
+
'T ::= -> ( E ) [#-]'],
|
|
38
|
+
['E ::= T -> [#)-]'],
|
|
39
|
+
['T ::= n -> [#)-]'],
|
|
40
|
+
['S ::= E -> [#]',
|
|
41
|
+
'E ::= E -> - T [#-]'],
|
|
42
|
+
['_Start_ ::= S -> # [_End_]'],
|
|
43
|
+
['T ::= ( -> E ) [#)-]',
|
|
44
|
+
'E ::= -> E - T [)-]',
|
|
45
|
+
'E ::= -> T [)-]',
|
|
46
|
+
'T ::= -> n [)-]',
|
|
47
|
+
'T ::= -> ( E ) [)-]'],
|
|
48
|
+
['E ::= E - -> T [#)-]',
|
|
49
|
+
'T ::= -> n [#)-]',
|
|
50
|
+
'T ::= -> ( E ) [#)-]'],
|
|
51
|
+
['E ::= E - T -> [#)-]'],
|
|
52
|
+
['T ::= ( E -> ) [#)-]',
|
|
53
|
+
'E ::= E -> - T [)-]'],
|
|
54
|
+
['T ::= ( E ) -> [#)-]'],
|
|
55
|
+
['_Start_ ::= S # -> [_End_]']]
|
|
56
|
+
actual_states = @parser.send('states').collect {|state| state.items.values.collect {|item| item.to_s}}
|
|
57
|
+
assert_collection_equal(expected_states, actual_states)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_parser_can_be_exported_to_dot_format
|
|
61
|
+
dot_representation = @parser.to_dot
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_parser_generates_parse_tree_given_a_stream_of_symbols
|
|
65
|
+
parse_tree = @parser.parse(build_tokens(['(','n','-','(','n','-','n',')',')','-','n','#', Dhaka::END_SYMBOL_NAME]))
|
|
66
|
+
assert_equal \
|
|
67
|
+
["literal",
|
|
68
|
+
"term",
|
|
69
|
+
"literal",
|
|
70
|
+
"term",
|
|
71
|
+
"literal",
|
|
72
|
+
"subtraction",
|
|
73
|
+
"parenthetized_expression",
|
|
74
|
+
"subtraction",
|
|
75
|
+
"parenthetized_expression",
|
|
76
|
+
"term",
|
|
77
|
+
"literal",
|
|
78
|
+
"subtraction",
|
|
79
|
+
"expression",
|
|
80
|
+
"start"], parse_tree.linearize.collect {|node| node.production.name}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def get_linearized_parse_result(input, parser)
|
|
84
|
+
parser.parse(build_tokens(input)).parse_tree.linearize.collect {|node| node.production.name}
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_with_a_grammar_with_nullables_after_terminals
|
|
88
|
+
grammar = NullableGrammar
|
|
89
|
+
parser = Dhaka::Parser.new(grammar)
|
|
90
|
+
parser_input = ['(','a',')', Dhaka::END_SYMBOL_NAME]
|
|
91
|
+
assert_equal \
|
|
92
|
+
["literal_a",
|
|
93
|
+
"empty_element_list",
|
|
94
|
+
"concatenate_element_lists",
|
|
95
|
+
"element_list",
|
|
96
|
+
"tuple"], get_linearized_parse_result(parser_input, parser)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_with_a_grammar_that_is_not_SLR
|
|
100
|
+
grammar = LALRButNotSLRGrammar
|
|
101
|
+
parser = Dhaka::Parser.new(grammar)
|
|
102
|
+
parser_input = ['b','d','c', Dhaka::END_SYMBOL_NAME]
|
|
103
|
+
assert_equal(["A_d", "E_bAc", "start"], get_linearized_parse_result(parser_input, parser))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_with_another_grammar_that_is_not_SLR
|
|
107
|
+
grammar = AnotherLALRButNotSLRGrammar
|
|
108
|
+
parser = Dhaka::Parser.new(grammar)
|
|
109
|
+
parser_input = ['*', 'id', '=', 'id', Dhaka::END_SYMBOL_NAME]
|
|
110
|
+
assert_equal(["identifier", "l_value", "contents", "identifier", "l_value", "assignment"], get_linearized_parse_result(parser_input, parser))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_debug_output_with_a_grammar_that_should_generate_an_RR_conflict
|
|
114
|
+
fake_logger = FakeLogger.new
|
|
115
|
+
Dhaka::ParserState.any_instance.stubs(:unique_name).returns("StateXXX")
|
|
116
|
+
parser = Dhaka::Parser.new(RRConflictGrammar, fake_logger)
|
|
117
|
+
num_states = parser.send(:states).size
|
|
118
|
+
assert_equal(['Created StateXXX.'] * num_states, fake_logger.debugs[0...num_states])
|
|
119
|
+
assert_equal(1, fake_logger.errors.size)
|
|
120
|
+
assert(fake_logger.errors.first.match(/^Parser Conflict at State:\n(.+)\n(.+)\nExisting: (.+)\nNew: (.+)\nLookahead: (.+)$/))
|
|
121
|
+
assert_equal(["A ::= x y ->", "B ::= x y ->", "Reduce with xy A ::= x y", "Reduce with xy_again B ::= x y", "c"],
|
|
122
|
+
$~[1..5].sort)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def write_parser(parser)
|
|
126
|
+
File.open('parser.dot', 'w') do |file|
|
|
127
|
+
file << parser.to_dot
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class PrecedenceGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
precedences do
|
|
4
|
+
left %w| * |
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
8
|
+
expression %w| E * F |
|
|
9
|
+
whatever %w| E F |, :prec => '*'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
for_symbol('F') do
|
|
13
|
+
something %w| foo |
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../dhaka_test_helper'
|
|
2
|
+
require File.dirname(__FILE__) + "/precedence_grammar"
|
|
3
|
+
|
|
4
|
+
class TestPrecedenceGrammar < Test::Unit::TestCase
|
|
5
|
+
def test_precedences_are_computed_correctly
|
|
6
|
+
assert_equal(:left, PrecedenceGrammar.production_named('expression').precedence.associativity)
|
|
7
|
+
assert_equal(:left, PrecedenceGrammar.production_named('whatever').precedence.associativity)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class RRConflictGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
4
|
+
start %w| S |
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
for_symbol('S') do
|
|
8
|
+
a_expansion %w| A c d |
|
|
9
|
+
b_expansion %w| B c e |
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
for_symbol('A') do
|
|
13
|
+
xy %w| x y |
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
for_symbol('B') do
|
|
17
|
+
xy_again %w| x y |
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class SimpleGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
4
|
+
start %w| S # |
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
for_symbol('S') do
|
|
8
|
+
expression %w| E |
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
for_symbol('E') do
|
|
12
|
+
subtraction %w| E - T |
|
|
13
|
+
term %w| T |
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
for_symbol('T') do
|
|
17
|
+
literal %w| n |
|
|
18
|
+
parenthetized_expression %w| ( E ) |
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class SRConflictGrammar < Dhaka::Grammar
|
|
2
|
+
|
|
3
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
|
4
|
+
statement %w| statement |
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
for_symbol('statement') do
|
|
8
|
+
if_statement %w| if_statement |
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
for_symbol('if_statement') do
|
|
12
|
+
if_then_statement %w| IF expr THEN statement |
|
|
13
|
+
if_then_else_statement %w| IF expr THEN statement ELSE statement END |
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
unless defined? Dhaka
|
|
2
|
+
require File.dirname(__FILE__) + '/../lib/dhaka'
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
require File.dirname(__FILE__) + '/fake_logger'
|
|
6
|
+
|
|
7
|
+
require 'test/unit'
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
require 'mocha'
|
|
11
|
+
rescue LoadError
|
|
12
|
+
puts "
|
|
13
|
+
The tests depend on Mocha. Please install it if you wish to run them:
|
|
14
|
+
sudo gem install mocha
|
|
15
|
+
This gem is not required for using the library."
|
|
16
|
+
exit
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class FakeLogger
|
|
2
|
+
attr_reader :warnings, :debugs, :errors
|
|
3
|
+
def initialize
|
|
4
|
+
@warnings = []
|
|
5
|
+
@debugs = []
|
|
6
|
+
@errors = []
|
|
7
|
+
end
|
|
8
|
+
def debug message
|
|
9
|
+
@debugs << message
|
|
10
|
+
end
|
|
11
|
+
def error message
|
|
12
|
+
@errors << message
|
|
13
|
+
end
|
|
14
|
+
def warn message
|
|
15
|
+
@warnings << message
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
require 'simplerdb/query_language'
|
|
3
|
+
|
|
4
|
+
module SimplerDB
|
|
5
|
+
|
|
6
|
+
class Domain
|
|
7
|
+
attr_accessor :name, :items
|
|
8
|
+
|
|
9
|
+
def initialize(name)
|
|
10
|
+
@name = name
|
|
11
|
+
@items = Hash.new { |hash, key| hash[key] = Item.new(key) }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class Item
|
|
16
|
+
attr_accessor :name, :attributes
|
|
17
|
+
|
|
18
|
+
def initialize(name)
|
|
19
|
+
@name = name
|
|
20
|
+
@attributes = Hash.new { |hash, key| hash[key] = [] }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def put_attribute(attr, replace = false)
|
|
24
|
+
@attributes[attr.name].clear if replace
|
|
25
|
+
@attributes[attr.name] << attr
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete_attribute(attr)
|
|
29
|
+
if attr.value.nil?
|
|
30
|
+
@attributes[attr.name].clear
|
|
31
|
+
else
|
|
32
|
+
@attributes[attr.name].delete(attr)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if @attributes[attr.name].size == 0
|
|
36
|
+
@attributes.delete(attr.name)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_attributes(attribute_name = nil)
|
|
41
|
+
attrs = []
|
|
42
|
+
|
|
43
|
+
@attributes.each do |key, value|
|
|
44
|
+
if (attribute_name.nil? || attribute_name == key)
|
|
45
|
+
attrs += value
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
return attrs
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Attribute
|
|
54
|
+
attr_accessor :name, :value
|
|
55
|
+
|
|
56
|
+
def initialize(name, value)
|
|
57
|
+
@name = name
|
|
58
|
+
@value = value
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ==(other)
|
|
62
|
+
@name == other.name && @value == other.value
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class AttributeParam < Attribute
|
|
67
|
+
attr_accessor :replace
|
|
68
|
+
|
|
69
|
+
def initialize(name, value, replace = false)
|
|
70
|
+
super(name, value)
|
|
71
|
+
@replace = replace
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_attr
|
|
75
|
+
Attribute.new(self.name, self.value)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The main SimplerDB class, containing methods that correspond to the
|
|
80
|
+
# AWS API.
|
|
81
|
+
class DB
|
|
82
|
+
include Singleton
|
|
83
|
+
|
|
84
|
+
def initialize
|
|
85
|
+
reset
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# For testing
|
|
89
|
+
def reset
|
|
90
|
+
@domains = {}
|
|
91
|
+
@query_executor = QueryExecutor.new
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def create_domain(name)
|
|
95
|
+
@domains[name] ||= Domain.new(name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def delete_domain(name)
|
|
99
|
+
@domains.delete(name)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def list_domains(max = 100, token = 0)
|
|
103
|
+
doms = []
|
|
104
|
+
count = 0
|
|
105
|
+
token = 0 unless token
|
|
106
|
+
@domains.keys.each do |domain|
|
|
107
|
+
break if doms.size == max
|
|
108
|
+
doms << domain if count >= token.to_i
|
|
109
|
+
count += 1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if (count >= @domains.size)
|
|
113
|
+
return doms,nil
|
|
114
|
+
else
|
|
115
|
+
return doms,count
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def get_attributes(domain_name, item_name, attribute_name = nil)
|
|
120
|
+
domain = @domains[domain_name]
|
|
121
|
+
item = domain.items[item_name]
|
|
122
|
+
return item.get_attributes(attribute_name)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def put_attributes(domain_name, item_name, attribute_params)
|
|
126
|
+
domain = @domains[domain_name]
|
|
127
|
+
item = domain.items[item_name]
|
|
128
|
+
attribute_params.each { |attr| item.put_attribute(attr.to_attr, attr.replace) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def delete_attributes(domain_name, item_name, attributes)
|
|
132
|
+
domain = @domains[domain_name]
|
|
133
|
+
item = domain.items[item_name]
|
|
134
|
+
if attributes.empty?
|
|
135
|
+
domain.items.delete(item_name)
|
|
136
|
+
else
|
|
137
|
+
attributes.each { |attr| item.delete_attribute(attr) }
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def query(domain, query, max = 100, token = 0)
|
|
142
|
+
@query_executor.do_query(query, @domains[domain], max, token)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|