rubysl-rexml 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rexml/attlistdecl.rb +62 -0
  9. data/lib/rexml/attribute.rb +185 -0
  10. data/lib/rexml/cdata.rb +67 -0
  11. data/lib/rexml/child.rb +96 -0
  12. data/lib/rexml/comment.rb +80 -0
  13. data/lib/rexml/doctype.rb +271 -0
  14. data/lib/rexml/document.rb +230 -0
  15. data/lib/rexml/dtd/attlistdecl.rb +10 -0
  16. data/lib/rexml/dtd/dtd.rb +51 -0
  17. data/lib/rexml/dtd/elementdecl.rb +17 -0
  18. data/lib/rexml/dtd/entitydecl.rb +56 -0
  19. data/lib/rexml/dtd/notationdecl.rb +39 -0
  20. data/lib/rexml/element.rb +1227 -0
  21. data/lib/rexml/encoding.rb +71 -0
  22. data/lib/rexml/encodings/CP-1252.rb +103 -0
  23. data/lib/rexml/encodings/EUC-JP.rb +35 -0
  24. data/lib/rexml/encodings/ICONV.rb +22 -0
  25. data/lib/rexml/encodings/ISO-8859-1.rb +7 -0
  26. data/lib/rexml/encodings/ISO-8859-15.rb +72 -0
  27. data/lib/rexml/encodings/SHIFT-JIS.rb +37 -0
  28. data/lib/rexml/encodings/SHIFT_JIS.rb +1 -0
  29. data/lib/rexml/encodings/UNILE.rb +34 -0
  30. data/lib/rexml/encodings/US-ASCII.rb +30 -0
  31. data/lib/rexml/encodings/UTF-16.rb +35 -0
  32. data/lib/rexml/encodings/UTF-8.rb +18 -0
  33. data/lib/rexml/entity.rb +166 -0
  34. data/lib/rexml/formatters/default.rb +109 -0
  35. data/lib/rexml/formatters/pretty.rb +138 -0
  36. data/lib/rexml/formatters/transitive.rb +56 -0
  37. data/lib/rexml/functions.rb +382 -0
  38. data/lib/rexml/instruction.rb +70 -0
  39. data/lib/rexml/light/node.rb +196 -0
  40. data/lib/rexml/namespace.rb +47 -0
  41. data/lib/rexml/node.rb +75 -0
  42. data/lib/rexml/output.rb +24 -0
  43. data/lib/rexml/parent.rb +166 -0
  44. data/lib/rexml/parseexception.rb +51 -0
  45. data/lib/rexml/parsers/baseparser.rb +503 -0
  46. data/lib/rexml/parsers/lightparser.rb +60 -0
  47. data/lib/rexml/parsers/pullparser.rb +196 -0
  48. data/lib/rexml/parsers/sax2parser.rb +238 -0
  49. data/lib/rexml/parsers/streamparser.rb +46 -0
  50. data/lib/rexml/parsers/treeparser.rb +97 -0
  51. data/lib/rexml/parsers/ultralightparser.rb +56 -0
  52. data/lib/rexml/parsers/xpathparser.rb +698 -0
  53. data/lib/rexml/quickpath.rb +266 -0
  54. data/lib/rexml/rexml.rb +32 -0
  55. data/lib/rexml/sax2listener.rb +97 -0
  56. data/lib/rexml/source.rb +251 -0
  57. data/lib/rexml/streamlistener.rb +92 -0
  58. data/lib/rexml/syncenumerator.rb +33 -0
  59. data/lib/rexml/text.rb +344 -0
  60. data/lib/rexml/undefinednamespaceexception.rb +8 -0
  61. data/lib/rexml/validation/relaxng.rb +559 -0
  62. data/lib/rexml/validation/validation.rb +155 -0
  63. data/lib/rexml/validation/validationexception.rb +9 -0
  64. data/lib/rexml/xmldecl.rb +119 -0
  65. data/lib/rexml/xmltokens.rb +18 -0
  66. data/lib/rexml/xpath.rb +66 -0
  67. data/lib/rexml/xpath_parser.rb +792 -0
  68. data/lib/rubysl/rexml.rb +1 -0
  69. data/lib/rubysl/rexml/version.rb +5 -0
  70. data/rubysl-rexml.gemspec +23 -0
  71. data/spec/attribute/clone_spec.rb +10 -0
  72. data/spec/attribute/element_spec.rb +22 -0
  73. data/spec/attribute/equal_value_spec.rb +17 -0
  74. data/spec/attribute/hash_spec.rb +12 -0
  75. data/spec/attribute/initialize_spec.rb +28 -0
  76. data/spec/attribute/inspect_spec.rb +19 -0
  77. data/spec/attribute/namespace_spec.rb +23 -0
  78. data/spec/attribute/node_type_spec.rb +9 -0
  79. data/spec/attribute/prefix_spec.rb +17 -0
  80. data/spec/attribute/remove_spec.rb +19 -0
  81. data/spec/attribute/to_s_spec.rb +13 -0
  82. data/spec/attribute/to_string_spec.rb +14 -0
  83. data/spec/attribute/value_spec.rb +14 -0
  84. data/spec/attribute/write_spec.rb +22 -0
  85. data/spec/attribute/xpath_spec.rb +19 -0
  86. data/spec/attributes/add_spec.rb +6 -0
  87. data/spec/attributes/append_spec.rb +6 -0
  88. data/spec/attributes/delete_all_spec.rb +30 -0
  89. data/spec/attributes/delete_spec.rb +26 -0
  90. data/spec/attributes/each_attribute_spec.rb +24 -0
  91. data/spec/attributes/each_spec.rb +24 -0
  92. data/spec/attributes/element_reference_spec.rb +18 -0
  93. data/spec/attributes/element_set_spec.rb +25 -0
  94. data/spec/attributes/get_attribute_ns_spec.rb +13 -0
  95. data/spec/attributes/get_attribute_spec.rb +28 -0
  96. data/spec/attributes/initialize_spec.rb +18 -0
  97. data/spec/attributes/length_spec.rb +6 -0
  98. data/spec/attributes/namespaces_spec.rb +5 -0
  99. data/spec/attributes/prefixes_spec.rb +23 -0
  100. data/spec/attributes/shared/add.rb +17 -0
  101. data/spec/attributes/shared/length.rb +12 -0
  102. data/spec/attributes/size_spec.rb +6 -0
  103. data/spec/attributes/to_a_spec.rb +20 -0
  104. data/spec/cdata/clone_spec.rb +9 -0
  105. data/spec/cdata/initialize_spec.rb +24 -0
  106. data/spec/cdata/shared/to_s.rb +11 -0
  107. data/spec/cdata/to_s_spec.rb +6 -0
  108. data/spec/cdata/value_spec.rb +6 -0
  109. data/spec/document/add_element_spec.rb +30 -0
  110. data/spec/document/add_spec.rb +60 -0
  111. data/spec/document/clone_spec.rb +19 -0
  112. data/spec/document/doctype_spec.rb +14 -0
  113. data/spec/document/encoding_spec.rb +21 -0
  114. data/spec/document/expanded_name_spec.rb +15 -0
  115. data/spec/document/new_spec.rb +37 -0
  116. data/spec/document/node_type_spec.rb +7 -0
  117. data/spec/document/root_spec.rb +11 -0
  118. data/spec/document/stand_alone_spec.rb +18 -0
  119. data/spec/document/version_spec.rb +13 -0
  120. data/spec/document/write_spec.rb +38 -0
  121. data/spec/document/xml_decl_spec.rb +14 -0
  122. data/spec/element/add_attribute_spec.rb +40 -0
  123. data/spec/element/add_attributes_spec.rb +21 -0
  124. data/spec/element/add_element_spec.rb +38 -0
  125. data/spec/element/add_namespace_spec.rb +23 -0
  126. data/spec/element/add_text_spec.rb +23 -0
  127. data/spec/element/attribute_spec.rb +16 -0
  128. data/spec/element/attributes_spec.rb +18 -0
  129. data/spec/element/cdatas_spec.rb +23 -0
  130. data/spec/element/clone_spec.rb +28 -0
  131. data/spec/element/comments_spec.rb +20 -0
  132. data/spec/element/delete_attribute_spec.rb +38 -0
  133. data/spec/element/delete_element_spec.rb +50 -0
  134. data/spec/element/delete_namespace_spec.rb +24 -0
  135. data/spec/element/document_spec.rb +17 -0
  136. data/spec/element/each_element_with_attribute_spec.rb +34 -0
  137. data/spec/element/each_element_with_text_spec.rb +30 -0
  138. data/spec/element/get_text_spec.rb +17 -0
  139. data/spec/element/has_attributes_spec.rb +16 -0
  140. data/spec/element/has_elements_spec.rb +17 -0
  141. data/spec/element/has_text_spec.rb +15 -0
  142. data/spec/element/inspect_spec.rb +26 -0
  143. data/spec/element/instructions_spec.rb +20 -0
  144. data/spec/element/namespace_spec.rb +26 -0
  145. data/spec/element/namespaces_spec.rb +31 -0
  146. data/spec/element/new_spec.rb +34 -0
  147. data/spec/element/next_element_spec.rb +18 -0
  148. data/spec/element/node_type_spec.rb +7 -0
  149. data/spec/element/prefixes_spec.rb +22 -0
  150. data/spec/element/previous_element_spec.rb +19 -0
  151. data/spec/element/raw_spec.rb +23 -0
  152. data/spec/element/root_spec.rb +27 -0
  153. data/spec/element/text_spec.rb +45 -0
  154. data/spec/element/texts_spec.rb +15 -0
  155. data/spec/element/whitespace_spec.rb +22 -0
  156. data/spec/node/each_recursive_spec.rb +20 -0
  157. data/spec/node/find_first_recursive_spec.rb +24 -0
  158. data/spec/node/index_in_parent_spec.rb +14 -0
  159. data/spec/node/next_sibling_node_spec.rb +20 -0
  160. data/spec/node/parent_spec.rb +20 -0
  161. data/spec/node/previous_sibling_node_spec.rb +20 -0
  162. data/spec/shared/each_element.rb +35 -0
  163. data/spec/shared/elements_to_a.rb +35 -0
  164. data/spec/text/append_spec.rb +9 -0
  165. data/spec/text/clone_spec.rb +9 -0
  166. data/spec/text/comparison_spec.rb +24 -0
  167. data/spec/text/empty_spec.rb +11 -0
  168. data/spec/text/indent_text_spec.rb +23 -0
  169. data/spec/text/inspect_spec.rb +7 -0
  170. data/spec/text/new_spec.rb +48 -0
  171. data/spec/text/node_type_spec.rb +7 -0
  172. data/spec/text/normalize_spec.rb +7 -0
  173. data/spec/text/read_with_substitution_spec.rb +12 -0
  174. data/spec/text/to_s_spec.rb +17 -0
  175. data/spec/text/unnormalize_spec.rb +7 -0
  176. data/spec/text/value_spec.rb +36 -0
  177. data/spec/text/wrap_spec.rb +20 -0
  178. data/spec/text/write_with_substitution_spec.rb +32 -0
  179. metadata +385 -0
