simply_stored 0.3.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/CHANGELOG.md +38 -0
  2. data/README.md +45 -24
  3. data/lib/simply_stored/couch/association_property.rb +27 -0
  4. data/lib/simply_stored/couch/belongs_to.rb +5 -7
  5. data/lib/simply_stored/couch/finders.rb +5 -1
  6. data/lib/simply_stored/couch/has_and_belongs_to_many.rb +202 -0
  7. data/lib/simply_stored/couch/has_many.rb +6 -51
  8. data/lib/simply_stored/couch/has_one.rb +4 -29
  9. data/lib/simply_stored/couch/properties.rb +11 -0
  10. data/lib/simply_stored/couch.rb +38 -2
  11. data/lib/simply_stored/instance_methods.rb +68 -29
  12. data/lib/simply_stored.rb +3 -1
  13. data/test/{couchdb/couch_active_model_compatibility_test.rb → active_model_compatibility_test.rb} +2 -2
  14. data/test/{couchdb/couch_belongs_to_test.rb → belongs_to_test.rb} +13 -3
  15. data/test/{couchdb/couch_conflict_handling_test.rb → conflict_handling_test.rb} +3 -3
  16. data/test/{couchdb/couch_finder_test.rb → finder_test.rb} +8 -3
  17. data/test/fixtures/couch.rb +55 -0
  18. data/test/has_and_belongs_to_many_test.rb +639 -0
  19. data/test/{couchdb/couch_has_many_test.rb → has_many_test.rb} +13 -3
  20. data/test/{couchdb/couch_has_one_test.rb → has_one_test.rb} +13 -3
  21. data/test/{couchdb/couch_instance_lifecycle_test.rb → instance_lifecycle_test.rb} +3 -3
  22. data/test/{couchdb/couch_mass_assignment_protection_test.rb → mass_assignment_protection_test.rb} +3 -3
  23. data/test/{couchdb/couch_s3_test.rb → s3_test.rb} +3 -3
  24. data/test/{couchdb/couch_soft_deletable_test.rb → soft_deletable_test.rb} +3 -3
  25. data/test/test_helper.rb +1 -5
  26. data/test/{couchdb/couch_validations_test.rb → validations_test.rb} +3 -3
  27. data/test/{couchdb/custom_views_test.rb → views_test.rb} +3 -3
  28. metadata +36 -234
  29. data/lib/simply_stored/simpledb/associations.rb +0 -215
  30. data/lib/simply_stored/simpledb/attributes.rb +0 -173
  31. data/lib/simply_stored/simpledb/storag.rb +0 -85
  32. data/lib/simply_stored/simpledb/validations.rb +0 -88
  33. data/lib/simply_stored/simpledb.rb +0 -216
  34. data/test/fixtures/simpledb/item.rb +0 -11
  35. data/test/fixtures/simpledb/item_daddy.rb +0 -8
  36. data/test/fixtures/simpledb/log_item.rb +0 -3
  37. data/test/fixtures/simpledb/namespace_bar.rb +0 -5
  38. data/test/fixtures/simpledb/namespace_foo.rb +0 -7
  39. data/test/fixtures/simpledb/protected_item.rb +0 -3
  40. data/test/simply_stored_simpledb_test.rb +0 -1376
  41. data/test/vendor/dhaka-2.2.1/lib/dhaka/dot/dot.rb +0 -29
  42. data/test/vendor/dhaka-2.2.1/lib/dhaka/evaluator/evaluator.rb +0 -133
  43. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/closure_hash.rb +0 -15
  44. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar.rb +0 -240
  45. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/grammar_symbol.rb +0 -27
  46. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/precedence.rb +0 -19
  47. data/test/vendor/dhaka-2.2.1/lib/dhaka/grammar/production.rb +0 -36
  48. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/accept_actions.rb +0 -36
  49. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/alphabet.rb +0 -21
  50. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/compiled_lexer.rb +0 -46
  51. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/dfa.rb +0 -121
  52. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexeme.rb +0 -32
  53. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer.rb +0 -70
  54. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/lexer_run.rb +0 -78
  55. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_grammar.rb +0 -392
  56. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_parser.rb +0 -2010
  57. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/regex_tokenizer.rb +0 -14
  58. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/specification.rb +0 -96
  59. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state.rb +0 -68
  60. data/test/vendor/dhaka-2.2.1/lib/dhaka/lexer/state_machine.rb +0 -37
  61. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/action.rb +0 -55
  62. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/channel.rb +0 -58
  63. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/compiled_parser.rb +0 -51
  64. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/conflict.rb +0 -54
  65. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/item.rb +0 -42
  66. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_result.rb +0 -50
  67. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parse_tree.rb +0 -66
  68. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser.rb +0 -165
  69. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_methods.rb +0 -11
  70. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_run.rb +0 -39
  71. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/parser_state.rb +0 -74
  72. data/test/vendor/dhaka-2.2.1/lib/dhaka/parser/token.rb +0 -22
  73. data/test/vendor/dhaka-2.2.1/lib/dhaka/runtime.rb +0 -51
  74. data/test/vendor/dhaka-2.2.1/lib/dhaka/tokenizer/tokenizer.rb +0 -190
  75. data/test/vendor/dhaka-2.2.1/lib/dhaka.rb +0 -62
  76. data/test/vendor/dhaka-2.2.1/test/all_tests.rb +0 -5
  77. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator.rb +0 -64
  78. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_evaluator_test.rb +0 -43
  79. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar.rb +0 -41
  80. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_grammar_test.rb +0 -9
  81. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_test_methods.rb +0 -9
  82. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer.rb +0 -39
  83. data/test/vendor/dhaka-2.2.1/test/arithmetic/arithmetic_tokenizer_test.rb +0 -38
  84. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_evaluator.rb +0 -43
  85. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar.rb +0 -24
  86. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_grammar_test.rb +0 -30
  87. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_lexer_specification.rb +0 -23
  88. data/test/vendor/dhaka-2.2.1/test/arithmetic_precedence/arithmetic_precedence_parser_test.rb +0 -33
  89. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_grammar.rb +0 -23
  90. data/test/vendor/dhaka-2.2.1/test/brackets/bracket_tokenizer.rb +0 -22
  91. data/test/vendor/dhaka-2.2.1/test/brackets/brackets_test.rb +0 -28
  92. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver.rb +0 -46
  93. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_driver_test.rb +0 -276
  94. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator.rb +0 -284
  95. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_evaluator_test.rb +0 -38
  96. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_grammar.rb +0 -104
  97. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer.rb +0 -109
  98. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_specification.rb +0 -37
  99. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_lexer_test.rb +0 -58
  100. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser.rb +0 -879
  101. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_parser_test.rb +0 -55
  102. data/test/vendor/dhaka-2.2.1/test/chittagong/chittagong_test.rb +0 -170
  103. data/test/vendor/dhaka-2.2.1/test/core/another_lalr_but_not_slr_grammar.rb +0 -20
  104. data/test/vendor/dhaka-2.2.1/test/core/compiled_parser_test.rb +0 -44
  105. data/test/vendor/dhaka-2.2.1/test/core/dfa_test.rb +0 -170
  106. data/test/vendor/dhaka-2.2.1/test/core/evaluator_test.rb +0 -22
  107. data/test/vendor/dhaka-2.2.1/test/core/grammar_test.rb +0 -83
  108. data/test/vendor/dhaka-2.2.1/test/core/lalr_but_not_slr_grammar.rb +0 -19
  109. data/test/vendor/dhaka-2.2.1/test/core/lexer_test.rb +0 -139
  110. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar.rb +0 -7
  111. data/test/vendor/dhaka-2.2.1/test/core/malformed_grammar_test.rb +0 -8
  112. data/test/vendor/dhaka-2.2.1/test/core/nullable_grammar.rb +0 -21
  113. data/test/vendor/dhaka-2.2.1/test/core/parse_result_test.rb +0 -44
  114. data/test/vendor/dhaka-2.2.1/test/core/parser_state_test.rb +0 -24
  115. data/test/vendor/dhaka-2.2.1/test/core/parser_test.rb +0 -131
  116. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar.rb +0 -17
  117. data/test/vendor/dhaka-2.2.1/test/core/precedence_grammar_test.rb +0 -9
  118. data/test/vendor/dhaka-2.2.1/test/core/rr_conflict_grammar.rb +0 -21
  119. data/test/vendor/dhaka-2.2.1/test/core/simple_grammar.rb +0 -22
  120. data/test/vendor/dhaka-2.2.1/test/core/sr_conflict_grammar.rb +0 -16
  121. data/test/vendor/dhaka-2.2.1/test/dhaka_test_helper.rb +0 -17
  122. data/test/vendor/dhaka-2.2.1/test/fake_logger.rb +0 -17
  123. data/test/vendor/simplerdb-0.2/lib/simplerdb/client_exception.rb +0 -10
  124. data/test/vendor/simplerdb-0.2/lib/simplerdb/db.rb +0 -146
  125. data/test/vendor/simplerdb-0.2/lib/simplerdb/query_language.rb +0 -266
  126. data/test/vendor/simplerdb-0.2/lib/simplerdb/server.rb +0 -33
  127. data/test/vendor/simplerdb-0.2/lib/simplerdb/servlet.rb +0 -191
  128. data/test/vendor/simplerdb-0.2/lib/simplerdb.rb +0 -3
  129. data/test/vendor/simplerdb-0.2/test/functional_test.rb +0 -81
  130. data/test/vendor/simplerdb-0.2/test/query_evaluator_test.rb +0 -73
  131. data/test/vendor/simplerdb-0.2/test/query_parser_test.rb +0 -64
  132. data/test/vendor/simplerdb-0.2/test/simplerdb_test.rb +0 -80
