rhodes 2.0.0.beta1 → 2.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/CHANGELOG +5 -0
  2. data/LICENSE +19 -674
  3. data/Manifest.txt +21 -4
  4. data/README.textile +5 -36
  5. data/Rakefile +5 -0
  6. data/lib/build/jake.rb +3 -1
  7. data/lib/extensions/rexml/rexml/document.rb +2 -0
  8. data/lib/extensions/rexml/rexml/parsers/baseparser.rb +0 -6
  9. data/lib/extensions/rhoxml/rexml/child.rb +96 -0
  10. data/lib/extensions/rhoxml/rexml/document.rb +527 -0
  11. data/lib/extensions/rhoxml/rexml/element.rb +987 -0
  12. data/lib/extensions/rhoxml/rexml/encoding.rb +71 -0
  13. data/lib/extensions/rhoxml/rexml/encodings/US-ASCII.rb +30 -0
  14. data/lib/extensions/rhoxml/rexml/encodings/UTF-16.rb +35 -0
  15. data/lib/extensions/rhoxml/rexml/encodings/UTF-8.rb +18 -0
  16. data/lib/extensions/rhoxml/rexml/namespace.rb +47 -0
  17. data/lib/extensions/rhoxml/rexml/node.rb +76 -0
  18. data/lib/extensions/rhoxml/rexml/parent.rb +166 -0
  19. data/lib/extensions/rhoxml/rexml/parseexception.rb +51 -0
  20. data/lib/extensions/rhoxml/rexml/parsers/baseparser.rb +531 -0
  21. data/lib/extensions/rhoxml/rexml/parsers/treeparser.rb +100 -0
  22. data/lib/extensions/rhoxml/rexml/parsers/xpathparser.rb +698 -0
  23. data/lib/extensions/rhoxml/rexml/set.rb +1274 -0
  24. data/lib/extensions/rhoxml/rexml/source.rb +258 -0
  25. data/lib/extensions/rhoxml/rexml/xmltokens.rb +18 -0
  26. data/lib/extensions/rhoxml/rexml/xpath.rb +77 -0
  27. data/lib/extensions/rhoxml/rexml/xpath_parser.rb +806 -0
  28. data/lib/framework/builtinME.rb +2 -0
  29. data/lib/framework/dateME.rb +5 -1
  30. data/lib/framework/rho/render.rb +10 -2
  31. data/lib/framework/rhom/rhom_object_factory.rb +2 -1
  32. data/lib/framework/singleton.rb +1 -1
  33. data/platform/android/Rhodes/jni/src/rhodes.cpp +2 -4
  34. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +23 -18
  35. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +42 -69
  36. data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +59 -7
  37. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/Camera.java +1 -1
  38. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/Annotation.java +1 -0
  39. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +97 -85
  40. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/SmsUriHandler.java +52 -0
  41. data/platform/android/build/RhodesSRC_build.files +1 -0
  42. data/platform/android/build/android.rake +38 -14
  43. data/platform/bb/RubyVM/RubyVM.jdp +1 -0
  44. data/platform/bb/build/RubyVM_build.files +1 -0
  45. data/platform/bb/build/bb.rake +44 -2
  46. data/platform/bb/rhodes/platform/5.0/com/rho/BrowserAdapter5.java +1 -1
  47. data/platform/bb/rhodes/rhodes.jdp +4 -4
  48. data/platform/bb/rhodes/src/com/rho/BrowserAdapter.java +8 -4
  49. data/platform/bb/rhodes/src/com/rho/rubyext/Alert.java +149 -17
  50. data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +20 -17
  51. data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +54 -28
  52. data/platform/bb/rhodes/src/rhomobile/mapview/Annotation.java +1 -0
  53. data/platform/bb/rhodes/src/rhomobile/mapview/GoogleMapField.java +37 -11
  54. data/platform/bb/rhodes/src/rhomobile/mapview/MapView.java +49 -19
  55. data/platform/bb/rhodes/src/rhomobile/mapview/MapViewScreen.java +6 -0
  56. data/platform/iphone/Classes/MapView/GoogleGeocoder.h +6 -7
  57. data/platform/iphone/Classes/MapView/GoogleGeocoder.m +70 -70
  58. data/platform/iphone/Classes/MapView/MapAnnotation.h +5 -3
  59. data/platform/iphone/Classes/MapView/MapAnnotation.m +10 -8
  60. data/platform/iphone/Classes/MapView/MapViewController.h +13 -10
  61. data/platform/iphone/Classes/MapView/MapViewController.m +131 -72
  62. data/platform/iphone/Classes/Rhodes.h +2 -0
  63. data/platform/iphone/Classes/Rhodes.m +13 -1
  64. data/platform/iphone/Classes/SimpleMainView.m +0 -1
  65. data/platform/iphone/Classes/TabbedMainView.m +5 -6
  66. data/platform/shared/common/RhoTime.h +2 -2
  67. data/platform/shared/common/RhodesApp.cpp +1 -1
  68. data/platform/shared/db/DBAdapter.cpp +6 -0
  69. data/platform/shared/net/CURLNetRequest.cpp +23 -1
  70. data/platform/shared/ruby/thread_win32.c +9 -1
  71. data/platform/shared/rubyJVM/src/com/rho/Capabilities.java +6 -0
  72. data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +1 -1
  73. data/platform/shared/rubyJVM/src/com/rho/sync/ClientRegister.java +1 -1
  74. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubySymbol_Methods.java +6 -1
  75. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubyTime_Methods.java +3 -3
  76. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/InputStreamExecutor.java +1 -1
  77. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyArray.java +15 -3
  78. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyString.java +10 -2
  79. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyTime.java +12 -1
  80. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubyKernelModule.java +18 -9
  81. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubySymbol.java +5 -0
  82. data/platform/shared/rubyJVM/src/org/json/me/JSONArray.java +2 -1
  83. data/platform/shared/unzip/unzip.cpp +1 -1
  84. data/platform/wm/build/wm.rake +27 -6
  85. data/platform/wm/rhodes/Alert.cpp +335 -5
  86. data/platform/wm/rhodes/Alert.h +84 -1
  87. data/platform/wm/rhodes/MainWindow.cpp +28 -6
  88. data/platform/wm/rhodes/MainWindow.h +7 -2
  89. data/platform/wm/rhodes/Rhodes.cpp +23 -0
  90. data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +2 -1
  91. data/platform/wm/rhodes/stdafx.h +1 -0
  92. data/platform/wm/tools/detool/detool.cpp +405 -14
  93. data/rakefile.rb +5 -0
  94. data/res/build-tools/detool.exe +0 -0
  95. data/res/generators/rhogen.rb +2 -0
  96. data/rhodes.gemspec +1 -1
  97. data/spec/framework_spec/app/spec/fixtures/object_values.txt +1 -1
  98. data/spec/framework_spec/app/spec/pagination/fixtures/object_values.txt +1 -1
  99. data/spec/framework_spec/app/spec/rhom_object_spec.rb +12 -12
  100. metadata +23 -6
  101. data/LICENSING_OPTIONS +0 -1
  102. data/platform/bb/build/rhodesApp.rapc +0 -9
  103. data/res/generators/templates/source/source_adapter.rb +0 -48
  104. data/rhobuild.yml +0 -37