@@ -0,0 +1,8 @@
1
+ require 'rexml/parseexception'
2
+ module REXML
3
+ class UndefinedNamespaceException < ParseException
4
+ def initialize( prefix, source, parser )
5
+ super( "Undefined prefix #{prefix} found" )
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,559 @@
1
+ require "rexml/validation/validation"
2
+ require "rexml/parsers/baseparser"
3
+
4
+ module REXML
5
+ module Validation
6
+ # Implemented:
7
+ # * empty
8
+ # * element
9
+ # * attribute
10
+ # * text
11
+ # * optional
12
+ # * choice
13
+ # * oneOrMore
14
+ # * zeroOrMore
15
+ # * group
16
+ # * value
17
+ # * interleave
18
+ # * mixed
19
+ # * ref
20
+ # * grammar
21
+ # * start
22
+ # * define
23
+ #
24
+ # Not implemented:
25
+ # * data
26
+ # * param
27
+ # * include
28
+ # * externalRef
29
+ # * notAllowed
30
+ # * anyName
31
+ # * nsName
32
+ # * except
33
+ # * name
34
+ class RelaxNG
35
+ include Validator
36
+
37
+ INFINITY = 1.0 / 0.0
38
+ EMPTY = Event.new( nil )
39
+ TEXT = [:start_element, "text"]
40
+ attr_accessor :current
41
+ attr_accessor :count
42
+ attr_reader :references
43
+
44
+ # FIXME: Namespaces
45
+ def initialize source
46
+ parser = REXML::Parsers::BaseParser.new( source )
47
+
48
+ @count = 0
49
+ @references = {}
50
+ @root = @current = Sequence.new(self)
51
+ @root.previous = true
52
+ states = [ @current ]
53
+ begin
54
+ event = parser.pull
55
+ case event[0]
56
+ when :start_element
57
+ case event[1]
58
+ when "empty"
59
+ when "element", "attribute", "text", "value"
60
+ states[-1] << event
61
+ when "optional"
62
+ states << Optional.new( self )
63
+ states[-2] << states[-1]
64
+ when "choice"
65
+ states << Choice.new( self )
66
+ states[-2] << states[-1]
67
+ when "oneOrMore"
68
+ states << OneOrMore.new( self )
69
+ states[-2] << states[-1]
70
+ when "zeroOrMore"
71
+ states << ZeroOrMore.new( self )
72
+ states[-2] << states[-1]
73
+ when "group"
74
+ states << Sequence.new( self )
75
+ states[-2] << states[-1]
76
+ when "interleave"
77
+ states << Interleave.new( self )
78
+ states[-2] << states[-1]
79
+ when "mixed"
80
+ states << Interleave.new( self )
81
+ states[-2] << states[-1]
82
+ states[-1] << TEXT
83
+ when "define"
84
+ states << [ event[2]["name"] ]
85
+ when "ref"
86
+ states[-1] << Ref.new( event[2]["name"] )
87
+ when "anyName"
88
+ states << AnyName.new( self )
89
+ states[-2] << states[-1]
90
+ when "nsName"
91
+ when "except"
92
+ when "name"
93
+ when "data"
94
+ when "param"
95
+ when "include"
96
+ when "grammar"
97
+ when "start"
98
+ when "externalRef"
99
+ when "notAllowed"
100
+ end
101
+ when :end_element
102
+ case event[1]
103
+ when "element", "attribute"
104
+ states[-1] << event
105
+ when "zeroOrMore", "oneOrMore", "choice", "optional",
106
+ "interleave", "group", "mixed"
107
+ states.pop
108
+ when "define"
109
+ ref = states.pop
110
+ @references[ ref.shift ] = ref
111
+ #when "empty"
112
+ end
113
+ when :end_document
114
+ states[-1] << event
115
+ when :text
116
+ states[-1] << event
117
+ end
118
+ end while event[0] != :end_document
119
+ end
120
+
121
+ def receive event
122
+ validate( event )
123
+ end
124
+ end
125
+
126
+ class State
127
+ def initialize( context )
128
+ @previous = []
129
+ @events = []
130
+ @current = 0
131
+ @count = context.count += 1
132
+ @references = context.references
133
+ @value = false
134
+ end
135
+
136
+ def reset
137
+ return if @current == 0
138
+ @current = 0
139
+ @events.each {|s| s.reset if s.kind_of? State }
140
+ end
141
+
142
+ def previous=( previous )
143
+ @previous << previous
144
+ end
145
+
146
+ def next( event )
147
+ #print "In next with #{event.inspect}. "
148
+ #puts "Next (#@current) is #{@events[@current]}"
149
+ #p @previous
150
+ return @previous.pop.next( event ) if @events[@current].nil?
151
+ expand_ref_in( @events, @current ) if @events[@current].class == Ref
152
+ if ( @events[@current].kind_of? State )
153
+ @current += 1
154
+ @events[@current-1].previous = self
155
+ return @events[@current-1].next( event )
156
+ end
157
+ #puts "Current isn't a state"
158
+ if ( @events[@current].matches?(event) )
159
+ @current += 1
160
+ if @events[@current].nil?
161
+ #puts "#{inspect[0,5]} 1RETURNING #{@previous.inspect[0,5]}"
162
+ return @previous.pop
163
+ elsif @events[@current].kind_of? State
164
+ @current += 1
165
+ #puts "#{inspect[0,5]} 2RETURNING (#{@current-1}) #{@events[@current-1].inspect[0,5]}; on return, next is #{@events[@current]}"
166
+ @events[@current-1].previous = self
167
+ return @events[@current-1]
168
+ else
169
+ #puts "#{inspect[0,5]} RETURNING self w/ next(#@current) = #{@events[@current]}"
170
+ return self
171
+ end
172
+ else
173
+ return nil
174
+ end
175
+ end
176
+
177
+ def to_s
178
+ # Abbreviated:
179
+ self.class.name =~ /(?:::)(\w)\w+$/
180
+ # Full:
181
+ #self.class.name =~ /(?:::)(\w+)$/
182
+ "#$1.#@count"
183
+ end
184
+
185
+ def inspect
186
+ "< #{to_s} #{@events.collect{|e|
187
+ pre = e == @events[@current] ? '#' : ''
188
+ pre + e.inspect unless self == e
189
+ }.join(', ')} >"
190
+ end
191
+
192
+ def expected
193
+ return [@events[@current]]
194
+ end
195
+
196
+ def <<( event )
197
+ add_event_to_arry( @events, event )
198
+ end
199
+
200
+
201
+ protected
202
+ def expand_ref_in( arry, ind )
203
+ new_events = []
204
+ @references[ arry[ind].to_s ].each{ |evt|
205
+ add_event_to_arry(new_events,evt)
206
+ }
207
+ arry[ind,1] = new_events
208
+ end
209
+
210
+ def add_event_to_arry( arry, evt )
211
+ evt = generate_event( evt )
212
+ if evt.kind_of? String
213
+ arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value
214
+ @value = false
215
+ else
216
+ arry << evt
217
+ end
218
+ end
219
+
220
+ def generate_event( event )
221
+ return event if event.kind_of? State or event.class == Ref
222
+ evt = nil
223
+ arg = nil
224
+ case event[0]
225
+ when :start_element
226
+ case event[1]
227
+ when "element"
228
+ evt = :start_element
229
+ arg = event[2]["name"]
230
+ when "attribute"
231
+ evt = :start_attribute
232
+ arg = event[2]["name"]
233
+ when "text"
234
+ evt = :text
235
+ when "value"
236
+ evt = :text
237
+ @value = true
238
+ end
239
+ when :text
240
+ return event[1]
241
+ when :end_document
242
+ return Event.new( event[0] )
243
+ else # then :end_element
244
+ case event[1]
245
+ when "element"
246
+ evt = :end_element
247
+ when "attribute"
248
+ evt = :end_attribute
249
+ end
250
+ end
251
+ return Event.new( evt, arg )
252
+ end
253
+ end
254
+
255
+
256
+ class Sequence < State
257
+ def matches?(event)
258
+ @events[@current].matches?( event )
259
+ end
260
+ end
261
+
262
+
263
+ class Optional < State
264
+ def next( event )
265
+ if @current == 0
266
+ rv = super
267
+ return rv if rv
268
+ @prior = @previous.pop
269
+ return @prior.next( event )
270
+ end
271
+ super
272
+ end
273
+
274
+ def matches?(event)
275
+ @events[@current].matches?(event) ||
276
+ (@current == 0 and @previous[-1].matches?(event))
277
+ end
278
+
279
+ def expected
280
+ return [ @prior.expected, @events[0] ].flatten if @current == 0
281
+ return [@events[@current]]
282
+ end
283
+ end
284
+
285
+
286
+ class ZeroOrMore < Optional
287
+ def next( event )
288
+ expand_ref_in( @events, @current ) if @events[@current].class == Ref
289
+ if ( @events[@current].matches?(event) )
290
+ @current += 1
291
+ if @events[@current].nil?
292
+ @current = 0
293
+ return self
294
+ elsif @events[@current].kind_of? State
295
+ @current += 1
296
+ @events[@current-1].previous = self
297
+ return @events[@current-1]
298
+ else
299
+ return self
300
+ end
301
+ else
302
+ @prior = @previous.pop
303
+ return @prior.next( event ) if @current == 0
304
+ return nil
305
+ end
306
+ end
307
+
308
+ def expected
309
+ return [ @prior.expected, @events[0] ].flatten if @current == 0
310
+ return [@events[@current]]
311
+ end
312
+ end
313
+
314
+
315
+ class OneOrMore < State
316
+ def initialize context
317
+ super
318
+ @ord = 0
319
+ end
320
+
321
+ def reset
322
+ super
323
+ @ord = 0
324
+ end
325
+
326
+ def next( event )
327
+ expand_ref_in( @events, @current ) if @events[@current].class == Ref
328
+ if ( @events[@current].matches?(event) )
329
+ @current += 1
330
+ @ord += 1
331
+ if @events[@current].nil?
332
+ @current = 0
333
+ return self
334
+ elsif @events[@current].kind_of? State
335
+ @current += 1
336
+ @events[@current-1].previous = self
337
+ return @events[@current-1]
338
+ else
339
+ return self
340
+ end
341
+ else
342
+ return @previous.pop.next( event ) if @current == 0 and @ord > 0
343
+ return nil
344
+ end
345
+ end
346
+
347
+ def matches?( event )
348
+ @events[@current].matches?(event) ||
349
+ (@current == 0 and @ord > 0 and @previous[-1].matches?(event))
350
+ end
351
+
352
+ def expected
353
+ if @current == 0 and @ord > 0
354
+ return [@previous[-1].expected, @events[0]].flatten
355
+ else
356
+ return [@events[@current]]
357
+ end
358
+ end
359
+ end
360
+
361
+
362
+ class Choice < State
363
+ def initialize context
364
+ super
365
+ @choices = []
366
+ end
367
+
368
+ def reset
369
+ super
370
+ @events = []
371
+ @choices.each { |c| c.each { |s| s.reset if s.kind_of? State } }
372
+ end
373
+
374
+ def <<( event )
375
+ add_event_to_arry( @choices, event )
376
+ end
377
+
378
+ def next( event )
379
+ # Make the choice if we haven't
380
+ if @events.size == 0
381
+ c = 0 ; max = @choices.size
382
+ while c < max
383
+ if @choices[c][0].class == Ref
384
+ expand_ref_in( @choices[c], 0 )
385
+ @choices += @choices[c]
386
+ @choices.delete( @choices[c] )
387
+ max -= 1
388
+ else
389
+ c += 1
390
+ end
391
+ end
392
+ @events = @choices.find { |evt| evt[0].matches? event }
393
+ # Remove the references
394
+ # Find the events
395
+ end
396
+ #puts "In next with #{event.inspect}."
397
+ #puts "events is #{@events.inspect}"
398
+ unless @events
399
+ @events = []
400
+ return nil
401
+ end
402
+ #puts "current = #@current"
403
+ super
404
+ end
405
+
406
+ def matches?( event )
407
+ return @events[@current].matches?( event ) if @events.size > 0
408
+ !@choices.find{|evt| evt[0].matches?(event)}.nil?
409
+ end
410
+
411
+ def expected
412
+ #puts "IN CHOICE EXPECTED"
413
+ #puts "EVENTS = #{@events.inspect}"
414
+ return [@events[@current]] if @events.size > 0
415
+ return @choices.collect do |x|
416
+ if x[0].kind_of? State
417
+ x[0].expected
418
+ else
419
+ x[0]
420
+ end
421
+ end.flatten
422
+ end
423
+
424
+ def inspect
425
+ "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' or ')} >"
426
+ end
427
+
428
+ protected
429
+ def add_event_to_arry( arry, evt )
430
+ if evt.kind_of? State or evt.class == Ref
431
+ arry << [evt]
432
+ elsif evt[0] == :text
433
+ if arry[-1] and
434
+ arry[-1][-1].kind_of?( Event ) and
435
+ arry[-1][-1].event_type == :text and @value
436
+
437
+ arry[-1][-1].event_arg = evt[1]
438
+ @value = false
439
+ end
440
+ else
441
+ arry << [] if evt[0] == :start_element
442
+ arry[-1] << generate_event( evt )
443
+ end
444
+ end
445
+ end
446
+
447
+
448
+ class Interleave < Choice
449
+ def initialize context
450
+ super
451
+ @choice = 0
452
+ end
453
+
454
+ def reset
455
+ @choice = 0
456
+ end
457
+
458
+ def next_current( event )
459
+ # Expand references
460
+ c = 0 ; max = @choices.size
461
+ while c < max
462
+ if @choices[c][0].class == Ref
463
+ expand_ref_in( @choices[c], 0 )
464
+ @choices += @choices[c]
465
+ @choices.delete( @choices[c] )
466
+ max -= 1
467
+ else
468
+ c += 1
469
+ end
470
+ end
471
+ @events = @choices[@choice..-1].find { |evt| evt[0].matches? event }
472
+ @current = 0
473
+ if @events
474
+ # reorder the choices
475
+ old = @choices[@choice]
476
+ idx = @choices.index( @events )
477
+ @choices[@choice] = @events
478
+ @choices[idx] = old
479
+ @choice += 1
480
+ end
481
+
482
+ #puts "In next with #{event.inspect}."
483
+ #puts "events is #{@events.inspect}"
484
+ @events = [] unless @events
485
+ end
486
+
487
+
488
+ def next( event )
489
+ # Find the next series
490
+ next_current(event) unless @events[@current]
491
+ return nil unless @events[@current]
492
+
493
+ expand_ref_in( @events, @current ) if @events[@current].class == Ref
494
+ #puts "In next with #{event.inspect}."
495
+ #puts "Next (#@current) is #{@events[@current]}"
496
+ if ( @events[@current].kind_of? State )
497
+ @current += 1
498
+ @events[@current-1].previous = self
499
+ return @events[@current-1].next( event )
500
+ end
501
+ #puts "Current isn't a state"
502
+ return @previous.pop.next( event ) if @events[@current].nil?
503
+ if ( @events[@current].matches?(event) )
504
+ @current += 1
505
+ if @events[@current].nil?
506
+ #puts "#{inspect[0,5]} 1RETURNING self" unless @choices[@choice].nil?
507
+ return self unless @choices[@choice].nil?
508
+ #puts "#{inspect[0,5]} 1RETURNING #{@previous[-1].inspect[0,5]}"
509
+ return @previous.pop
510
+ elsif @events[@current].kind_of? State
511
+ @current += 1
512
+ #puts "#{inspect[0,5]} 2RETURNING (#{@current-1}) #{@events[@current-1].inspect[0,5]}; on return, next is #{@events[@current]}"
513
+ @events[@current-1].previous = self
514
+ return @events[@current-1]
515
+ else
516
+ #puts "#{inspect[0,5]} RETURNING self w/ next(#@current) = #{@events[@current]}"
517
+ return self
518
+ end
519
+ else
520
+ return nil
521
+ end
522
+ end
523
+
524
+ def matches?( event )
525
+ return @events[@current].matches?( event ) if @events[@current]
526
+ !@choices[@choice..-1].find{|evt| evt[0].matches?(event)}.nil?
527
+ end
528
+
529
+ def expected
530
+ #puts "IN CHOICE EXPECTED"
531
+ #puts "EVENTS = #{@events.inspect}"
532
+ return [@events[@current]] if @events[@current]
533
+ return @choices[@choice..-1].collect do |x|
534
+ if x[0].kind_of? State
535
+ x[0].expected
536
+ else
537
+ x[0]
538
+ end
539
+ end.flatten
540
+ end
541
+
542
+ def inspect
543
+ "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' and ')} >"
544
+ end
545
+ end
546
+
547
+ class Ref
548
+ def initialize value
549
+ @value = value
550
+ end
551
+ def to_s
552
+ @value
553
+ end
554
+ def inspect
555
+ "{#{to_s}}"
556
+ end
557
+ end
558
+ end
559
+ end