@@ -1,29 +0,0 @@
1
- module Dhaka
2
- module Dot #:nodoc:
3
- class Digraph #:nodoc:
4
- def initialize(node_attributes = {})
5
- @result = ["digraph x {"]
6
- @result << %(node #{dotify_hash(node_attributes)})
7
- yield(self)
8
- @result << '}'
9
- end
10
-
11
- def node(obj, attributes = {})
12
- @result << "#{obj.object_id} #{dotify_hash(attributes)}"
13
- end
14
-
15
- def edge(src, dest, attributes = {})
16
- @result << "#{src.object_id} -> #{dest.object_id} #{dotify_hash(attributes)}"
17
- end
18
-
19
- def dotify_hash hash
20
- sorted_key_value_pairs = hash.collect {|key, value| [key.to_s, value.to_s]}.sort
21
- hash.empty? ? "" : '[' + sorted_key_value_pairs.collect {|key, value| "#{key}=#{value.to_s.inspect}"}.join(' ') + ']'
22
- end
23
-
24
- def to_dot
25
- @result.join("\n")
26
- end
27
- end
28
- end
29
- end
@@ -1,133 +0,0 @@
1
- module Dhaka
2
- # Abstract base class for evaluators.
3
- #
4
- # Defining an evaluator is an easy way to perform syntax-directed evaluation without having to generate an abstract
5
- # syntax tree representation of the input.
6
- #
7
- # An evaluation rule for a given production named +bar+ is defined by calling +for_bar+ with
8
- # a block that performs the evaluation. For detailed examples, see the evaluators in the
9
- # test suite.
10
- #
11
- # The following is an evaluator for arithmetic expressions. When a parse tree node is encountered that
12
- # corresponds to the production named +addition+, the block passed to +for_addition+ is invoked. The +evaluate+
13
- # method is then recursively called on the child nodes, in this case the operands to the addition operation. The
14
- # result is obtained by adding the evaluation results of the child nodes.
15
- #
16
- # class ArithmeticPrecedenceEvaluator < Dhaka::Evaluator
17
- #
18
- # self.grammar = ArithmeticPrecedenceGrammar
19
- #
20
- # define_evaluation_rules do
21
- #
22
- # for_subtraction do
23
- # evaluate(child_nodes[0]) - evaluate(child_nodes[2])
24
- # end
25
- #
26
- # for_addition do
27
- # evaluate(child_nodes[0]) + evaluate(child_nodes[2])
28
- # end
29
- #
30
- # for_division do
31
- # evaluate(child_nodes[0]).to_f/evaluate(child_nodes[2])
32
- # end
33
- #
34
- # for_multiplication do
35
- # evaluate(child_nodes[0]) * evaluate(child_nodes[2])
36
- # end
37
- #
38
- # for_literal do
39
- # child_nodes[0].token.value.to_i
40
- # end
41
- #
42
- # for_parenthetized_expression do
43
- # evaluate(child_nodes[1])
44
- # end
45
- #
46
- # for_negated_expression do
47
- # -evaluate(child_nodes[1])
48
- # end
49
- #
50
- # for_power do
51
- # evaluate(child_nodes[0])**evaluate(child_nodes[2])
52
- # end
53
- #
54
- # end
55
- #
56
- # end
57
-
58
- class Evaluator < SimpleDelegator
59
- class << self
60
- # Define evaluation rules within a block passed to this method. The evaluator will define
61
- # default evaluation rules for pass-through productions (i.e. productions with expansions
62
- # consisting of exactly one grammar symbol). The default evaluation rule for such productions
63
- # is to simply return the result of calling +evaluate+ on the unique child node. Setting the
64
- # <tt>:raise_error</tt> option to true tells the evaluator to throw an exception if you neglect
65
- # to define a rule for a non-pass-through production (one where the expansion consists of
66
- # multiple symbols), listing all the productions that absolutely need to be defined before you
67
- # can continue.
68
- def define_evaluation_rules(options = {})
69
- yield
70
- check_definitions(options)
71
- end
72
-
73
- private
74
-
75
- def check_definitions(options)
76
- filter = lambda {|productions| productions.map {|production| production.name} - actions}
77
- pass_through_productions_without_rules = filter[grammar.productions.select {|production| production.expansion.size == 1}]
78
- pass_through_productions_without_rules.each do |rule_name|
79
- send(:define_method, rule_name) do
80
- evaluate(child_nodes.first)
81
- end
82
- end
83
- non_trivial_productions_with_rules_undefined = filter[grammar.productions.select {|production| production.expansion.size != 1}]
84
- raise EvaluatorDefinitionError.new(non_trivial_productions_with_rules_undefined) unless non_trivial_productions_with_rules_undefined.empty? || !options[:raise_error]
85
- end
86
-
87
- def inherited(evaluator)
88
- class << evaluator
89
- attr_accessor :grammar, :actions
90
- end
91
- evaluator.actions = []
92
- end
93
-
94
- def method_missing(method_name, *args, &blk)
95
- name = method_name.to_s
96
- if name =~ /^for_(.+)$/
97
- rule_name = $1
98
- raise "Attempted to define evaluation rule for non-existent production '#{rule_name}'" unless grammar.production_named(rule_name)
99
- actions << rule_name
100
- send(:define_method, rule_name, &blk)
101
- else
102
- super
103
- end
104
- end
105
- end
106
-
107
- # Evaluate a parse tree node.
108
- def evaluate node
109
- @node_stack ||= []
110
- @node_stack << node
111
- __setobj__(@node_stack.last)
112
- result = send(node.production.name)
113
- @node_stack.pop
114
- __setobj__(@node_stack.last)
115
- result
116
- end
117
-
118
- def initialize
119
-
120
- end
121
- end
122
-
123
- class EvaluatorDefinitionError < StandardError #:nodoc:
124
- def initialize(non_trivial_productions_with_rules_undefined)
125
- @non_trivial_productions_with_rules_undefined = non_trivial_productions_with_rules_undefined
126
- end
127
-
128
- def to_s
129
- result = "The following non-trivial productions do not have any evaluation rules defined:\n"
130
- result << @non_trivial_productions_with_rules_undefined.join("\n")
131
- end
132
- end
133
- end
@@ -1,15 +0,0 @@
1
- module Dhaka
2
- # A subclass of Hash with a dirty flag
3
- class ClosureHash < Hash #:nodoc:
4
- attr_accessor :dirty
5
-
6
- def initialize
7
- super
8
- @dirty = false
9
- end
10
-
11
- def load_set(set)
12
- set.each {|item| self[item] = item}
13
- end
14
- end
15
- end
@@ -1,240 +0,0 @@
1
- module Dhaka
2
-
3
- # Reserved name for the start symbol for all grammars.
4
- START_SYMBOL_NAME = "_Start_"
5
- END_SYMBOL_NAME = "_End_" #:nodoc:
6
-
7
- # Productions for specific grammar symbols are defined in the context of this class.
8
- class ProductionBuilder
9
- # +symbol+ is the grammar symbol that productions are being defined for.
10
- def initialize(grammar, symbol)
11
- @grammar = grammar
12
- @symbol = symbol
13
- end
14
-
15
- def to_byte(char)
16
- char.respond_to?(:bytes) ? char.bytes.first : char[0]
17
- end
18
-
19
- # Creates a new production for +symbol+ with an expansion of +expansion+. The options hash can include
20
- # a directive <tt>:prec</tt>, the value of which is a grammar symbol name. The precedence of the production is then
21
- # set to the precedence of the grammar symbol corresponding to that name.
22
- #
23
- # See the arithmetic precedence grammar in the test suites for an example.
24
- def method_missing(production_name, expansion, options = {}, &blk)
25
- expansion_symbols = Array(expansion).collect {|name| @grammar.symbols[name]}
26
- production_args = [@symbol, expansion_symbols, production_name.to_s, blk, @grammar.production_index]
27
- if precedence_symbol_name = options[:prec]
28
- production_args << @grammar.symbol_for_name(precedence_symbol_name).precedence
29
- end
30
-
31
- production = Production.new(*production_args)
32
- @grammar.production_index += 1
33
-
34
- @symbol.nullable = true if expansion_symbols.empty?
35
- @grammar.productions_by_symbol[production.symbol] << production
36
- raise "Duplicate production named #{production.name}" if @grammar.productions_by_name[production.name]
37
- @grammar.productions_by_name[production.name] = production
38
- end
39
- end
40
-
41
- # The precedence builder defines three methods, +left+, +right+ and +nonassoc+. These accept arrays of grammar
42
- # symbols all of which have the same precedence level and associativity.
43
- #
44
- # See the arithmetic precedence grammar in the test suites for an example of how this works.
45
- class PrecedenceBuilder
46
- def initialize(grammar) #:nodoc:
47
- @grammar = grammar
48
- @precedence_level = 0
49
- end
50
-
51
- [:left, :right, :nonassoc].each do |associativity|
52
- define_method(associativity) do |symbols|
53
- assign_precedences associativity, symbols
54
- end
55
- end
56
-
57
- private
58
- def assign_precedences(associativity, symbol_names)
59
- symbol_names.each do |symbol_name|
60
- symbol = @grammar.symbols[symbol_name]
61
- symbol.precedence = Precedence.new(@precedence_level, associativity)
62
- end
63
- @precedence_level += 1
64
- end
65
- end
66
-
67
- # Abstract base class for grammar specifications.
68
- #
69
- # The following is a grammar specification for simple arithmetic. Precedences are specified as in Yacc -
70
- # in ascending order of binding strength, with equal-strength symbols on the same level.
71
- # Production rules are specified for each symbol by specifying the name of the production (used when
72
- # encoding the Evaluator) and the expansion for that particular production. For example, the production named
73
- # +addition+ expands the symbol <tt>'E'</tt> to the list of symbols <tt>['E', '+', 'E']</tt>.
74
- #
75
- # class ArithmeticPrecedenceGrammar < Dhaka::Grammar
76
- # precedences do
77
- # left ['+', '-']
78
- # left ['*', '/']
79
- # nonassoc ['^']
80
- # end
81
- #
82
- # for_symbol(Dhaka::START_SYMBOL_NAME) do
83
- # expression ['E']
84
- # end
85
- #
86
- # for_symbol('E') do
87
- # addition ['E', '+', 'E']
88
- # subtraction ['E', '-', 'E']
89
- # multiplication ['E', '*', 'E']
90
- # division ['E', '/', 'E']
91
- # power ['E', '^', 'E']
92
- # literal ['n']
93
- # parenthetized_expression ['(', 'E', ')']
94
- # negated_expression ['-', 'E'], :prec => '*'
95
- # end
96
- # end
97
- #
98
- # In the above grammar, the symbols <tt>+</tt> and <tt>-</tt> are declared as being +left+-associative, meaning that
99
- # 1 + 2 + 3 is parsed as (1 + 2) + 3 as opposed to 1 + (2 + 3) (+right+-associativity). The symbol <tt>^</tt> is declared
100
- # +nonassoc+ which means that expressions such as 2 ^ 3 ^ 4 are not allowed (non-associative). <tt>+</tt> and <tt>-</tt> are listed
101
- # before <tt>^</tt> which means that they bind lower, and an expression such as 2 + 3 ^ 5 will be always be parsed as
102
- # 2 + (3 ^ 5) and not (2 + 3) ^ 5.
103
- class Grammar
104
- class << self
105
- # Used for defining the Production-s for the symbol with name +symbol+. The block +blk+ is
106
- # evaluated in the context of a ProductionBuilder.
107
- def for_symbol symbol, &blk
108
- symbol = symbols[symbol]
109
- symbol.non_terminal = true
110
- ProductionBuilder.new(self, symbol).instance_eval(&blk)
111
- end
112
-
113
- # Used for defining the precedences and associativities of symbols. The block +blk+ is
114
- # evaluated in the context of a PrecedenceBuilder.
115
- def precedences &blk
116
- PrecedenceBuilder.new(self).instance_eval(&blk)
117
- end
118
-
119
- # Returns the grammar symbol identified by +name+
120
- def symbol_for_name(name)
121
- if symbols.has_key? name
122
- symbols[name]
123
- else
124
- raise "No symbol with name #{name} found"
125
- end
126
- end
127
-
128
- # Returns a list of all the Production-s in this grammar.
129
- def productions
130
- productions_by_name.values
131
- end
132
-
133
- def productions_for_symbol(symbol) #:nodoc:
134
- productions_by_symbol[symbol]
135
- end
136
-
137
- def closure(kernel) #:nodoc:
138
- channels = Hash.new {|hash, start_item| hash[start_item] = Set.new}
139
- result = compute_closure(kernel) do |hash, item|
140
- if item.next_symbol and item.next_symbol.non_terminal
141
- productions_by_symbol[item.next_symbol].each do |production|
142
- new_channel = spontaneous_channel(item, hash[Item.new(production, 0)])
143
- channels[item] << new_channel
144
- end
145
- end
146
- end
147
- [result, channels]
148
- end
149
-
150
- def passive_channel(start_item, end_item) #:nodoc:
151
- PassiveChannel.new(self, start_item, end_item)
152
- end
153
-
154
- def first(given_symbol) #:nodoc:
155
- cached_result = __first_cache[given_symbol]
156
- return cached_result if cached_result
157
- result = compute_closure([given_symbol]) do |hash, symbol|
158
- productions_by_symbol[symbol].each do |production|
159
- symbol_index = 0
160
- while next_symbol = production.expansion[symbol_index]
161
- hash[next_symbol]
162
- break unless next_symbol.nullable
163
- symbol_index += 1
164
- end
165
- end if symbol.non_terminal
166
- end.values.select {|symbol| symbol.terminal}.to_set
167
- __first_cache[given_symbol] = result
168
- result
169
- end
170
-
171
- # Returns the Production identified by +name+.
172
- def production_named(name)
173
- productions_by_name[name]
174
- end
175
-
176
- # Returns the set of terminal symbols in the grammar.
177
- def terminal_symbols
178
- symbols.values.select {|symbol| symbol.terminal}
179
- end
180
-
181
- # Returns the set of non-terminal symbols in the grammar.
182
- def non_terminal_symbols
183
- symbols.values.select {|symbol| symbol.non_terminal}
184
- end
185
-
186
- # Export the grammar to a BNF-like format
187
- def to_bnf
188
- result = []
189
- last_symbol = nil
190
- productions.sort.each do |production|
191
- if production.symbol != last_symbol
192
- result << ""
193
- result << "#{production.symbol.name.inspect} :"
194
- last_symbol = production.symbol
195
- end
196
- result << " | #{production.expansion.collect{|symbol| symbol.name.inspect}.join(' ')}"
197
- end
198
- result.join("\n")
199
- end
200
-
201
- private
202
-
203
- def inherited(grammar)
204
- class << grammar
205
- attr_accessor :symbols, :productions_by_symbol, :productions_by_name, :start_symbol, :end_symbol, :__first_cache, :production_index
206
- end
207
- grammar.symbols = Hash.new {|hash, name| hash[name] = GrammarSymbol.new(name)}
208
- grammar.productions_by_symbol = Hash.new {|hash, name| hash[name] = Set.new([])}
209
- grammar.productions_by_name = {}
210
- grammar.end_symbol = grammar.symbols[END_SYMBOL_NAME]
211
- grammar.start_symbol = grammar.symbols[START_SYMBOL_NAME]
212
- grammar.__first_cache = {}
213
- grammar.production_index = 0
214
- end
215
-
216
- def spontaneous_channel(start_item, end_item)
217
- SpontaneousChannel.new(self, start_item, end_item)
218
- end
219
-
220
- def compute_closure(initial)
221
- closure_hash = ClosureHash.new do |hash, item|
222
- hash.dirty = true
223
- hash[item] = item
224
- end
225
-
226
- closure_hash.load_set(initial)
227
-
228
- loop do
229
- closure_hash.keys.each do |element|
230
- yield closure_hash, element
231
- end
232
- break unless closure_hash.dirty
233
- closure_hash.dirty = false
234
- end
235
- closure_hash
236
- end
237
- end
238
- end
239
-
240
- end
@@ -1,27 +0,0 @@
1
- module Dhaka
2
- # Each grammar symbol is uniquely identified by a string name. The name of a symbol can
3
- # be anything (except the two reserved names <tt>'\_Start_'</tt> and <tt>'\_End_'</tt>) and need not
4
- # correspond to its character representation. For example, an ampersand in the input string could
5
- # be tokenized as a symbol with a name 'AND_OP'. You never have to directly instantiate a
6
- # GrammarSymbol. It is done implicitly for you when you define a Grammar.
7
- class GrammarSymbol
8
- attr_reader :name
9
- attr_accessor :non_terminal, :nullable, :precedence, :associativity
10
-
11
- def initialize(name)
12
- @name = name
13
- end
14
-
15
- def terminal
16
- !non_terminal
17
- end
18
-
19
- def to_s #:nodoc:
20
- name.dup
21
- end
22
-
23
- def <=> other
24
- name <=> other.name
25
- end
26
- end
27
- end
@@ -1,19 +0,0 @@
1
- module Dhaka
2
- class Precedence #:nodoc:
3
- include Comparable
4
- attr_reader :precedence_level, :associativity
5
-
6
- def initialize(precedence_level, associativity)
7
- @precedence_level = precedence_level
8
- @associativity = associativity
9
- end
10
-
11
- def <=> other
12
- precedence_level <=> other.precedence_level
13
- end
14
-
15
- def to_s
16
- "Precedence: #{precedence_level} Associativity: #{associativity}"
17
- end
18
- end
19
- end
@@ -1,36 +0,0 @@
1
- module Dhaka
2
- class Production
3
- include Comparable
4
-
5
- attr_reader :symbol, :expansion, :name, :action, :priority
6
-
7
- def initialize(symbol, expansion, name, action, priority, precedence = nil)
8
- @symbol = symbol
9
- @expansion = expansion
10
- @name = name
11
- @precedence = precedence
12
- @action = action || proc { self }
13
- @priority = priority
14
- end
15
-
16
- def precedence
17
- unless @precedence
18
- expansion.reverse_each do |symbol|
19
- if symbol.terminal
20
- @precedence = symbol.precedence
21
- break
22
- end
23
- end
24
- end
25
- @precedence
26
- end
27
-
28
- def to_s #:nodoc:
29
- "#{name} #{symbol} ::= #{expansion.join(' ')}"
30
- end
31
-
32
- def <=> other
33
- priority <=> other.priority
34
- end
35
- end
36
- end
@@ -1,36 +0,0 @@
1
- module Dhaka
2
- module LexerSupport
3
- class AcceptAction
4
- attr_reader :pattern
5
- def initialize(pattern)
6
- @pattern = pattern
7
- end
8
-
9
- def call(lexer_run)
10
- lexer_run.accept(pattern)
11
- end
12
-
13
- def compile_to_ruby_source
14
- "accept(#{pattern.inspect})"
15
- end
16
-
17
- def to_dot
18
- "Accept #{pattern.inspect}"
19
- end
20
- end
21
-
22
- class LookaheadAcceptAction < AcceptAction
23
- def call(lexer_run)
24
- lexer_run.accept_last_saved_checkpoint(pattern)
25
- end
26
-
27
- def compile_to_ruby_source
28
- "accept_with_lookahead(#{pattern.inspect})"
29
- end
30
-
31
- def to_dot
32
- "Accept With Lookahead #{pattern.inspect}"
33
- end
34
- end
35
- end
36
- end
@@ -1,21 +0,0 @@
1
- module Dhaka
2
- module LexerSupport
3
- DIGITS = ('0'..'9').to_a
4
- LOWERCASE_LETTERS = ('a'..'z').to_a
5
- UPPERCASE_LETTERS = ('A'..'Z').to_a
6
- LETTERS = LOWERCASE_LETTERS + UPPERCASE_LETTERS
7
- WHITESPACE = [" ", "\r", "\n", "\t"]
8
- SYMBOLS = %w| ~ ` ! @ # % & _ = : ; " ' < , > - |
9
- CLASSES = {'d' => DIGITS, 'w' => LETTERS, 's' => WHITESPACE}
10
-
11
- OPERATOR_CHARACTERS = {'(' => 'open_parenth', ')' => 'close_parenth', '[' => 'open_square_bracket',
12
- ']' => 'close_square_bracket', '+' => 'plus', '*' => 'asterisk',
13
- '?' => 'question_mark', '.' => 'period', '\\' => 'back_slash',
14
- '|' => 'pipe', '{' => 'left_curly_brace', '}' => 'right_curly_brace',
15
- '/' => 'forward_slash', '^' => 'caret', '$' => 'dollar'}
16
-
17
- SET_OPERATOR_CHARACTERS = %w| - ^ [ ] \\ |
18
-
19
- ALL_CHARACTERS = DIGITS + LETTERS + SYMBOLS + WHITESPACE + OPERATOR_CHARACTERS.keys
20
- end
21
- end
@@ -1,46 +0,0 @@
1
- module Dhaka
2
- # Abstract base class of all compiled Lexers. It is only used by generated code.
3
- class CompiledLexer
4
-
5
- class << self
6
- # Returns a LexerRun that tokenizes +input+.
7
- def lex input
8
- LexerRun.new(self, input)
9
- end
10
-
11
- def start_state #:nodoc:
12
- states[start_state_id]
13
- end
14
-
15
- def action_for_pattern pattern #:nodoc:
16
- specification.items[pattern].action
17
- end
18
-
19
- private
20
- def inherited(lexer)
21
- class << lexer
22
- attr_accessor :states, :specification, :start_state_id
23
- end
24
- lexer.states = Hash.new do |hash, state_id|
25
- hash[state_id] = LexerSupport::State.new(lexer, nil)
26
- end
27
- end
28
-
29
- def at_state x, &blk
30
- states[x].instance_eval(&blk)
31
- end
32
-
33
- def start_with start_state_id
34
- self.start_state_id = start_state_id
35
- end
36
-
37
- def switch_to dest_state_id
38
- states[dest_state_id]
39
- end
40
-
41
- def inspect
42
- "<Dhaka::CompiledLexer specification : #{specification}>"
43
- end
44
- end
45
- end
46
- end