@@ -0,0 +1,100 @@
1
+ #require 'rexml/validation/validationexception'
2
+ #require 'rexml/undefinednamespaceexception'
3
+
4
+ module REXML
5
+ module Parsers
6
+ class TreeParser
7
+ def initialize( source, build_context = Document.new )
8
+ @build_context = build_context
9
+ @parser = Parsers::BaseParser.new( source )
10
+ end
11
+
12
+ def add_listener( listener )
13
+ @parser.add_listener( listener )
14
+ end
15
+
16
+ def parse
17
+ tag_stack = []
18
+ in_doctype = false
19
+ entities = nil
20
+ begin
21
+ while true
22
+ event = @parser.pull
23
+ #STDERR.puts "TREEPARSER GOT #{event.inspect}"
24
+ case event[0]
25
+ when :end_document
26
+ unless tag_stack.empty?
27
+ #raise ParseException.new("No close tag for #{tag_stack.inspect}")
28
+ raise ParseException.new("No close tag for #{@build_context.xpath}")
29
+ end
30
+ return
31
+ when :start_element
32
+ tag_stack.push(event[1])
33
+ el = @build_context = @build_context.add_element( event[1] )
34
+ event[2].each do |key, value|
35
+ el.attributes[key] = value #Attribute.new(key,value,self)
36
+ end
37
+ when :end_element
38
+ tag_stack.pop
39
+ @build_context = @build_context.parent
40
+ when :text
41
+ if not in_doctype
42
+ if @build_context[-1].instance_of? Text
43
+ @build_context[-1] << event[1]
44
+ else
45
+ @build_context.add(
46
+ Text.new(event[1], @build_context.whitespace, nil, true)
47
+ ) unless (
48
+ @build_context.ignore_whitespace_nodes and
49
+ event[1].strip.size==0
50
+ )
51
+ end
52
+ end
53
+ when :comment
54
+ c = Comment.new( event[1] )
55
+ @build_context.add( c )
56
+ when :cdata
57
+ c = CData.new( event[1] )
58
+ @build_context.add( c )
59
+ when :processing_instruction
60
+ @build_context.add( Instruction.new( event[1], event[2] ) )
61
+ when :end_doctype
62
+ in_doctype = false
63
+ entities.each { |k,v| entities[k] = @build_context.entities[k].value }
64
+ @build_context = @build_context.parent
65
+ when :start_doctype
66
+ doctype = DocType.new( event[1..-1], @build_context )
67
+ @build_context = doctype
68
+ entities = {}
69
+ in_doctype = true
70
+ when :attlistdecl
71
+ n = AttlistDecl.new( event[1..-1] )
72
+ @build_context.add( n )
73
+ when :externalentity
74
+ n = ExternalEntity.new( event[1] )
75
+ @build_context.add( n )
76
+ when :elementdecl
77
+ n = ElementDecl.new( event[1] )
78
+ @build_context.add(n)
79
+ when :entitydecl
80
+ entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
81
+ @build_context.add(Entity.new(event))
82
+ when :notationdecl
83
+ n = NotationDecl.new( *event[1..-1] )
84
+ @build_context.add( n )
85
+ when :xmldecl
86
+ x = XMLDecl.new( event[1], event[2], event[3] )
87
+ @build_context.add( x )
88
+ end
89
+ end
90
+ #rescue REXML::Validation::ValidationException
91
+ # raise
92
+ #rescue REXML::UndefinedNamespaceException
93
+ # raise
94
+ rescue
95
+ raise ParseException.new( $!.message, @parser.source, @parser, $! )
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,698 @@
1
+ require 'rexml/namespace'
2
+ require 'rexml/xmltokens'
3
+
4
+ module REXML
5
+ module Parsers
6
+ # You don't want to use this class. Really. Use XPath, which is a wrapper
7
+ # for this class. Believe me. You don't want to poke around in here.
8
+ # There is strange, dark magic at work in this code. Beware. Go back! Go
9
+ # back while you still can!
10
+ class XPathParser
11
+ include XMLTokens
12
+ LITERAL = /^'([^']*)'|^"([^"]*)"/u
13
+
14
+ def namespaces=( namespaces )
15
+ #Functions::namespace_context = namespaces
16
+ @namespaces = namespaces
17
+ end
18
+
19
+ def parse path
20
+ path.gsub!(/([\(\[])\s+/, '\1') # Strip ignorable spaces
21
+ path.gsub!( /\s+([\]\)])/, '\1' )
22
+ parsed = []
23
+ path = OrExpr(path, parsed)
24
+ parsed
25
+ end
26
+
27
+ def predicate path
28
+ parsed = []
29
+ Predicate( "[#{path}]", parsed )
30
+ parsed
31
+ end
32
+
33
+ def abbreviate( path )
34
+ path = path.kind_of?(String) ? parse( path ) : path
35
+ string = ""
36
+ document = false
37
+ while path.size > 0
38
+ op = path.shift
39
+ case op
40
+ when :node
41
+ when :attribute
42
+ string << "/" if string.size > 0
43
+ string << "@"
44
+ when :child
45
+ string << "/" if string.size > 0
46
+ when :descendant_or_self
47
+ string << "/"
48
+ when :self
49
+ string << "."
50
+ when :parent
51
+ string << ".."
52
+ when :any
53
+ string << "*"
54
+ when :text
55
+ string << "text()"
56
+ when :following, :following_sibling,
57
+ :ancestor, :ancestor_or_self, :descendant,
58
+ :namespace, :preceding, :preceding_sibling
59
+ string << "/" unless string.size == 0
60
+ string << op.to_s.tr("_", "-")
61
+ string << "::"
62
+ when :qname
63
+ prefix = path.shift
64
+ name = path.shift
65
+ string << prefix+":" if prefix.size > 0
66
+ string << name
67
+ when :predicate
68
+ string << '['
69
+ string << predicate_to_string( path.shift ) {|x| abbreviate( x ) }
70
+ string << ']'
71
+ when :document
72
+ document = true
73
+ when :function
74
+ string << path.shift
75
+ string << "( "
76
+ string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
77
+ string << " )"
78
+ when :literal
79
+ string << %Q{ "#{path.shift}" }
80
+ else
81
+ string << "/" unless string.size == 0
82
+ string << "UNKNOWN("
83
+ string << op.inspect
84
+ string << ")"
85
+ end
86
+ end
87
+ string = "/"+string if document
88
+ return string
89
+ end
90
+
91
+ def expand( path )
92
+ path = path.kind_of?(String) ? parse( path ) : path
93
+ string = ""
94
+ document = false
95
+ while path.size > 0
96
+ op = path.shift
97
+ case op
98
+ when :node
99
+ string << "node()"
100
+ when :attribute, :child, :following, :following_sibling,
101
+ :ancestor, :ancestor_or_self, :descendant, :descendant_or_self,
102
+ :namespace, :preceding, :preceding_sibling, :self, :parent
103
+ string << "/" unless string.size == 0
104
+ string << op.to_s.tr("_", "-")
105
+ string << "::"
106
+ when :any
107
+ string << "*"
108
+ when :qname
109
+ prefix = path.shift
110
+ name = path.shift
111
+ string << prefix+":" if prefix.size > 0
112
+ string << name
113
+ when :predicate
114
+ string << '['
115
+ string << predicate_to_string( path.shift ) { |x| expand(x) }
116
+ string << ']'
117
+ when :document
118
+ document = true
119
+ else
120
+ string << "/" unless string.size == 0
121
+ string << "UNKNOWN("
122
+ string << op.inspect
123
+ string << ")"
124
+ end
125
+ end
126
+ string = "/"+string if document
127
+ return string
128
+ end
129
+
130
+ def predicate_to_string( path, &block )
131
+ string = ""
132
+ case path[0]
133
+ when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union
134
+ op = path.shift
135
+ case op
136
+ when :eq
137
+ op = "="
138
+ when :lt
139
+ op = "<"
140
+ when :gt
141
+ op = ">"
142
+ when :lteq
143
+ op = "<="
144
+ when :gteq
145
+ op = ">="
146
+ when :neq
147
+ op = "!="
148
+ when :union
149
+ op = "|"
150
+ end
151
+ left = predicate_to_string( path.shift, &block )
152
+ right = predicate_to_string( path.shift, &block )
153
+ string << " "
154
+ string << left
155
+ string << " "
156
+ string << op.to_s
157
+ string << " "
158
+ string << right
159
+ string << " "
160
+ when :function
161
+ path.shift
162
+ name = path.shift
163
+ string << name
164
+ string << "( "
165
+ string << predicate_to_string( path.shift, &block )
166
+ string << " )"
167
+ when :literal
168
+ path.shift
169
+ string << " "
170
+ string << path.shift.inspect
171
+ string << " "
172
+ else
173
+ string << " "
174
+ string << yield( path )
175
+ string << " "
176
+ end
177
+ return string.squeeze(" ")
178
+ end
179
+
180
+ private
181
+ #LocationPath
182
+ # | RelativeLocationPath
183
+ # | '/' RelativeLocationPath?
184
+ # | '//' RelativeLocationPath
185
+ def LocationPath path, parsed
186
+ #puts "LocationPath '#{path}'"
187
+ path = path.strip
188
+ if path[0] == ?/
189
+ parsed << :document
190
+ if path[1] == ?/
191
+ parsed << :descendant_or_self
192
+ parsed << :node
193
+ path = path[2..-1]
194
+ else
195
+ path = path[1..-1]
196
+ end
197
+ end
198
+ #puts parsed.inspect
199
+ return RelativeLocationPath( path, parsed ) if path.size > 0
200
+ end
201
+
202
+ #RelativeLocationPath
203
+ # | Step
204
+ # | (AXIS_NAME '::' | '@' | '') AxisSpecifier
205
+ # NodeTest
206
+ # Predicate
207
+ # | '.' | '..' AbbreviatedStep
208
+ # | RelativeLocationPath '/' Step
209
+ # | RelativeLocationPath '//' Step
210
+ AXIS = /^(ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self)::/
211
+ def RelativeLocationPath path, parsed
212
+ #puts "RelativeLocationPath #{path}"
213
+ while path.size > 0
214
+ # (axis or @ or <child::>) nodetest predicate >
215
+ # OR > / Step
216
+ # (. or ..) >
217
+ if path[0] == ?.
218
+ if path[1] == ?.
219
+ parsed << :parent
220
+ parsed << :node
221
+ path = path[2..-1]
222
+ else
223
+ parsed << :self
224
+ parsed << :node
225
+ path = path[1..-1]
226
+ end
227
+ else
228
+ if path[0] == ?@
229
+ #puts "ATTRIBUTE"
230
+ parsed << :attribute
231
+ path = path[1..-1]
232
+ # Goto Nodetest
233
+ elsif path =~ AXIS
234
+ parsed << $1.tr('-','_').intern
235
+ path = $'
236
+ # Goto Nodetest
237
+ else
238
+ parsed << :child
239
+ end
240
+
241
+ #puts "NODETESTING '#{path}'"
242
+ n = []
243
+ path = NodeTest( path, n)
244
+ #puts "NODETEST RETURNED '#{path}'"
245
+
246
+ if path[0] == ?[
247
+ path = Predicate( path, n )
248
+ end
249
+
250
+ parsed.concat(n)
251
+ end
252
+
253
+ if path.size > 0
254
+ if path[0] == ?/
255
+ if path[1] == ?/
256
+ parsed << :descendant_or_self
257
+ parsed << :node
258
+ path = path[2..-1]
259
+ else
260
+ path = path[1..-1]
261
+ end
262
+ else
263
+ return path
264
+ end
265
+ end
266
+ end
267
+ return path
268
+ end
269
+
270
+ # Returns a 1-1 map of the nodeset
271
+ # The contents of the resulting array are either:
272
+ # true/false, if a positive match
273
+ # String, if a name match
274
+ #NodeTest
275
+ # | ('*' | NCNAME ':' '*' | QNAME) NameTest
276
+ # | NODE_TYPE '(' ')' NodeType
277
+ # | PI '(' LITERAL ')' PI
278
+ # | '[' expr ']' Predicate
279
+ NCNAMETEST= /^(#{NCNAME_STR}):\*/u
280
+ QNAME = Namespace::NAMESPLIT
281
+ NODE_TYPE = /^(comment|text|node)\(\s*\)/m
282
+ PI = /^processing-instruction\(/
283
+ def NodeTest path, parsed
284
+ #puts "NodeTest with #{path}"
285
+ res = nil
286
+ case path
287
+ when /^\*/
288
+ path = $'
289
+ parsed << :any
290
+ when NODE_TYPE
291
+ type = $1
292
+ path = $'
293
+ parsed << type.tr('-', '_').intern
294
+ when PI
295
+ path = $'
296
+ literal = nil
297
+ if path !~ /^\s*\)/
298
+ path =~ LITERAL
299
+ literal = $1
300
+ path = $'
301
+ raise ParseException.new("Missing ')' after processing instruction") if path[0] != ?)
302
+ path = path[1..-1]
303
+ end
304
+ parsed << :processing_instruction
305
+ parsed << (literal || '')
306
+ when NCNAMETEST
307
+ #puts "NCNAMETEST"
308
+ prefix = $1
309
+ path = $'
310
+ parsed << :namespace
311
+ parsed << prefix
312
+ when QNAME
313
+ #puts "QNAME"
314
+ prefix = $1
315
+ name = $2
316
+ path = $'
317
+ prefix = "" unless prefix
318
+ parsed << :qname
319
+ parsed << prefix
320
+ parsed << name
321
+ end
322
+ return path
323
+ end
324
+
325
+ # Filters the supplied nodeset on the predicate(s)
326
+ def Predicate path, parsed
327
+ #puts "PREDICATE with #{path}"
328
+ return nil unless path[0] == ?[
329
+ predicates = []
330
+ while path[0] == ?[
331
+ path, expr = get_group(path)
332
+ predicates << expr[1..-2] if expr
333
+ end
334
+ #puts "PREDICATES = #{predicates.inspect}"
335
+ predicates.each{ |pred|
336
+ #puts "ORING #{pred}"
337
+ preds = []
338
+ parsed << :predicate
339
+ parsed << preds
340
+ OrExpr(pred, preds)
341
+ }
342
+ #puts "PREDICATES = #{predicates.inspect}"
343
+ path
344
+ end
345
+
346
+ # The following return arrays of true/false, a 1-1 mapping of the
347
+ # supplied nodeset, except for axe(), which returns a filtered
348
+ # nodeset
349
+
350
+ #| OrExpr S 'or' S AndExpr
351
+ #| AndExpr
352
+ def OrExpr path, parsed
353
+ #puts "OR >>> #{path}"
354
+ n = []
355
+ rest = AndExpr( path, n )
356
+ #puts "OR <<< #{rest}"
357
+ if rest != path
358
+ while rest =~ /^\s*( or )/
359
+ n = [ :or, n, [] ]
360
+ rest = AndExpr( $', n[-1] )
361
+ end
362
+ end
363
+ if parsed.size == 0 and n.size != 0
364
+ parsed.replace(n)
365
+ elsif n.size > 0
366
+ parsed << n
367
+ end
368
+ rest
369
+ end
370
+
371
+ #| AndExpr S 'and' S EqualityExpr
372
+ #| EqualityExpr
373
+ def AndExpr path, parsed
374
+ #puts "AND >>> #{path}"
375
+ n = []
376
+ rest = EqualityExpr( path, n )
377
+ #puts "AND <<< #{rest}"
378
+ if rest != path
379
+ while rest =~ /^\s*( and )/
380
+ n = [ :and, n, [] ]
381
+ #puts "AND >>> #{rest}"
382
+ rest = EqualityExpr( $', n[-1] )
383
+ #puts "AND <<< #{rest}"
384
+ end
385
+ end
386
+ if parsed.size == 0 and n.size != 0
387
+ parsed.replace(n)
388
+ elsif n.size > 0
389
+ parsed << n
390
+ end
391
+ rest
392
+ end
393
+
394
+ #| EqualityExpr ('=' | '!=') RelationalExpr
395
+ #| RelationalExpr
396
+ def EqualityExpr path, parsed
397
+ #puts "EQUALITY >>> #{path}"
398
+ n = []
399
+ rest = RelationalExpr( path, n )
400
+ #puts "EQUALITY <<< #{rest}"
401
+ if rest != path
402
+ while rest =~ /^\s*(!?=)\s*/
403
+ if $1[0] == ?!
404
+ n = [ :neq, n, [] ]
405
+ else
406
+ n = [ :eq, n, [] ]
407
+ end
408
+ rest = RelationalExpr( $', n[-1] )
409
+ end
410
+ end
411
+ if parsed.size == 0 and n.size != 0
412
+ parsed.replace(n)
413
+ elsif n.size > 0
414
+ parsed << n
415
+ end
416
+ rest
417
+ end
418
+
419
+ #| RelationalExpr ('<' | '>' | '<=' | '>=') AdditiveExpr
420
+ #| AdditiveExpr
421
+ def RelationalExpr path, parsed
422
+ #puts "RELATION >>> #{path}"
423
+ n = []
424
+ rest = AdditiveExpr( path, n )
425
+ #puts "RELATION <<< #{rest}"
426
+ if rest != path
427
+ while rest =~ /^\s*([<>]=?)\s*/
428
+ if $1[0] == ?<
429
+ sym = "lt"
430
+ else
431
+ sym = "gt"
432
+ end
433
+ sym << "eq" if $1[-1] == ?=
434
+ n = [ sym.intern, n, [] ]
435
+ rest = AdditiveExpr( $', n[-1] )
436
+ end
437
+ end
438
+ if parsed.size == 0 and n.size != 0
439
+ parsed.replace(n)
440
+ elsif n.size > 0
441
+ parsed << n
442
+ end
443
+ rest
444
+ end
445
+
446
+ #| AdditiveExpr ('+' | S '-') MultiplicativeExpr
447
+ #| MultiplicativeExpr
448
+ def AdditiveExpr path, parsed
449
+ #puts "ADDITIVE >>> #{path}"
450
+ n = []
451
+ rest = MultiplicativeExpr( path, n )
452
+ #puts "ADDITIVE <<< #{rest}"
453
+ if rest != path
454
+ while rest =~ /^\s*(\+| -)\s*/
455
+ if $1[0] == ?+
456
+ n = [ :plus, n, [] ]
457
+ else
458
+ n = [ :minus, n, [] ]
459
+ end
460
+ rest = MultiplicativeExpr( $', n[-1] )
461
+ end
462
+ end
463
+ if parsed.size == 0 and n.size != 0
464
+ parsed.replace(n)
465
+ elsif n.size > 0
466
+ parsed << n
467
+ end
468
+ rest
469
+ end
470
+
471
+ #| MultiplicativeExpr ('*' | S ('div' | 'mod') S) UnaryExpr
472
+ #| UnaryExpr
473
+ def MultiplicativeExpr path, parsed
474
+ #puts "MULT >>> #{path}"
475
+ n = []
476
+ rest = UnaryExpr( path, n )
477
+ #puts "MULT <<< #{rest}"
478
+ if rest != path
479
+ while rest =~ /^\s*(\*| div | mod )\s*/
480
+ if $1[0] == ?*
481
+ n = [ :mult, n, [] ]
482
+ elsif $1.include?( "div" )
483
+ n = [ :div, n, [] ]
484
+ else
485
+ n = [ :mod, n, [] ]
486
+ end
487
+ rest = UnaryExpr( $', n[-1] )
488
+ end
489
+ end
490
+ if parsed.size == 0 and n.size != 0
491
+ parsed.replace(n)
492
+ elsif n.size > 0
493
+ parsed << n
494
+ end
495
+ rest
496
+ end
497
+
498
+ #| '-' UnaryExpr
499
+ #| UnionExpr
500
+ def UnaryExpr path, parsed
501
+ path =~ /^(\-*)/
502
+ path = $'
503
+ if $1 and (($1.size % 2) != 0)
504
+ mult = -1
505
+ else
506
+ mult = 1
507
+ end
508
+ parsed << :neg if mult < 0
509
+
510
+ #puts "UNARY >>> #{path}"
511
+ n = []
512
+ path = UnionExpr( path, n )
513
+ #puts "UNARY <<< #{path}"
514
+ parsed.concat( n )
515
+ path
516
+ end
517
+
518
+ #| UnionExpr '|' PathExpr
519
+ #| PathExpr
520
+ def UnionExpr path, parsed
521
+ #puts "UNION >>> #{path}"
522
+ n = []
523
+ rest = PathExpr( path, n )
524
+ #puts "UNION <<< #{rest}"
525
+ if rest != path
526
+ while rest =~ /^\s*(\|)\s*/
527
+ n = [ :union, n, [] ]
528
+ rest = PathExpr( $', n[-1] )
529
+ end
530
+ end
531
+ if parsed.size == 0 and n.size != 0
532
+ parsed.replace( n )
533
+ elsif n.size > 0
534
+ parsed << n
535
+ end
536
+ rest
537
+ end
538
+
539
+ #| LocationPath
540
+ #| FilterExpr ('/' | '//') RelativeLocationPath
541
+ def PathExpr path, parsed
542
+ path =~ /^\s*/
543
+ path = $'
544
+ #puts "PATH >>> #{path}"
545
+ n = []
546
+ rest = FilterExpr( path, n )
547
+ #puts "PATH <<< '#{rest}'"
548
+ if rest != path
549
+ if rest and rest[0] == ?/
550
+ return RelativeLocationPath(rest, n)
551
+ end
552
+ end
553
+ #puts "BEFORE WITH '#{rest}'"
554
+ rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w_*]/
555
+ parsed.concat(n)
556
+ return rest
557
+ end
558
+
559
+ #| FilterExpr Predicate
560
+ #| PrimaryExpr
561
+ def FilterExpr path, parsed
562
+ #puts "FILTER >>> #{path}"
563
+ n = []
564
+ path = PrimaryExpr( path, n )
565
+ #puts "FILTER <<< #{path}"
566
+ path = Predicate(path, n) if path and path[0] == ?[
567
+ #puts "FILTER <<< #{path}"
568
+ parsed.concat(n)
569
+ path
570
+ end
571
+
572
+ #| VARIABLE_REFERENCE
573
+ #| '(' expr ')'
574
+ #| LITERAL
575
+ #| NUMBER
576
+ #| FunctionCall
577
+ VARIABLE_REFERENCE = /^\$(#{NAME_STR})/u
578
+ NUMBER = /^(\d*\.?\d+)/
579
+ NT = /^comment|text|processing-instruction|node$/
580
+ def PrimaryExpr path, parsed
581
+ arry = []
582
+ case path
583
+ when VARIABLE_REFERENCE
584
+ varname = $1
585
+ path = $'
586
+ parsed << :variable
587
+ parsed << varname
588
+ #arry << @variables[ varname ]
589
+ when /^(\w[-\w]*)(?:\()/
590
+ #puts "PrimaryExpr :: Function >>> #$1 -- '#$''"
591
+ fname = $1
592
+ tmp = $'
593
+ #puts "#{fname} =~ #{NT.inspect}"
594
+ return path if fname =~ NT
595
+ path = tmp
596
+ parsed << :function
597
+ parsed << fname
598
+ path = FunctionCall(path, parsed)
599
+ when NUMBER
600
+ #puts "LITERAL or NUMBER: #$1"
601
+ varname = $1.nil? ? $2 : $1
602
+ path = $'
603
+ parsed << :literal
604
+ parsed << (varname.include?('.') ? varname.to_f : varname.to_i)
605
+ when LITERAL
606
+ #puts "LITERAL or NUMBER: #$1"
607
+ varname = $1.nil? ? $2 : $1
608
+ path = $'
609
+ parsed << :literal
610
+ parsed << varname
611
+ when /^\(/ #/
612
+ path, contents = get_group(path)
613
+ contents = contents[1..-2]
614
+ n = []
615
+ OrExpr( contents, n )
616
+ parsed.concat(n)
617
+ end
618
+ path
619
+ end
620
+
621
+ #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')'
622
+ def FunctionCall rest, parsed
623
+ path, arguments = parse_args(rest)
624
+ argset = []
625
+ for argument in arguments
626
+ args = []
627
+ OrExpr( argument, args )
628
+ argset << args
629
+ end
630
+ parsed << argset
631
+ path
632
+ end
633
+
634
+ # get_group( '[foo]bar' ) -> ['bar', '[foo]']
635
+ def get_group string
636
+ ind = 0
637
+ depth = 0
638
+ st = string[0,1]
639
+ en = (st == "(" ? ")" : "]")
640
+ begin
641
+ case string[ind,1]
642
+ when st
643
+ depth += 1
644
+ when en
645
+ depth -= 1
646
+ end
647
+ ind += 1
648
+ end while depth > 0 and ind < string.length
649
+ return nil unless depth==0
650
+ [string[ind..-1], string[0..ind-1]]
651
+ end
652
+
653
+ def parse_args( string )
654
+ arguments = []
655
+ ind = 0
656
+ inquot = false
657
+ inapos = false
658
+ depth = 1
659
+ begin
660
+ case string[ind]
661
+ when ?"
662
+ inquot = !inquot unless inapos
663
+ when ?'
664
+ inapos = !inapos unless inquot
665
+ else
666
+ unless inquot or inapos
667
+ case string[ind]
668
+ when ?(
669
+ depth += 1
670
+ if depth == 1
671
+ string = string[1..-1]
672
+ ind -= 1
673
+ end
674
+ when ?)
675
+ depth -= 1
676
+ if depth == 0
677
+ s = string[0,ind].strip
678
+ arguments << s unless s == ""
679
+ string = string[ind+1..-1]
680
+ end
681
+ when ?,
682
+ if depth == 1
683
+ s = string[0,ind].strip
684
+ arguments << s unless s == ""
685
+ string = string[ind+1..-1]
686
+ ind = -1
687
+ end
688
+ end
689
+ end
690
+ end
691
+ ind += 1
692
+ end while depth > 0 and ind < string.length
693
+ return nil unless depth==0
694
+ [string,arguments]
695
+ end
696
+ end
697
+ end
698
+ end