xmlparser 0.6.81

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/MANIFEST +112 -0
  2. data/README +697 -0
  3. data/README.ja +789 -0
  4. data/Rakefile +34 -0
  5. data/ext/encoding.h +91 -0
  6. data/ext/xmlparser/mkrf_conf.rb +28 -0
  7. data/ext/xmlparser/xmlparser.c +2226 -0
  8. data/lib/sax.rb +1 -0
  9. data/lib/saxdriver.rb +1 -0
  10. data/lib/wget.rb +47 -0
  11. data/lib/xml/dom/builder-ja.rb +58 -0
  12. data/lib/xml/dom/builder.rb +310 -0
  13. data/lib/xml/dom/core.rb +3276 -0
  14. data/lib/xml/dom/digest.rb +94 -0
  15. data/lib/xml/dom/visitor.rb +182 -0
  16. data/lib/xml/dom2/attr.rb +213 -0
  17. data/lib/xml/dom2/cdatasection.rb +76 -0
  18. data/lib/xml/dom2/characterdata.rb +177 -0
  19. data/lib/xml/dom2/comment.rb +81 -0
  20. data/lib/xml/dom2/core.rb +19 -0
  21. data/lib/xml/dom2/document.rb +317 -0
  22. data/lib/xml/dom2/documentfragment.rb +82 -0
  23. data/lib/xml/dom2/documenttype.rb +102 -0
  24. data/lib/xml/dom2/dombuilder.rb +277 -0
  25. data/lib/xml/dom2/dombuilderfilter.rb +12 -0
  26. data/lib/xml/dom2/domentityresolver.rb +13 -0
  27. data/lib/xml/dom2/domentityresolverimpl.rb +37 -0
  28. data/lib/xml/dom2/domexception.rb +95 -0
  29. data/lib/xml/dom2/domimplementation.rb +61 -0
  30. data/lib/xml/dom2/dominputsource.rb +29 -0
  31. data/lib/xml/dom2/element.rb +533 -0
  32. data/lib/xml/dom2/entity.rb +110 -0
  33. data/lib/xml/dom2/entityreference.rb +107 -0
  34. data/lib/xml/dom2/namednodemap.rb +138 -0
  35. data/lib/xml/dom2/node.rb +587 -0
  36. data/lib/xml/dom2/nodelist.rb +231 -0
  37. data/lib/xml/dom2/notation.rb +86 -0
  38. data/lib/xml/dom2/processinginstruction.rb +155 -0
  39. data/lib/xml/dom2/text.rb +128 -0
  40. data/lib/xml/dom2/xpath.rb +398 -0
  41. data/lib/xml/encoding-ja.rb +42 -0
  42. data/lib/xml/parser.rb +13 -0
  43. data/lib/xml/parserns.rb +236 -0
  44. data/lib/xml/sax.rb +353 -0
  45. data/lib/xml/saxdriver.rb +370 -0
  46. data/lib/xml/xpath.rb +3284 -0
  47. data/lib/xml/xpath.ry +2352 -0
  48. data/lib/xmldigest.rb +1 -0
  49. data/lib/xmltree.rb +1 -0
  50. data/lib/xmltreebuilder.rb +1 -0
  51. data/lib/xmltreevisitor.rb +1 -0
  52. metadata +111 -0
@@ -0,0 +1,370 @@
1
+ ## -*- Ruby -*-
2
+ ## SAX Driver for XML::Parser (experimental)
3
+ ## 1999 by yoshidam
4
+ ##
5
+ ## Limitation:
6
+ ## * AttributeList#getType always returns 'CDATA'.
7
+ ## * DocumentHandler#ignorableWhitespace is never called.
8
+ ## * ErrorHandler#warning and ErrorHandler#error are never called.
9
+ ## * Locator#getLineNumber and Locator#getColumnNumber do not
10
+ ## return the proper value in DocumentHandler#characters method.
11
+ ## * Parser#setLocale is not implemented.
12
+ ## * Parser cannot parse non-local file.
13
+
14
+ require 'xml/parser'
15
+ require 'xml/sax'
16
+
17
+ module XML
18
+ class Parser
19
+ class SAXDriver
20
+ include XML::SAX::Parser
21
+ include XML::SAX::AttributeList
22
+ include XML::SAX::Locator
23
+
24
+ ## very simple URL parser
25
+ class URL
26
+ attr :scheme
27
+ attr :login
28
+ attr :urlpath
29
+
30
+ def initialize(url, url2 = nil)
31
+ @scheme = ''
32
+ @login = ''
33
+ @urlpath = ''
34
+ if url.kind_of?(String) && url2.nil?
35
+ if url =~ /^([a-z0-9\+\-\.]+):\/\/([^\/]+)(\/.*)$/
36
+ @scheme, @login, @urlpath = $1, $2, $3
37
+ else
38
+ url = File::expand_path(url)
39
+ @scheme, @login, @urlpath = "file", "localhost", url
40
+ end
41
+ elsif url.kind_of?(URL) && url2.kind_of?(String)
42
+ if url2 =~ /^([a-z0-9\+\-\.]+):\/\/([^\/]+)(\/.*)$/
43
+ @scheme, @login, @urlpath = $1, $2, $3
44
+ else
45
+ @scheme = url.scheme
46
+ @login = url.login
47
+ if url2 =~ /^\//
48
+ @urlpath = url2
49
+ else
50
+ path = url.urlpath
51
+ path =~ /^([^\#]+)\#?(.*)$/
52
+ path = $1
53
+ path =~ /^([^\?]+)\??(.*)$/
54
+ path = $1
55
+ path =~ /^(.+)\/(.*)/
56
+ path = $1
57
+ @urlpath = File.expand_path(path + '/' + url2)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def to_s
64
+ @scheme + "://" + @login + @urlpath
65
+ end
66
+ end
67
+
68
+ ## All parser events are delegated to SAXDriver
69
+ class SAXParser < XML::Parser
70
+ include XML::SAX::Locator
71
+
72
+ def SAXParser.new(saxdriver, *rest)
73
+ obj = super(*rest)
74
+ obj.setDriver(saxdriver)
75
+ obj
76
+ end
77
+
78
+ def initialize(*args)
79
+ super(*args)
80
+ @publicId = nil
81
+ @systemId = nil
82
+ if self.respond_to?(:setParamEntityParsing)
83
+ self.setParamEntityParsing(PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
84
+ end
85
+ end
86
+
87
+ def setDriver(saxdriver)
88
+ @saxdriver = saxdriver
89
+ end
90
+
91
+ def parse(inputSource)
92
+ @systemId = inputSource.getSystemId
93
+ @saxdriver.pushLocator(self)
94
+ setBase(@systemId)
95
+ super(inputSource.getByteStream.read)
96
+ @saxdriver.popLocator
97
+ end
98
+
99
+ def getPublicId
100
+ @publicId
101
+ end
102
+
103
+ def getSystemId
104
+ @systemId
105
+ end
106
+
107
+ def getLineNumber
108
+ self.line
109
+ end
110
+
111
+ def getColumnNumber
112
+ self.column
113
+ end
114
+
115
+ def startElement(name, attr)
116
+ @saxdriver.startElement(name, attr)
117
+ end
118
+
119
+ def endElement(name)
120
+ @saxdriver.endElement(name)
121
+ end
122
+
123
+ def character(data)
124
+ @saxdriver.character(data)
125
+ end
126
+
127
+ def processingInstruction(target, data)
128
+ @saxdriver.processingInstruction(target, data)
129
+ end
130
+
131
+ def notationDecl(name, base, sysid, pubid)
132
+ @saxdriver.notationDecl(name, base, sysid, pubid)
133
+ end
134
+
135
+ def unparsedEntityDecl(name, base, sysid, pubid, notation)
136
+ @saxdriver.unparsedEntityDecl(name, base, sysid, pubid, notation)
137
+ end
138
+
139
+ def comment(data)
140
+ end
141
+
142
+ def externalEntityRef(context, base, systemId, publicId)
143
+ inputSource = @saxdriver.xmlOpen(base, systemId, publicId)
144
+ encoding = inputSource.getEncoding
145
+ if encoding
146
+ parser = SAXParser.new(@saxdriver, self, context, encoding)
147
+ else
148
+ parser = SAXParser.new(@saxdriver, self, context)
149
+ end
150
+ parser.parse(inputSource)
151
+ parser.done
152
+ end
153
+ end
154
+
155
+ class DummyLocator
156
+ include XML::SAX::Locator
157
+
158
+ def initialize(systemId)
159
+ @systemId = systemId
160
+ end
161
+
162
+ def getPublicId; nil end
163
+ def getSystemId; @systemId end
164
+ def getLineNumber; 1 end
165
+ def getColumnNumber; 1 end
166
+ end
167
+
168
+ ## open stream if it is not opened
169
+ def openInputStream(stream)
170
+ if stream.getByteStream
171
+ return stream
172
+ else stream.getSystemId
173
+ url = URL.new(stream.getSystemId)
174
+ if url.scheme == 'file' && url.login == 'localhost'
175
+ s = open(url.urlpath)
176
+ stream.setByteStream(s)
177
+ return stream
178
+ end
179
+ end
180
+ return nil
181
+ end
182
+ private :openInputStream
183
+
184
+ def xmlOpen(base, systemId, publicId)
185
+ if base.nil? || base == ""
186
+ file = URL.new(systemId)
187
+ else
188
+ file = URL.new(URL.new(base), systemId)
189
+ end
190
+ if !@entityResolver.nil?
191
+ stream = @entityResolver.resolveEntity(file.to_s, publicId)
192
+ return openInputStream(stream) if stream
193
+ end
194
+ if file.scheme == 'file' && file.login == 'localhost'
195
+ stream = open(file.urlpath)
196
+ is = XML::SAX::InputSource.new(stream)
197
+ is.setSystemId(file.to_s)
198
+ is.setPublicId(publicId)
199
+ return is
200
+ end
201
+ end
202
+
203
+ def initialize
204
+ handler = XML::SAX::HandlerBase.new
205
+ @attributes = nil
206
+ @documentHandler = handler
207
+ @dtdHandler = handler
208
+ @errorHandler = handler
209
+ @entityResolver = handler
210
+ @dataBuf = ''
211
+ @locators = []
212
+ end
213
+
214
+ ## implementation of Parser
215
+ def setEntityResolver(handler)
216
+ if !handler.kind_of?(XML::SAX::EntityResolver)
217
+ raise TypeError.new("parameter error")
218
+ end
219
+ @entityResolver = handler
220
+ end
221
+
222
+ ## implementation of Parser
223
+ def setDocumentHandler(handler)
224
+ if !handler.kind_of?(XML::SAX::DocumentHandler)
225
+ raise TypeError.new("parameter error")
226
+ end
227
+ @documentHandler = handler
228
+ end
229
+
230
+ ## implementation of Parser
231
+ def setDTDHandler(handler)
232
+ if !handler.kind_of?(XML::SAX::DTDHandler)
233
+ raise TypeError.new("parameter error")
234
+ end
235
+ @dtdHandler = handler
236
+ end
237
+
238
+ ## implementation of Parser
239
+ def setErrorHandler(handler)
240
+ if !handler.kind_of?(XML::SAX::ErrorHandler)
241
+ raise TypeError.new("parameter error")
242
+ end
243
+ @errorHandler = handler
244
+ end
245
+
246
+ ## implementation of Parser
247
+ def setLocale(locale)
248
+ raise SAXException.new("locale not supported")
249
+ end
250
+
251
+ def flushData
252
+ if @dataBuf.length > 0
253
+ @documentHandler.characters(@dataBuf, 0, @dataBuf.length)
254
+ @dataBuf = ''
255
+ end
256
+ end
257
+ private :flushData
258
+
259
+ def startElement(name, attrs)
260
+ flushData;
261
+ @attributes = attrs
262
+ @documentHandler.startElement(name, self)
263
+ end
264
+
265
+ def character(data)
266
+ @dataBuf << data
267
+ end
268
+
269
+ def endElement(name)
270
+ flushData;
271
+ @documentHandler.endElement(name)
272
+ end
273
+
274
+ def processingInstruction(target, data)
275
+ flushData;
276
+ @documentHandler.processingInstruction(target, data)
277
+ end
278
+
279
+ def notationDecl(name, base, sysid, pubid)
280
+ @dtdHandler.notationDecl(name, pubid, sysid)
281
+ end
282
+
283
+ def unparsedEntityDecl(name, base, sysid, pubid, notation)
284
+ @dtdHandler.unparsedEntityDecl(name, pubid, sysid, notation)
285
+ end
286
+
287
+ ## implementation of AttributeList
288
+ def getLength
289
+ @attributes.length
290
+ end
291
+
292
+ ## implementation of AttributeList
293
+ def getName(pos)
294
+ @attributes.keys[pos]
295
+ end
296
+
297
+ ## implementation of AttributeList
298
+ def getValue(pos)
299
+ if pos.kind_of?(String)
300
+ @attributes[pos]
301
+ else
302
+ @attributes.values[pos]
303
+ end
304
+ end
305
+
306
+ ## implementation of AttributeList
307
+ def getType(pos)
308
+ ## expat cannot get attribyte type
309
+ return "CDATA"
310
+ end
311
+
312
+ ## locator is DummyLoacator or SAXParser
313
+ def pushLocator(locator)
314
+ @locators.push(locator)
315
+ end
316
+
317
+ def popLocator
318
+ @locators.pop
319
+ end
320
+
321
+ ## implementation of Locator
322
+ def getPublicId
323
+ @locators[-1].getPublicId
324
+ end
325
+
326
+ ## implementation of Locator
327
+ def getSystemId
328
+ @locators[-1].getSystemId
329
+ end
330
+
331
+ ## implementation of Locator
332
+ def getLineNumber
333
+ @locators[-1].getLineNumber
334
+ end
335
+
336
+ ## implementation of Locator
337
+ def getColumnNumber
338
+ @locators[-1].getColumnNumber
339
+ end
340
+
341
+ ## implementation of Parser
342
+ def parse(sysid)
343
+ @documentHandler.setDocumentLocator(self)
344
+ if sysid.kind_of?(XML::SAX::InputSource)
345
+ inputSource = openInputStream(sysid.dup)
346
+ else
347
+ inputSource = openInputStream(XML::SAX::InputSource.new(sysid))
348
+ end
349
+ encoding = inputSource.getEncoding
350
+ if encoding
351
+ parser = SAXParser.new(self, encoding)
352
+ else
353
+ parser = SAXParser.new(self)
354
+ end
355
+
356
+ pushLocator(DummyLocator.new(inputSource.getSystemId))
357
+ begin
358
+ @documentHandler.startDocument
359
+ parser.parse(inputSource)
360
+ @documentHandler.endDocument
361
+ rescue XML::Parser::Error
362
+ @errorHandler.fatalError(XML::SAX::SAXParseException.new($!.to_s,
363
+ self))
364
+ rescue
365
+ @errorHandler.fatalError($!)
366
+ end
367
+ end
368
+ end
369
+ end
370
+ end
data/lib/xml/xpath.rb ADDED
@@ -0,0 +1,3284 @@
1
+ #
2
+ # xpath.rb: generated by racc (runtime embedded)
3
+ #
4
+
5
+ ###### racc/parser.rb
6
+
7
+ unless $".index 'racc/parser.rb' then
8
+ $".push 'racc/parser.rb'
9
+
10
+ type.module_eval <<'..end /home/katsu/local/lib/site_ruby/racc/parser.rb modeval..id92db944ac5', '/home/katsu/local/lib/site_ruby/racc/parser.rb', 1
11
+ #
12
+ # parser.rb
13
+ #
14
+ # Copyright (c) 1999,2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
15
+ #
16
+ # This program is free software.
17
+ # You can distribute/modify this program under the terms of
18
+ # the GNU Lesser General Public License version 2 or later.
19
+ #
20
+ # As a special exception, when this code is copied by Racc
21
+ # into a Racc output file, you may use that output file
22
+ # without restriction.
23
+ #
24
+
25
+ module Racc
26
+ class ParseError < StandardError; end
27
+ end
28
+ unless defined? ParseError then
29
+ ParseError = Racc::ParseError
30
+ end
31
+
32
+
33
+ module Racc
34
+
35
+ class Parser
36
+
37
+ private
38
+
39
+
40
+ begin
41
+ if defined? Racc_Debug_Ruby_Parser then
42
+ raise LoadError, 'debug ruby routine'
43
+ end
44
+ require 'racc/cparse'
45
+ unless new.respond_to? :_racc_do_parse_c, true then
46
+ raise LoadError, 'old cparse.so'
47
+ end
48
+ Racc_Main_Parsing_Routine = :_racc_do_parse_c
49
+ Racc_YY_Parse_Method = :_racc_yyparse_c
50
+ rescue LoadError
51
+ Racc_Main_Parsing_Routine = :_racc_do_parse_rb
52
+ Racc_YY_Parse_Method = :_racc_yyparse_rb
53
+ end
54
+
55
+ Racc_ruby_parser_version = '1.3.3'
56
+ Racc_parser_version = Racc_ruby_parser_version
57
+
58
+ def self.racc_runtime_type
59
+ if Racc_Main_Parsing_Routine == :_racc_do_parse_c then
60
+ 'c'
61
+ else
62
+ 'ruby'
63
+ end
64
+ end
65
+
66
+
67
+ def _racc_setup
68
+ t = self.type
69
+
70
+ unless t::Racc_debug_parser then
71
+ @yydebug = false
72
+ end
73
+ @yydebug = false unless defined? @yydebug
74
+
75
+ if @yydebug then
76
+ @racc_debug_out = $stderr unless defined? @racc_debug_out
77
+ @racc_debug_out ||= $stderr
78
+ end
79
+
80
+ arg = t::Racc_arg
81
+ if arg.size < 14 then
82
+ arg[13] = true
83
+ end
84
+ arg
85
+ end
86
+
87
+ def _racc_init_sysvars
88
+ @racc_state = [ 0 ]
89
+ @racc_tstack = []
90
+ @racc_vstack = []
91
+
92
+ @racc_t = nil
93
+ @racc_val = nil
94
+
95
+ @racc_read_next = true
96
+
97
+ @racc_user_yyerror = false
98
+ @racc_error_status = 0
99
+ end
100
+
101
+
102
+ ###
103
+ ### do_parse
104
+ ###
105
+
106
+ def do_parse
107
+ __send__ Racc_Main_Parsing_Routine, _racc_setup(), false
108
+ end
109
+
110
+ def next_token
111
+ raise NotImplementError, "#{self.type}\#next_token must be defined"
112
+ end
113
+
114
+ def _racc_do_parse_rb( arg, in_debug )
115
+ action_table, action_check, action_default, action_pointer,
116
+ goto_table, goto_check, goto_default, goto_pointer,
117
+ nt_base, reduce_table, token_table, shift_n,
118
+ reduce_n, use_result = arg
119
+
120
+ _racc_init_sysvars
121
+ act = i = nil
122
+ nerr = 0
123
+
124
+
125
+ catch( :racc_end_parse ) {
126
+ while true do
127
+
128
+ if i = action_pointer[ @racc_state[-1] ] then
129
+ if @racc_read_next then
130
+ if @racc_t != 0 then # $
131
+ tok, @racc_val = next_token()
132
+ @racc_t = (token_table[tok] or 1) # error token
133
+ racc_read_token( @racc_t, tok, @racc_val ) if @yydebug
134
+
135
+ @racc_read_next = false
136
+ end
137
+ end
138
+ i += @racc_t
139
+ if i >= 0 and act = action_table[i] and
140
+ action_check[i] == @racc_state[-1] then
141
+ ;
142
+ else
143
+ act = action_default[ @racc_state[-1] ]
144
+ end
145
+ else
146
+ act = action_default[ @racc_state[-1] ]
147
+ end
148
+
149
+ while act = _racc_evalact( act, arg ) do end
150
+
151
+ end
152
+ }
153
+ end
154
+
155
+
156
+ ###
157
+ ### yyparse
158
+ ###
159
+
160
+ def yyparse( recv, mid )
161
+ __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true
162
+ end
163
+
164
+ def _racc_yyparse_rb( recv, mid, arg, c_debug )
165
+ action_table, action_check, action_default, action_pointer,
166
+ goto_table, goto_check, goto_default, goto_pointer,
167
+ nt_base, reduce_table, token_table, shift_n,
168
+ reduce_n, use_result, = arg
169
+
170
+ _racc_init_sysvars
171
+ tok = nil
172
+ act = nil
173
+ i = nil
174
+ nerr = 0
175
+
176
+
177
+ catch( :racc_end_parse ) {
178
+ until i = action_pointer[ @racc_state[-1] ] do
179
+ while act = _racc_evalact(
180
+ action_default[ @racc_state[-1] ], arg ) do end
181
+ end
182
+
183
+ recv.__send__( mid ) do |tok, val|
184
+ # $stderr.puts "rd: tok=#{tok}, val=#{val}"
185
+ @racc_val = val
186
+ @racc_t = (token_table[tok] or 1) # error token
187
+ @racc_read_next = false
188
+
189
+ i += @racc_t
190
+ if i >= 0 and act = action_table[i] and
191
+ action_check[i] == @racc_state[-1] then
192
+ # $stderr.puts "01: act=#{act}"
193
+ else
194
+ act = action_default[ @racc_state[-1] ]
195
+ # $stderr.puts "02: act=#{act}"
196
+ # $stderr.puts "curstate=#{@racc_state[-1]}"
197
+ end
198
+
199
+ while act = _racc_evalact( act, arg ) do end
200
+
201
+ while not (i = action_pointer[ @racc_state[-1] ]) or
202
+ not @racc_read_next or
203
+ @racc_t == 0 do # $
204
+ if i and i += @racc_t and
205
+ i >= 0 and
206
+ act = action_table[i] and
207
+ action_check[i] == @racc_state[-1] then
208
+ # $stderr.puts "03: act=#{act}"
209
+ ;
210
+ else
211
+ # $stderr.puts "04: act=#{act}"
212
+ act = action_default[ @racc_state[-1] ]
213
+ end
214
+
215
+ while act = _racc_evalact( act, arg ) do end
216
+ end
217
+ end
218
+ }
219
+ end
220
+
221
+
222
+ ###
223
+ ### common
224
+ ###
225
+
226
+ def _racc_evalact( act, arg )
227
+ # $stderr.puts "ea: act=#{act}"
228
+ action_table, action_check, action_default, action_pointer,
229
+ goto_table, goto_check, goto_default, goto_pointer,
230
+ nt_base, reduce_table, token_table, shift_n,
231
+ reduce_n, use_result, = arg
232
+ nerr = 0 # tmp
233
+
234
+ if act > 0 and act < shift_n then
235
+ #
236
+ # shift
237
+ #
238
+
239
+ if @racc_error_status > 0 then
240
+ @racc_error_status -= 1 unless @racc_t == 1 # error token
241
+ end
242
+
243
+ @racc_vstack.push @racc_val
244
+ @racc_state.push act
245
+ @racc_read_next = true
246
+
247
+ if @yydebug then
248
+ @racc_tstack.push @racc_t
249
+ racc_shift( @racc_t, @racc_tstack, @racc_vstack )
250
+ end
251
+
252
+ elsif act < 0 and act > -reduce_n then
253
+ #
254
+ # reduce
255
+ #
256
+
257
+ code = catch( :racc_jump ) {
258
+ @racc_state.push _racc_do_reduce( arg, act )
259
+ false
260
+ }
261
+ if code then
262
+ case code
263
+ when 1 # yyerror
264
+ @racc_user_yyerror = true # user_yyerror
265
+ return -reduce_n
266
+ when 2 # yyaccept
267
+ return shift_n
268
+ else
269
+ raise RuntimeError, '[Racc Bug] unknown jump code'
270
+ end
271
+ end
272
+
273
+ elsif act == shift_n then
274
+ #
275
+ # accept
276
+ #
277
+
278
+ racc_accept if @yydebug
279
+ throw :racc_end_parse, @racc_vstack[0]
280
+
281
+ elsif act == -reduce_n then
282
+ #
283
+ # error
284
+ #
285
+
286
+ case @racc_error_status
287
+ when 0
288
+ unless arg[21] then # user_yyerror
289
+ nerr += 1
290
+ on_error @racc_t, @racc_val, @racc_vstack
291
+ end
292
+ when 3
293
+ if @racc_t == 0 then # is $
294
+ throw :racc_end_parse, nil
295
+ end
296
+ @racc_read_next = true
297
+ end
298
+ @racc_user_yyerror = false
299
+ @racc_error_status = 3
300
+
301
+ while true do
302
+ if i = action_pointer[ @racc_state[-1] ] then
303
+ i += 1 # error token
304
+ if i >= 0 and
305
+ (act = action_table[i]) and
306
+ action_check[i] == @racc_state[-1] then
307
+ break
308
+ end
309
+ end
310
+
311
+ throw :racc_end_parse, nil if @racc_state.size < 2
312
+ @racc_state.pop
313
+ @racc_vstack.pop
314
+ if @yydebug then
315
+ @racc_tstack.pop
316
+ racc_e_pop( @racc_state, @racc_tstack, @racc_vstack )
317
+ end
318
+ end
319
+
320
+ return act
321
+
322
+ else
323
+ raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}"
324
+ end
325
+
326
+ racc_next_state( @racc_state[-1], @racc_state ) if @yydebug
327
+
328
+ nil
329
+ end
330
+
331
+ def _racc_do_reduce( arg, act )
332
+ action_table, action_check, action_default, action_pointer,
333
+ goto_table, goto_check, goto_default, goto_pointer,
334
+ nt_base, reduce_table, token_table, shift_n,
335
+ reduce_n, use_result, = arg
336
+ state = @racc_state
337
+ vstack = @racc_vstack
338
+ tstack = @racc_tstack
339
+
340
+ i = act * -3
341
+ len = reduce_table[i]
342
+ reduce_to = reduce_table[i+1]
343
+ method_id = reduce_table[i+2]
344
+ void_array = []
345
+
346
+ tmp_t = tstack[ -len, len ] if @yydebug
347
+ tmp_v = vstack[ -len, len ]
348
+ tstack[ -len, len ] = void_array if @yydebug
349
+ vstack[ -len, len ] = void_array
350
+ state[ -len, len ] = void_array
351
+
352
+ # tstack must be updated AFTER method call
353
+ if use_result then
354
+ vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
355
+ else
356
+ vstack.push __send__(method_id, tmp_v, vstack)
357
+ end
358
+ tstack.push reduce_to
359
+
360
+ racc_reduce( tmp_t, reduce_to, tstack, vstack ) if @yydebug
361
+
362
+ k1 = reduce_to - nt_base
363
+ if i = goto_pointer[ k1 ] then
364
+ i += state[-1]
365
+ if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 then
366
+ return curstate
367
+ end
368
+ end
369
+ goto_default[ k1 ]
370
+ end
371
+
372
+ def on_error( t, val, vstack )
373
+ raise ParseError, "\nparse error on value #{val.inspect}"
374
+ end
375
+
376
+ def yyerror
377
+ throw :racc_jump, 1
378
+ end
379
+
380
+ def yyaccept
381
+ throw :racc_jump, 2
382
+ end
383
+
384
+ def yyerrok
385
+ @racc_error_status = 0
386
+ end
387
+
388
+
389
+ # for debugging output
390
+
391
+ def racc_read_token( t, tok, val )
392
+ @racc_debug_out.print 'read '
393
+ @racc_debug_out.print tok.inspect, '(internaly ', racc_token2str(t), ') '
394
+ @racc_debug_out.puts val.inspect
395
+ @racc_debug_out.puts
396
+ end
397
+
398
+ def racc_shift( tok, tstack, vstack )
399
+ @racc_debug_out.puts "shift #{racc_token2str tok}"
400
+ racc_print_stacks tstack, vstack
401
+ @racc_debug_out.puts
402
+ end
403
+
404
+ def racc_reduce( toks, sim, tstack, vstack )
405
+ out = @racc_debug_out
406
+ out.print 'reduce '
407
+ if toks.empty? then
408
+ out.print ' <none>'
409
+ else
410
+ toks.each {|t| out.print ' ', racc_token2str(t) }
411
+ end
412
+ out.puts " --> #{racc_token2str(sim)}"
413
+
414
+ racc_print_stacks tstack, vstack
415
+ @racc_debug_out.puts
416
+ end
417
+
418
+ def racc_accept
419
+ @racc_debug_out.puts 'accept'
420
+ @racc_debug_out.puts
421
+ end
422
+
423
+ def racc_e_pop( state, tstack, vstack )
424
+ @racc_debug_out.puts 'error recovering mode: pop token'
425
+ racc_print_states state
426
+ racc_print_stacks tstack, vstack
427
+ @racc_debug_out.puts
428
+ end
429
+
430
+ def racc_next_state( curstate, state )
431
+ @racc_debug_out.puts "goto #{curstate}"
432
+ racc_print_states state
433
+ @racc_debug_out.puts
434
+ end
435
+
436
+ def racc_print_stacks( t, v )
437
+ out = @racc_debug_out
438
+ out.print ' ['
439
+ t.each_index do |i|
440
+ out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
441
+ end
442
+ out.puts ' ]'
443
+ end
444
+
445
+ def racc_print_states( s )
446
+ out = @racc_debug_out
447
+ out.print ' ['
448
+ s.each {|st| out.print ' ', st }
449
+ out.puts ' ]'
450
+ end
451
+
452
+ def racc_token2str( tok )
453
+ type::Racc_token_to_s_table[tok] or
454
+ raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string"
455
+ end
456
+
457
+ end
458
+
459
+ end
460
+ ..end /home/katsu/local/lib/site_ruby/racc/parser.rb modeval..id92db944ac5
461
+ end # end of racc/parser.rb
462
+
463
+
464
+ #
465
+ # xpath.rb : generated by racc
466
+ #
467
+
468
+ module XPath
469
+
470
+ class Error < StandardError ; end
471
+ class CompileError < Error ; end
472
+ class TypeError < Error ; end
473
+ class NameError < Error ; end
474
+ class ArgumentError < Error ; end
475
+ class InvalidOperation < Error ; end
476
+
477
+
478
+ class XPathProc
479
+
480
+ def initialize(proc, source)
481
+ @proc = proc
482
+ @source = source
483
+ end
484
+
485
+ attr_reader :source
486
+
487
+ def call(context)
488
+ @proc.call context
489
+ end
490
+
491
+ end
492
+
493
+
494
+ def self.compile(src, pattern = false)
495
+ @compiler = Compiler.new unless defined? @compiler
496
+ @compiler.compile src, pattern
497
+ end
498
+
499
+
500
+
501
+ module XPathObject
502
+
503
+ def _type
504
+ type.name.sub(/\A.*::(?:XPath)?(?=[^:]+\z)/, '')
505
+ end
506
+ private :_type
507
+
508
+ def type_error(into)
509
+ raise XPath::TypeError, "failed to convert #{_type} into #{into}"
510
+ end
511
+ private :type_error
512
+
513
+
514
+ def to_str # => to Ruby String
515
+ type_error 'String'
516
+ end
517
+
518
+ def to_f # => to Ruby Float
519
+ type_error 'Float'
520
+ end
521
+
522
+ def true? # => to Ruby Boolean
523
+ type_error 'Boolean'
524
+ end
525
+
526
+ def to_ruby # => to Ruby Object
527
+ self
528
+ end
529
+
530
+ def to_predicate # => to Ruby Float, true or false. shouldn't override.
531
+ true?
532
+ end
533
+
534
+
535
+ def to_string(context) # => to XPath String. shouldn't override.
536
+ context.make_string to_str
537
+ end
538
+
539
+ def to_number(context) # => to XPath Number. shouldn't override.
540
+ context.make_number to_f
541
+ end
542
+
543
+ def to_boolean(context) # => to XPath Boolean. shouldn't override.
544
+ context.make_boolean true?
545
+ end
546
+
547
+
548
+ public
549
+
550
+ # called from compiled XPath expression
551
+
552
+ def ==(other)
553
+ if other.is_a? XPathNodeSet or
554
+ other.is_a? XPathBoolean or other.is_a? XPathNumber then
555
+ other == self
556
+ else
557
+ to_str == other.to_str
558
+ end
559
+ end
560
+
561
+ def <(other)
562
+ if other.is_a? XPathNodeSet then
563
+ other > self
564
+ else
565
+ to_f < other.to_f
566
+ end
567
+ end
568
+
569
+ def >(other)
570
+ if other.is_a? XPathNodeSet then
571
+ other < self
572
+ else
573
+ to_f > other.to_f
574
+ end
575
+ end
576
+
577
+ def <=(other)
578
+ if other.is_a? XPathNodeSet then
579
+ other >= self
580
+ else
581
+ to_f <= other.to_f
582
+ end
583
+ end
584
+
585
+ def >=(other)
586
+ if other.is_a? XPathNodeSet then
587
+ other <= self
588
+ else
589
+ to_f >= other.to_f
590
+ end
591
+ end
592
+
593
+ def **(other)
594
+ type_error 'NodeSet'
595
+ end
596
+
597
+ def predicate(&block)
598
+ type_error 'NodeSet'
599
+ end
600
+
601
+ def at(pos)
602
+ type_error 'NodeSet'
603
+ end
604
+
605
+ def funcall(name) # for XPointer
606
+ raise XPath::NameError, "undefined function `#{name}' for #{_type}"
607
+ end
608
+
609
+ end
610
+
611
+
612
+
613
+
614
+ class XPathBoolean
615
+
616
+ include XPathObject
617
+
618
+ class << self
619
+ attr_reader :instance
620
+ private :new
621
+ end
622
+
623
+ def to_str
624
+ true?.to_s
625
+ end
626
+
627
+ # def to_f
628
+ # def true?
629
+
630
+ def to_ruby
631
+ true?
632
+ end
633
+
634
+ def to_boolean(context)
635
+ self
636
+ end
637
+
638
+ def ==(other)
639
+ true? == other.true?
640
+ end
641
+
642
+ end
643
+
644
+
645
+ class XPathTrueClass < XPathBoolean
646
+
647
+ @instance = new
648
+
649
+ def to_f
650
+ 1.0
651
+ end
652
+
653
+ def true?
654
+ true
655
+ end
656
+
657
+ end
658
+
659
+
660
+ class XPathFalseClass < XPathBoolean
661
+
662
+ @instance = new
663
+
664
+ def to_f
665
+ 0.0
666
+ end
667
+
668
+ def true?
669
+ false
670
+ end
671
+
672
+ end
673
+
674
+
675
+ XPathTrue = XPathTrueClass.instance
676
+ XPathFalse = XPathFalseClass.instance
677
+
678
+
679
+
680
+
681
+ class XPathNumber
682
+
683
+ include XPathObject
684
+
685
+ def initialize(num)
686
+ raise ::TypeError, "must be a Float" unless num.is_a? Float
687
+ @value = num
688
+ end
689
+
690
+ def to_str
691
+ if @value.nan? then
692
+ 'NaN'
693
+ elsif @value.infinite? then
694
+ if @value < 0 then
695
+ '-Infinity'
696
+ else
697
+ 'Infinity'
698
+ end
699
+ else
700
+ sprintf("%.100f", @value).gsub(/\.?0+\z/, '') # enough?
701
+ end
702
+ end
703
+
704
+ def to_f
705
+ @value
706
+ end
707
+
708
+ def true?
709
+ @value != 0.0 and not @value.nan?
710
+ end
711
+
712
+ def to_ruby
713
+ to_f
714
+ end
715
+
716
+ def to_predicate
717
+ to_f
718
+ end
719
+
720
+ def to_number(context)
721
+ self
722
+ end
723
+
724
+
725
+ def ==(other)
726
+ if other.is_a? XPathNodeSet or other.is_a? XPathBoolean then
727
+ other == self
728
+ else
729
+ @value == other.to_f
730
+ end
731
+ end
732
+
733
+ def +(other)
734
+ @value += other.to_f
735
+ self
736
+ end
737
+
738
+ def -(other)
739
+ @value -= other.to_f
740
+ self
741
+ end
742
+
743
+ def *(other)
744
+ @value *= other.to_f
745
+ self
746
+ end
747
+
748
+ def /(other)
749
+ @value /= other.to_f
750
+ self
751
+ end
752
+
753
+ def %(other)
754
+ n = other.to_f
755
+ f = @value % n
756
+ f = -f if @value < 0
757
+ f = -f if n < 0
758
+ @value = f
759
+ self
760
+ end
761
+
762
+ def -@
763
+ @value = -@value
764
+ self
765
+ end
766
+
767
+ def floor
768
+ @value = @value.floor.to_f
769
+ self
770
+ end
771
+
772
+ def ceil
773
+ @value = @value.ceil.to_f
774
+ self
775
+ end
776
+
777
+ def round
778
+ f = @value
779
+ unless f.nan? or f.infinite? then
780
+ if f >= 0.0 then
781
+ @value = f.round.to_f
782
+ elsif f - f.truncate >= -0.5 then
783
+ @value = f.ceil.to_f
784
+ else
785
+ @value = f.floor.to_f
786
+ end
787
+ end
788
+ self
789
+ end
790
+
791
+ end
792
+
793
+
794
+
795
+
796
+ class XPathString
797
+
798
+ include XPathObject
799
+
800
+ def initialize(str)
801
+ raise ::TypeError, "must be a String" unless str.is_a? String
802
+ @value = str
803
+ end
804
+
805
+ def to_str
806
+ @value
807
+ end
808
+
809
+ def to_f
810
+ if /\A\s*(-?\d+\.?\d*)(?:\s|\z)/ =~ @value then
811
+ $1.to_f
812
+ else
813
+ 0.0 / 0.0 # NaN
814
+ end
815
+ end
816
+
817
+ def true?
818
+ not @value.empty?
819
+ end
820
+
821
+ def to_ruby
822
+ to_str
823
+ end
824
+
825
+ def to_string(context)
826
+ self
827
+ end
828
+
829
+
830
+ def concat(s)
831
+ @value = @value + s
832
+ self
833
+ end
834
+
835
+ def start_with?(s)
836
+ /\A#{Regexp.quote(s)}/ =~ @value
837
+ end
838
+
839
+ def contain?(s)
840
+ /#{Regexp.quote(s)}/ =~ @value
841
+ end
842
+
843
+ def substring_before(s)
844
+ if /#{Regexp.quote(s)}/ =~ @value then
845
+ @value = $`
846
+ else
847
+ @value = ''
848
+ end
849
+ self
850
+ end
851
+
852
+ def substring_after(s)
853
+ if /#{Regexp.quote(s)}/ =~ @value then
854
+ @value = $'
855
+ else
856
+ @value = ''
857
+ end
858
+ self
859
+ end
860
+
861
+ def substring(start, len)
862
+ start = start.round.to_f
863
+ if start.infinite? or start.nan? then
864
+ @value = ''
865
+ elsif len then
866
+ len = len.round.to_f
867
+ maxlen = start + len
868
+ len = maxlen - 1.0 if len >= maxlen
869
+ if start <= 1.0 then
870
+ start = 0
871
+ else
872
+ start = start.to_i - 1
873
+ end
874
+ if len.nan? or len < 1.0 then
875
+ @value = ''
876
+ elsif len.infinite? then
877
+ # @value = @value[start..-1]
878
+ /\A[\W\w]{0,#{start}}/ =~ @value
879
+ @value = $'
880
+ else
881
+ # @value = @value[start, len.to_i]
882
+ /\A[\W\w]{0,#{start}}([\W\w]{0,#{len.to_i}})/ =~ @value
883
+ @value = $1
884
+ end
885
+ elsif start > 1.0 then
886
+ # @value = @value[(start-1)..-1]
887
+ /\A[\W\w]{0,#{start.to_i-1}}/ =~ @value
888
+ @value = $'
889
+ end
890
+ raise "BUG" unless @value
891
+ self
892
+ end
893
+
894
+ def size
895
+ @value.gsub(/[^\Wa-zA-Z_\d]/, ' ').size
896
+ end
897
+
898
+ def normalize_space
899
+ @value = @value.strip
900
+ @value.gsub!(/\s+/, ' ')
901
+ self
902
+ end
903
+
904
+ def translate(from, to)
905
+ to = to.split(//)
906
+ h = {}
907
+ from.split(//).each_with_index { |i,n|
908
+ h[i] = to[n] unless h.key? i
909
+ }
910
+ @value = @value.gsub(/[#{Regexp.quote(h.keys.join)}]/) { |s| h[s] }
911
+ self
912
+ end
913
+
914
+ def replace(str)
915
+ @value = str
916
+ self
917
+ end
918
+
919
+ end
920
+
921
+
922
+
923
+
924
+
925
+ class Compiler < Racc::Parser
926
+
927
+ module_eval <<'..end xpath.ry modeval..idcc62899492', 'xpath.ry', 268
928
+
929
+ module CompilePhaseObject
930
+
931
+ def invoke_conv(expr, conv_method)
932
+ return unless conv_method
933
+ if conv_method == '.to_number' or
934
+ conv_method == '.to_string' or
935
+ conv_method == '.to_boolean' then
936
+ expr.push conv_method, '(', nil, ')'
937
+ else
938
+ expr.push conv_method
939
+ end
940
+ end
941
+ private :invoke_conv
942
+
943
+ end
944
+
945
+
946
+ module ConstantObject
947
+
948
+ include CompilePhaseObject
949
+
950
+ def to_string
951
+ StringConstant.new to_str
952
+ end
953
+
954
+ def to_number
955
+ NumberConstant.new self
956
+ end
957
+
958
+ def to_boolean
959
+ if true? then
960
+ ConstantTrue
961
+ else
962
+ ConstantFalse
963
+ end
964
+ end
965
+
966
+ end
967
+
968
+
969
+ module BooleanConstant
970
+
971
+ include ConstantObject
972
+
973
+ def value_type
974
+ :boolean
975
+ end
976
+
977
+ def expr(conv_method = nil)
978
+ if conv_method == '.to_ruby' or conv_method == '.true?' then
979
+ [ true?.to_s ]
980
+ else
981
+ ret = [ nil, '.make_boolean(', true?.to_s, ')' ]
982
+ invoke_conv ret, conv_method unless conv_method == '.to_boolean'
983
+ ret
984
+ end
985
+ end
986
+
987
+ end
988
+
989
+ class ConstantTrueClass < XPathTrueClass
990
+ include BooleanConstant
991
+ @instance = new
992
+ end
993
+
994
+ class ConstantFalseClass < XPathFalseClass
995
+ include BooleanConstant
996
+ @instance = new
997
+ end
998
+
999
+ ConstantTrue = ConstantTrueClass.instance
1000
+ ConstantFalse = ConstantFalseClass.instance
1001
+
1002
+
1003
+
1004
+ class NumberConstant < XPathNumber
1005
+
1006
+ include ConstantObject
1007
+
1008
+ def value_type
1009
+ :number
1010
+ end
1011
+
1012
+ def initialize(src)
1013
+ f = src.to_f
1014
+ if src.is_a? ConstantObject and s = dump_float(f) then
1015
+ src = s
1016
+ end
1017
+ @src = [ src ]
1018
+ @precedence = 1
1019
+ super f
1020
+ end
1021
+
1022
+ attr_reader :precedence
1023
+ protected :precedence
1024
+
1025
+ def to_number
1026
+ self
1027
+ end
1028
+
1029
+
1030
+ def expr(conv_method = nil)
1031
+ @src.collect! { |i|
1032
+ if i.is_a? ConstantObject then
1033
+ i.expr '.to_f'
1034
+ else
1035
+ i
1036
+ end
1037
+ }
1038
+ expr = @src
1039
+ expr.flatten!
1040
+ @src = :draff # for debug
1041
+ unless conv_method == '.to_ruby' or conv_method == '.to_f' then
1042
+ expr[0, 0] = [ nil, '.make_number(' ]
1043
+ expr.push(')')
1044
+ invoke_conv expr, conv_method unless conv_method == '.to_number'
1045
+ end
1046
+ expr
1047
+ end
1048
+
1049
+
1050
+ private
1051
+
1052
+ def dump_float(f)
1053
+ if f.finite? and f == eval(s = f.to_s) then
1054
+ s
1055
+ elsif f.infinite? then
1056
+ if f > 0 then
1057
+ '(1.0 / 0.0)'
1058
+ else
1059
+ '(-1.0 / 0.0)'
1060
+ end
1061
+ elsif f.nan? then
1062
+ '(0.0 / 0.0)'
1063
+ else
1064
+ nil
1065
+ end
1066
+ end
1067
+
1068
+
1069
+ def concat(op, other, prec)
1070
+ @src.unshift('(').push(')') if @precedence < prec
1071
+ if other.precedence < prec then
1072
+ @src.push(op).push('(').concat(other.expr('.to_f')).push(')')
1073
+ else
1074
+ @src.push(op).concat(other.expr('.to_f'))
1075
+ end
1076
+ @precedence = prec
1077
+ end
1078
+
1079
+
1080
+ public
1081
+
1082
+ def self.def_arithmetic_operator(op, precedence)
1083
+ module_eval <<_, __FILE__, __LINE__ + 1
1084
+ def #{op}(other)
1085
+ super other
1086
+ if s = dump_float(@value) then
1087
+ @src.clear
1088
+ @src.push s
1089
+ else
1090
+ concat ' #{op} ', other, #{precedence}
1091
+ end
1092
+ self
1093
+ end
1094
+ _
1095
+ end
1096
+
1097
+ def_arithmetic_operator '+', 0
1098
+ def_arithmetic_operator '-', 0
1099
+ def_arithmetic_operator '*', 1
1100
+ def_arithmetic_operator '/', 1
1101
+
1102
+ class << self
1103
+ undef def_arithmetic_operator
1104
+ end
1105
+
1106
+ def %(other)
1107
+ orig = @value
1108
+ super other
1109
+ if s = dump_float(@value) then
1110
+ @src.clear
1111
+ @src.push s
1112
+ else
1113
+ f = other.to_f
1114
+ other = -other if orig % f == -@value
1115
+ concat ' % ', other, 1
1116
+ end
1117
+ self
1118
+ end
1119
+
1120
+ def -@
1121
+ super
1122
+ if s = dump_float(@value) then
1123
+ @src.clear
1124
+ @src.push s
1125
+ else
1126
+ if @src.size == 1 then
1127
+ @src.unshift '-'
1128
+ else
1129
+ @src.unshift('-(').push(')')
1130
+ end
1131
+ @precedence = 1
1132
+ end
1133
+ self
1134
+ end
1135
+
1136
+ end
1137
+
1138
+
1139
+
1140
+ class StringConstant < XPathString
1141
+
1142
+ include ConstantObject
1143
+
1144
+ def value_type
1145
+ :string
1146
+ end
1147
+
1148
+ def to_string
1149
+ self
1150
+ end
1151
+
1152
+ def expr(conv_method = nil)
1153
+ if conv_method == '.to_ruby' or conv_method == '.to_str' then
1154
+ [ @value.dump ]
1155
+ else
1156
+ ret = [ nil, '.make_string(', @value.dump, ')' ]
1157
+ invoke_conv ret, conv_method unless conv_method == '.to_string'
1158
+ ret
1159
+ end
1160
+ end
1161
+
1162
+ end
1163
+
1164
+
1165
+
1166
+ class Expression
1167
+
1168
+ include CompilePhaseObject
1169
+
1170
+ def initialize(expr)
1171
+ if expr.is_a? ConstantObject then
1172
+ @value = expr
1173
+ else
1174
+ raise "BUG" unless expr.is_a? Array
1175
+ @value = nil
1176
+ @valuetype = nil
1177
+ @expr = expr
1178
+ end
1179
+ @unary = true
1180
+ end
1181
+
1182
+ attr_reader :value
1183
+
1184
+
1185
+ def value_type
1186
+ if @value then
1187
+ @value.value_type
1188
+ else
1189
+ @valuetype
1190
+ end
1191
+ end
1192
+
1193
+
1194
+ def unarize
1195
+ unless @unary then
1196
+ @expr.unshift('(').push(')')
1197
+ @unary = true
1198
+ end
1199
+ self
1200
+ end
1201
+
1202
+
1203
+ def self.def_comparison_operator(name, op)
1204
+ module_eval <<_, __FILE__, __LINE__ + 1
1205
+ def #{name}(other)
1206
+ if @value and other.value then
1207
+ if @value #{op} other.value then
1208
+ @value = ConstantTrue
1209
+ else
1210
+ @value = ConstantFalse
1211
+ end
1212
+ @unary = true
1213
+ else
1214
+ @expr = expr.push(' #{op} ').concat(other.expr)
1215
+ @valuetype = :ruby_boolean
1216
+ @unary = false
1217
+ end
1218
+ self
1219
+ end
1220
+ _
1221
+ end
1222
+
1223
+ def self.def_arithmetic_operator(*ops)
1224
+ ops.each { |op|
1225
+ module_eval <<_, __FILE__, __LINE__ + 1
1226
+ def #{op}(other)
1227
+ if @value and other.value then
1228
+ @value = @value.to_number #{op} other.value.to_number
1229
+ else
1230
+ @expr = expr('.to_number').push(' #{op} ')
1231
+ # not 'to_number', for a little speed up :-)
1232
+ @expr.concat other.expr('.to_f')
1233
+ @valuetype = :number
1234
+ @unary = false
1235
+ end
1236
+ self
1237
+ end
1238
+ _
1239
+ }
1240
+ end
1241
+
1242
+ def_comparison_operator 'eq', '=='
1243
+ def_comparison_operator 'neq', '!='
1244
+ def_comparison_operator 'lt', '<'
1245
+ def_comparison_operator 'gt', '>'
1246
+ def_comparison_operator 'le', '<='
1247
+ def_comparison_operator 'ge', '>='
1248
+ def_arithmetic_operator '+', '-', '*', '/', '%'
1249
+
1250
+ class << self
1251
+ undef def_comparison_operator
1252
+ undef def_arithmetic_operator
1253
+ end
1254
+
1255
+ def -@
1256
+ if @value then
1257
+ @value = -@value.to_number
1258
+ else
1259
+ unarize
1260
+ @expr = expr('.to_number').unshift('-')
1261
+ end
1262
+ self
1263
+ end
1264
+
1265
+ def logical_or(other)
1266
+ if @value and @value.true? then
1267
+ @value = ConstantTrue
1268
+ @unary = true
1269
+ @expr = @valuetype = nil
1270
+ else
1271
+ @expr = expr('.true?').push(' || ').concat(other.expr('.true?'))
1272
+ @valuetype = :ruby_boolean
1273
+ @unary = false
1274
+ end
1275
+ self
1276
+ end
1277
+
1278
+ def logical_and(other)
1279
+ if @value and not @value.true? then
1280
+ @value = ConstantFalse
1281
+ @unary = true
1282
+ @expr = @valuetype = nil
1283
+ else
1284
+ @expr = expr('.true?').push(' && ').concat(other.expr('.true?'))
1285
+ @valuetype = :ruby_boolean
1286
+ @unary = false
1287
+ end
1288
+ self
1289
+ end
1290
+
1291
+ def **(other)
1292
+ @expr = expr.push(' ** ').concat(other.expr)
1293
+ @valuetype = nil
1294
+ @unary = false
1295
+ self
1296
+ end
1297
+
1298
+
1299
+ def add_predicate(pred)
1300
+ unarize
1301
+ @expr = expr.concat(pred)
1302
+ @valuetype = nil
1303
+ self
1304
+ end
1305
+
1306
+ def <<(other)
1307
+ path = other.expr
1308
+ path.shift # nil
1309
+ path.shift # .to_nodeset
1310
+ add_predicate path
1311
+ end
1312
+
1313
+ def add_step(axis)
1314
+ add_predicate [ ".step(:#{axis.tr('-','_')})" ]
1315
+ end
1316
+
1317
+
1318
+ def expr(conv_method = nil)
1319
+ if @value then
1320
+ ret = @value.expr(conv_method)
1321
+ @value = nil
1322
+ elsif @valuetype == :ruby_boolean then
1323
+ ret = @expr
1324
+ unless conv_method == '.to_ruby' or conv_method == '.true?' then
1325
+ ret[0, 0] = [ nil, '.make_boolean(' ]
1326
+ ret.push ')'
1327
+ invoke_conv ret, conv_method unless conv_method == '.to_boolean'
1328
+ end
1329
+ elsif @valuetype == :number and conv_method == '.to_number' then
1330
+ ret = @expr
1331
+ elsif @valuetype == :string and conv_method == '.to_string' then
1332
+ ret = @expr
1333
+ elsif @valuetype == :boolean and conv_method == '.to_boolean' then
1334
+ ret = @expr
1335
+ else
1336
+ if conv_method then
1337
+ unarize
1338
+ invoke_conv @expr, conv_method
1339
+ end
1340
+ ret = @expr
1341
+ end
1342
+ @expr = :draff # for debug
1343
+ ret
1344
+ end
1345
+
1346
+ end
1347
+
1348
+
1349
+
1350
+ class LocationPath
1351
+
1352
+ include CompilePhaseObject
1353
+
1354
+ def initialize
1355
+ @root = false
1356
+ @steps = [] # [ axis, [ tests ], predicates ]
1357
+ end
1358
+
1359
+ attr_reader :root, :steps
1360
+ protected :root, :steps
1361
+
1362
+ def absolute!
1363
+ @root = true
1364
+ self
1365
+ end
1366
+
1367
+
1368
+ def add_step(axis, nodetype = false, localpart = false,
1369
+ namespace = false, predicate = nil)
1370
+ if nodetype == false and localpart == false and namespace == false then
1371
+ append_step axis, [], predicate
1372
+ else
1373
+ append_step axis, [ [ nodetype, localpart, namespace ] ], predicate
1374
+ end
1375
+ self
1376
+ end
1377
+
1378
+
1379
+ def <<(other)
1380
+ raise "BUG" if other.root
1381
+ other = other.steps
1382
+ other.each { |step|
1383
+ if step[0] then
1384
+ append_step(*step)
1385
+ else
1386
+ add_predicate(step[2])
1387
+ end
1388
+ }
1389
+ self
1390
+ end
1391
+
1392
+
1393
+ def add_predicate(pred)
1394
+ @steps.push [ nil, nil, pred ]
1395
+ self
1396
+ end
1397
+
1398
+
1399
+ def **(other)
1400
+ unless other.is_a? LocationPath then
1401
+ ret = nil
1402
+ else
1403
+ othersteps = other.steps
1404
+ size = @steps.size
1405
+ unless size == othersteps.size then
1406
+ othersize = othersteps.size
1407
+ if size >= othersize then
1408
+ ret = (@steps[0, othersize] == othersize and self)
1409
+ else
1410
+ ret = (othersteps[0, size] == @steps and other)
1411
+ end
1412
+ else
1413
+ last = @steps.pop
1414
+ otherlast = othersteps.pop
1415
+ if @steps == othersteps and mix_step(last, otherlast) then
1416
+ ret = self
1417
+ else
1418
+ ret = nil
1419
+ end
1420
+ @steps.push last
1421
+ othersteps.push otherlast
1422
+ end
1423
+ end
1424
+ ret or Expression.new(expr) ** other
1425
+ end
1426
+
1427
+
1428
+ private
1429
+
1430
+ UnifiableAxes = {
1431
+ 'descendant' => {
1432
+ 'descendant-or-self' => 'descendant',
1433
+ },
1434
+ 'descendant-or-self' => {
1435
+ 'child' => 'descendant',
1436
+ 'descendant' => 'descendant',
1437
+ 'descendant-or-self' => 'descendant-or-self',
1438
+ },
1439
+ 'ancestor' => {
1440
+ 'ancestor-or-self' => 'ancestor',
1441
+ },
1442
+ 'ancestor-or-self' => {
1443
+ 'parent' => 'ancestor',
1444
+ 'ancestor' => 'ancestor',
1445
+ 'ancestor-or-self' => 'ancestor-or-self',
1446
+ },
1447
+ 'following-sibling' => {
1448
+ 'following-sibling' => 'following-sibling',
1449
+ },
1450
+ 'preceding-sibling' => {
1451
+ 'preceding-sibling' => 'preceding-sibling',
1452
+ },
1453
+ 'following' => {
1454
+ 'following' => 'following',
1455
+ 'following-sibling' => 'following',
1456
+ },
1457
+ 'preceding' => {
1458
+ 'preceding' => 'preceding',
1459
+ 'preceding-sibling' => 'preceding',
1460
+ },
1461
+ 'child' => {
1462
+ 'following-sibling' => 'child',
1463
+ 'preceding-sibling' => 'child',
1464
+ },
1465
+ }
1466
+ UnifiableAxes.default = {}
1467
+
1468
+
1469
+ def append_step(axis, test, predicate)
1470
+ lastaxis, lasttest, lastpred = laststep = @steps.last
1471
+ if axis == 'self' and test.empty? then
1472
+ @steps.push [ nil, nil, predicate ] if predicate
1473
+ elsif lastaxis and lasttest.empty? and
1474
+ not lastpred and not predicate and
1475
+ w = UnifiableAxes[lastaxis][axis] then
1476
+ laststep[0] = w
1477
+ laststep[1] = test
1478
+ else
1479
+ @steps.push [ axis, test, predicate ]
1480
+ end
1481
+ end
1482
+
1483
+
1484
+ def mix_step(step, other)
1485
+ if step[0] and step[0] == other[0] and step[2] == other[2] then
1486
+ step[1].concat other[1]
1487
+ step
1488
+ else
1489
+ nil
1490
+ end
1491
+ end
1492
+
1493
+
1494
+ public
1495
+
1496
+ def expr(conv_method = nil)
1497
+ if @root then
1498
+ expr = [ nil, '.root_nodeset' ]
1499
+ else
1500
+ expr = [ nil, '.to_nodeset' ]
1501
+ end
1502
+ @steps.each { |axis,test,predicate|
1503
+ if axis.nil? then # predicate only
1504
+ expr.concat predicate
1505
+ elsif test.empty? and not predicate then
1506
+ expr.push ".select_all(:#{axis.tr('-','_')})"
1507
+ else
1508
+ expr.push ".step(:#{axis.tr('-','_')})"
1509
+ if test.empty? then
1510
+ expr.push ' { |n| n.select_all'
1511
+ else
1512
+ expr.push ' { |n| n.select { |i| '
1513
+ test.each { |nodetype,localpart,namespace|
1514
+ if nodetype then
1515
+ expr.push "i.node_type == :#{nodetype.tr('-','_')}", ' && '
1516
+ end
1517
+ if localpart then
1518
+ expr.push "i.name_localpart == #{localpart.dump}", ' && '
1519
+ end
1520
+ if namespace.nil? then
1521
+ expr.push 'i.namespace_uri.nil?', ' && '
1522
+ elsif namespace then
1523
+ namespace = namespace.dump
1524
+ expr.push('i.namespace_uri == ', nil,
1525
+ ".get_namespace(#{namespace})", ' && ')
1526
+ end
1527
+ expr[-1] = ' or '
1528
+ }
1529
+ expr[-1] = ' }'
1530
+ end
1531
+ expr.concat predicate if predicate
1532
+ expr.push ' }'
1533
+ end
1534
+ }
1535
+ @steps = :draff # for debug
1536
+ invoke_conv expr, conv_method
1537
+ expr
1538
+ end
1539
+
1540
+
1541
+ def value_type
1542
+ nil
1543
+ end
1544
+
1545
+ def value
1546
+ nil
1547
+ end
1548
+
1549
+ def unarize
1550
+ self
1551
+ end
1552
+
1553
+ def self.redirect_to_expr(*ops)
1554
+ ops.each { |op|
1555
+ name = op
1556
+ name = op[1..-1] if op[0] == ?.
1557
+ module_eval <<_, __FILE__, __LINE__ + 1
1558
+ def #{name}(arg) ; Expression.new(expr) #{op} arg ; end
1559
+ _
1560
+ }
1561
+ end
1562
+
1563
+ redirect_to_expr('.eq', '.neq', '.lt', '.gt', '.le', '.ge',
1564
+ '+', '-', '*', '/', '%', '.logical_or', '.logical_and')
1565
+
1566
+ class << self
1567
+ undef redirect_to_expr
1568
+ end
1569
+
1570
+ def -@
1571
+ -Expression.new(expr)
1572
+ end
1573
+
1574
+ end
1575
+
1576
+
1577
+
1578
+
1579
+ Delim = '\\s\\(\\)\\[\\]\\.@,\\/\\|\\*\\+"\'=!<>:'
1580
+ Name = "[^-#{Delim}][^#{Delim}]*"
1581
+
1582
+ Operator = {
1583
+ '@' => true, '::' => true, '(' => true, '[' => true,
1584
+ :MUL => true, 'and' => true, 'or' => true, 'mod' => true, 'div' => true,
1585
+ '/' => true, '//' => true, '|' => true, '+' => true,
1586
+ '-' => true, '=' => true, '!=' => true, '<' => true,
1587
+ '<=' => true, '>' => true, '>=' => true,
1588
+ ':' => false
1589
+ # ':' '*' => '*' must not be a MultiplyOperator
1590
+ # ':' 'and' => 'and' must be a OperatorName
1591
+ }
1592
+
1593
+ NodeType = {
1594
+ 'comment' => true,
1595
+ 'text' => true,
1596
+ 'processing-instruction' => true,
1597
+ 'node' => true,
1598
+ }
1599
+
1600
+
1601
+ private
1602
+
1603
+ def axis?(s)
1604
+ /\A[-a-zA-Z]+\z/ =~ s
1605
+ end
1606
+
1607
+ def nodetype?(s)
1608
+ NodeType.key? s
1609
+ end
1610
+
1611
+ def tokenize(src)
1612
+ token = []
1613
+ src.scan(/(\.\.?|\/\/?|::?|!=|[<>]=?|[-()\[\].@,|+=*])|
1614
+ ("[^"]*"|'[^']*')|(\d+\.?\d*)|
1615
+ (\$?#{Name}(?::#{Name})?)|
1616
+ \s+|./ox) { |delim,literal,number,name| #/
1617
+ if delim then
1618
+ if delim == '*' then
1619
+ delim = :MUL if (prev = token[-1]) and not Operator.key? prev[0]
1620
+ elsif delim == '::' then
1621
+ prev = token[-1]
1622
+ if prev and prev[0] == :Name and axis? prev[1] then
1623
+ prev[0] = :AxisName
1624
+ end
1625
+ elsif delim == '(' then
1626
+ if (prev = token[-1]) and prev[0] == :Name then
1627
+ if nodetype? prev[1] then
1628
+ prev[0] = :NodeType
1629
+ else
1630
+ prev[0] = :FuncName
1631
+ end
1632
+ end
1633
+ end
1634
+ token.push [ delim, delim ]
1635
+ elsif name then
1636
+ prev = token[-1]
1637
+ if name[0] == ?$ then
1638
+ name[0,1] = ''
1639
+ token.push [ :Variable, name ]
1640
+ elsif Operator.key? name and
1641
+ (prev = token[-1]) and not Operator[prev[0]] then
1642
+ token.push [ name, name ]
1643
+ else
1644
+ token.push [ :Name, name ]
1645
+ end
1646
+ elsif number then
1647
+ number << '.0' unless number.include? ?.
1648
+ token.push [ :Number, number ]
1649
+ elsif literal then
1650
+ literal.chop!
1651
+ literal[0,1] = ''
1652
+ token.push [ :Literal, literal ]
1653
+ else
1654
+ s = $&.strip
1655
+ token.push [ s, s ] unless s.empty?
1656
+ end
1657
+ }
1658
+ token
1659
+ end
1660
+
1661
+
1662
+ public
1663
+
1664
+ def compile(src, pattern = false)
1665
+ @token = tokenize(src)
1666
+ @token.push [ false, :end ]
1667
+ @token.each { |i| p i } if @yydebug
1668
+ @token.reverse!
1669
+ @token.push [ :PATTERN, nil ] if pattern
1670
+ @context = 'context0'
1671
+ ret = do_parse
1672
+ ret = ret.unshift("proc { |context0| ").push(" }").join
1673
+ print ">>>>\n", ret, "\n<<<<\n" if @yydebug
1674
+ XPathProc.new eval(ret), src
1675
+ end
1676
+
1677
+
1678
+ def initialize(debug = false)
1679
+ super()
1680
+ @yydebug = debug
1681
+ end
1682
+
1683
+
1684
+ private
1685
+
1686
+ def next_token
1687
+ @token.pop
1688
+ end
1689
+
1690
+
1691
+ def is_xpointer?
1692
+ false
1693
+ end
1694
+
1695
+
1696
+ def on_error(*args) # tok, val, values
1697
+ raise CompileError, 'parse error'
1698
+ end
1699
+
1700
+
1701
+ ..end xpath.ry modeval..idcc62899492
1702
+
1703
+ ##### racc 1.3.3 generates ###
1704
+
1705
+ racc_reduce_table = [
1706
+ 0, 0, :racc_error,
1707
+ 0, 39, :_reduce_1,
1708
+ 1, 39, :_reduce_2,
1709
+ 2, 39, :_reduce_3,
1710
+ 1, 41, :_reduce_none,
1711
+ 3, 41, :_reduce_5,
1712
+ 3, 40, :_reduce_6,
1713
+ 3, 40, :_reduce_7,
1714
+ 3, 40, :_reduce_8,
1715
+ 3, 40, :_reduce_9,
1716
+ 3, 40, :_reduce_10,
1717
+ 3, 40, :_reduce_11,
1718
+ 3, 40, :_reduce_12,
1719
+ 3, 40, :_reduce_13,
1720
+ 3, 40, :_reduce_14,
1721
+ 3, 40, :_reduce_15,
1722
+ 2, 40, :_reduce_16,
1723
+ 3, 40, :_reduce_17,
1724
+ 3, 40, :_reduce_18,
1725
+ 3, 40, :_reduce_19,
1726
+ 3, 40, :_reduce_20,
1727
+ 1, 40, :_reduce_none,
1728
+ 1, 40, :_reduce_none,
1729
+ 3, 40, :_reduce_23,
1730
+ 3, 40, :_reduce_24,
1731
+ 1, 43, :_reduce_25,
1732
+ 3, 43, :_reduce_26,
1733
+ 1, 43, :_reduce_27,
1734
+ 1, 43, :_reduce_28,
1735
+ 1, 43, :_reduce_29,
1736
+ 2, 43, :_reduce_30,
1737
+ 4, 45, :_reduce_31,
1738
+ 0, 47, :_reduce_32,
1739
+ 1, 47, :_reduce_33,
1740
+ 3, 47, :_reduce_34,
1741
+ 0, 48, :_reduce_35,
1742
+ 0, 49, :_reduce_36,
1743
+ 5, 46, :_reduce_37,
1744
+ 1, 42, :_reduce_38,
1745
+ 2, 42, :_reduce_39,
1746
+ 2, 42, :_reduce_40,
1747
+ 1, 42, :_reduce_none,
1748
+ 1, 44, :_reduce_42,
1749
+ 3, 44, :_reduce_43,
1750
+ 3, 44, :_reduce_44,
1751
+ 0, 51, :_reduce_45,
1752
+ 0, 52, :_reduce_46,
1753
+ 8, 44, :_reduce_47,
1754
+ 1, 50, :_reduce_48,
1755
+ 1, 50, :_reduce_49,
1756
+ 3, 50, :_reduce_50,
1757
+ 0, 55, :_reduce_none,
1758
+ 2, 55, :_reduce_52,
1759
+ 1, 54, :_reduce_53,
1760
+ 1, 54, :_reduce_54,
1761
+ 3, 54, :_reduce_55,
1762
+ 4, 54, :_reduce_56,
1763
+ 0, 56, :_reduce_none,
1764
+ 1, 56, :_reduce_none,
1765
+ 0, 53, :_reduce_59,
1766
+ 1, 53, :_reduce_60,
1767
+ 2, 53, :_reduce_none ]
1768
+
1769
+ racc_reduce_n = 62
1770
+
1771
+ racc_shift_n = 100
1772
+
1773
+ racc_action_table = [
1774
+ -1, 75, 87, 16, 19, 16, 19, 82, 2, 9,
1775
+ 12, 9, 12, 42, 44, 47, 48, 5, 7, 10,
1776
+ 14, 18, 43, 20, 1, 4, 71, 2, 84, 16,
1777
+ 19, 26, 83, 47, 48, 9, 12, 7, 10, 14,
1778
+ 18, 26, 20, 1, 4, 46, 2, 26, 16, 19,
1779
+ 52, 49, 54, 50, 9, 12, 7, 10, 14, 18,
1780
+ -32, 20, 1, 4, -32, 2, 88, 16, 19, 47,
1781
+ 48, 47, 48, 9, 12, 7, 10, 14, 18, -32,
1782
+ 20, 1, 4, -32, 2, 90, 16, 19, 47, 48,
1783
+ 43, 79, 9, 12, 7, 10, 14, 18, 78, 20,
1784
+ 1, 4, 95, 2, 26, 16, 19, 96, 37, 83,
1785
+ 99, 9, 12, 7, 10, 14, 18, nil, 20, 1,
1786
+ 4, nil, 2, nil, 16, 19, nil, nil, nil, nil,
1787
+ 9, 12, 7, 10, 14, 18, nil, 20, 1, 4,
1788
+ nil, 2, nil, 16, 19, nil, nil, nil, nil, 9,
1789
+ 12, 7, 10, 14, 18, nil, 20, 1, 4, nil,
1790
+ 2, nil, 16, 19, nil, nil, nil, nil, 9, 12,
1791
+ 7, 10, 14, 18, nil, 20, 1, 4, nil, 2,
1792
+ nil, 16, 19, nil, nil, nil, nil, 9, 12, 7,
1793
+ 10, 14, 18, nil, 20, 1, 4, nil, 2, nil,
1794
+ 16, 19, nil, nil, nil, nil, 9, 12, 7, 10,
1795
+ 14, 18, nil, 20, 1, 4, nil, 2, nil, 16,
1796
+ 19, nil, nil, nil, nil, 9, 12, 7, 10, 14,
1797
+ 18, nil, 20, 1, 4, nil, 2, nil, 16, 19,
1798
+ nil, nil, nil, nil, 9, 12, 7, 10, 14, 18,
1799
+ nil, 20, 1, 4, nil, 2, nil, 16, 19, nil,
1800
+ nil, nil, nil, 9, 12, 7, 10, 14, 18, nil,
1801
+ 20, 1, 4, nil, 2, nil, 16, 19, nil, nil,
1802
+ nil, nil, 9, 12, 7, 10, 14, 18, nil, 20,
1803
+ 1, 4, nil, 2, nil, 16, 19, nil, nil, nil,
1804
+ nil, 9, 12, 7, 10, 14, 18, nil, 20, 1,
1805
+ 4, nil, 2, nil, 16, 19, nil, nil, nil, nil,
1806
+ 9, 12, 7, 10, 14, 18, nil, 20, 1, 4,
1807
+ nil, 2, nil, 16, 19, nil, nil, nil, nil, 9,
1808
+ 12, 7, 10, 14, 18, nil, 20, 1, 4, nil,
1809
+ 2, nil, 16, 19, nil, nil, nil, nil, 9, 12,
1810
+ 7, 10, 14, 18, nil, 20, 1, 4, nil, 2,
1811
+ nil, 16, 19, nil, nil, nil, nil, 9, 12, 7,
1812
+ 10, 14, 18, nil, 20, 1, 4, nil, 2, nil,
1813
+ 16, 19, nil, nil, nil, nil, 9, 12, 7, 10,
1814
+ 14, 18, nil, 20, 1, 4, 16, 19, nil, 16,
1815
+ 19, nil, 9, 12, nil, 9, 12, 26, nil, 29,
1816
+ 31, 33, 35, 23, 25, 27, 28, 30, 32, 34,
1817
+ 36, 24, 7, 10, 7, 10, 26, 81, 29, 31,
1818
+ 33, 16, 19, 16, 19, 16, 19, 9, 12, 9,
1819
+ 12, 9, 12, 26, nil, 29, 31, 33, 35, 23,
1820
+ 25, 27, 28, 30, 32, 34, 36, 24, 26, nil,
1821
+ 29, 31, 33, 35, 23, 25, 27, 28, 30, 32,
1822
+ 34, 36, 24, 26, nil, 29, 31, 33, 35, 23,
1823
+ 25, 27, 28, 30, 32, 34, 36, 24, 26, nil,
1824
+ 29, 31, 33, 35, 23, 25, 27, 28, 30, 32,
1825
+ 34, 36, 24, 26, nil, 29, 31, 33, 35, 23,
1826
+ 25, 27, 28, 30, 32, 34, 36, 26, nil, 29,
1827
+ 31, 33, 35, 23, 25, 27, 28, 30, 32, 34,
1828
+ 26, nil, 29, 31, 33, 35, 23, 25, 27, 28,
1829
+ 30, 26, nil, 29, 31, 33, 35, 23, 25, 27,
1830
+ 28, 30, 16, 19, -59, -59, nil, -59, 9, 12,
1831
+ 16, 19, nil, nil, nil, nil, 9, 12, 26, nil,
1832
+ 29, 31, 33, 35, 23, 26, nil, 29, 31, 33,
1833
+ 35, 23, 26, nil, 29, 31, 33, 35, 23, 26,
1834
+ nil, 29, 31, 33, 35, 23, 26, nil, 29, 31,
1835
+ 33 ]
1836
+
1837
+ racc_action_check = [
1838
+ 0, 47, 75, 48, 48, 47, 47, 54, 0, 48,
1839
+ 48, 47, 47, 11, 11, 40, 40, 0, 0, 0,
1840
+ 0, 0, 11, 0, 0, 0, 38, 23, 70, 0,
1841
+ 0, 61, 70, 13, 13, 0, 0, 23, 23, 23,
1842
+ 23, 22, 23, 23, 23, 12, 37, 63, 23, 23,
1843
+ 15, 15, 21, 15, 23, 23, 37, 37, 37, 37,
1844
+ 37, 37, 37, 37, 37, 94, 78, 37, 37, 41,
1845
+ 41, 74, 74, 37, 37, 94, 94, 94, 94, 94,
1846
+ 94, 94, 94, 94, 36, 79, 94, 94, 72, 72,
1847
+ 80, 50, 94, 94, 36, 36, 36, 36, 49, 36,
1848
+ 36, 36, 89, 35, 65, 36, 36, 93, 4, 97,
1849
+ 98, 36, 36, 35, 35, 35, 35, nil, 35, 35,
1850
+ 35, nil, 34, nil, 35, 35, nil, nil, nil, nil,
1851
+ 35, 35, 34, 34, 34, 34, nil, 34, 34, 34,
1852
+ nil, 83, nil, 34, 34, nil, nil, nil, nil, 34,
1853
+ 34, 83, 83, 83, 83, nil, 83, 83, 83, nil,
1854
+ 73, nil, 83, 83, nil, nil, nil, nil, 83, 83,
1855
+ 73, 73, 73, 73, nil, 73, 73, 73, nil, 33,
1856
+ nil, 73, 73, nil, nil, nil, nil, 73, 73, 33,
1857
+ 33, 33, 33, nil, 33, 33, 33, nil, 32, nil,
1858
+ 33, 33, nil, nil, nil, nil, 33, 33, 32, 32,
1859
+ 32, 32, nil, 32, 32, 32, nil, 18, nil, 32,
1860
+ 32, nil, nil, nil, nil, 32, 32, 18, 18, 18,
1861
+ 18, nil, 18, 18, 18, nil, 31, nil, 18, 18,
1862
+ nil, nil, nil, nil, 18, 18, 31, 31, 31, 31,
1863
+ nil, 31, 31, 31, nil, 30, nil, 31, 31, nil,
1864
+ nil, nil, nil, 31, 31, 30, 30, 30, 30, nil,
1865
+ 30, 30, 30, nil, 2, nil, 30, 30, nil, nil,
1866
+ nil, nil, 30, 30, 2, 2, 2, 2, nil, 2,
1867
+ 2, 2, nil, 29, nil, 2, 2, nil, nil, nil,
1868
+ nil, 2, 2, 29, 29, 29, 29, nil, 29, 29,
1869
+ 29, nil, 25, nil, 29, 29, nil, nil, nil, nil,
1870
+ 29, 29, 25, 25, 25, 25, nil, 25, 25, 25,
1871
+ nil, 26, nil, 25, 25, nil, nil, nil, nil, 25,
1872
+ 25, 26, 26, 26, 26, nil, 26, 26, 26, nil,
1873
+ 27, nil, 26, 26, nil, nil, nil, nil, 26, 26,
1874
+ 27, 27, 27, 27, nil, 27, 27, 27, nil, 28,
1875
+ nil, 27, 27, nil, nil, nil, nil, 27, 27, 28,
1876
+ 28, 28, 28, nil, 28, 28, 28, nil, 24, nil,
1877
+ 28, 28, nil, nil, nil, nil, 28, 28, 24, 24,
1878
+ 24, 24, nil, 24, 24, 24, 44, 44, nil, 24,
1879
+ 24, nil, 44, 44, nil, 24, 24, 53, nil, 53,
1880
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
1881
+ 53, 53, 71, 71, 5, 5, 67, 53, 67, 67,
1882
+ 67, 42, 42, 71, 71, 5, 5, 42, 42, 71,
1883
+ 71, 5, 5, 3, nil, 3, 3, 3, 3, 3,
1884
+ 3, 3, 3, 3, 3, 3, 3, 3, 69, nil,
1885
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
1886
+ 69, 69, 69, 92, nil, 92, 92, 92, 92, 92,
1887
+ 92, 92, 92, 92, 92, 92, 92, 92, 86, nil,
1888
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
1889
+ 86, 86, 86, 56, nil, 56, 56, 56, 56, 56,
1890
+ 56, 56, 56, 56, 56, 56, 56, 68, nil, 68,
1891
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
1892
+ 66, nil, 66, 66, 66, 66, 66, 66, 66, 66,
1893
+ 66, 64, nil, 64, 64, 64, 64, 64, 64, 64,
1894
+ 64, 64, 7, 7, 7, 7, nil, 7, 7, 7,
1895
+ 10, 10, nil, nil, nil, nil, 10, 10, 57, nil,
1896
+ 57, 57, 57, 57, 57, 60, nil, 60, 60, 60,
1897
+ 60, 60, 59, nil, 59, 59, 59, 59, 59, 62,
1898
+ nil, 62, 62, 62, 62, 62, 55, nil, 55, 55,
1899
+ 55 ]
1900
+
1901
+ racc_action_pointer = [
1902
+ 0, nil, 266, 451, 87, 416, nil, 533, nil, nil,
1903
+ 541, -5, 8, 15, nil, 19, nil, nil, 209, nil,
1904
+ nil, 52, 39, 19, 380, 304, 323, 342, 361, 285,
1905
+ 247, 228, 190, 171, 114, 95, 76, 38, 24, nil,
1906
+ -3, 51, 412, nil, 377, nil, nil, -24, -26, 65,
1907
+ 70, nil, nil, 415, 7, 604, 511, 576, nil, 590,
1908
+ 583, 29, 597, 45, 549, 102, 538, 434, 525, 466,
1909
+ 6, 414, 70, 152, 53, -19, nil, nil, 35, 62,
1910
+ 63, nil, nil, 133, nil, nil, 496, nil, nil, 80,
1911
+ nil, nil, 481, 79, 57, nil, nil, 83, 88, nil ]
1912
+
1913
+ racc_action_default = [
1914
+ -59, -28, -59, -2, -62, -59, -42, -38, -21, -60,
1915
+ -59, -22, -62, -41, -25, -62, -48, -29, -59, -49,
1916
+ -27, -62, -16, -59, -59, -59, -59, -59, -59, -59,
1917
+ -59, -59, -59, -59, -59, -59, -59, -59, -3, -4,
1918
+ -39, -40, -59, -35, -59, -30, -61, -59, -59, -54,
1919
+ -62, -51, -53, -62, -62, -15, -6, -10, -20, -11,
1920
+ -12, -17, -13, -18, -8, -19, -9, -14, -7, -33,
1921
+ -62, -59, -23, -59, -24, -62, -43, -44, -62, -57,
1922
+ -50, -26, 100, -59, -31, -5, -36, -45, -55, -62,
1923
+ -58, -52, -34, -62, -59, -56, -37, -46, -62, -47 ]
1924
+
1925
+ racc_goto_table = [
1926
+ 3, 45, 22, 39, 70, 40, 76, 77, 41, 73,
1927
+ 38, 93, 21, 94, 98, 51, 80, 89, 53, nil,
1928
+ nil, nil, nil, 55, 56, 57, 58, 59, 60, 61,
1929
+ 62, 63, 64, 65, 66, 67, 68, nil, nil, nil,
1930
+ 72, nil, 74, nil, nil, nil, nil, nil, nil, nil,
1931
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
1932
+ nil, 97, nil, nil, nil, nil, nil, nil, nil, 85,
1933
+ 91, nil, nil, 86, nil, nil, nil, nil, nil, nil,
1934
+ nil, nil, nil, 92 ]
1935
+
1936
+ racc_goto_check = [
1937
+ 2, 8, 2, 4, 9, 6, 12, 12, 6, 10,
1938
+ 3, 11, 1, 13, 14, 16, 17, 18, 2, nil,
1939
+ nil, nil, nil, 2, 2, 2, 2, 2, 2, 2,
1940
+ 2, 2, 2, 2, 2, 2, 2, nil, nil, nil,
1941
+ 6, nil, 6, nil, nil, nil, nil, nil, nil, nil,
1942
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
1943
+ nil, 9, nil, nil, nil, nil, nil, nil, nil, 4,
1944
+ 8, nil, nil, 2, nil, nil, nil, nil, nil, nil,
1945
+ nil, nil, nil, 2 ]
1946
+
1947
+ racc_goto_pointer = [
1948
+ nil, 12, 0, 5, -2, nil, -2, nil, -10, -33,
1949
+ -34, -75, -41, -74, -83, nil, 0, -35, -62 ]
1950
+
1951
+ racc_goto_default = [
1952
+ nil, nil, 69, nil, 8, 11, 13, 17, nil, nil,
1953
+ nil, nil, 6, nil, nil, 15, nil, nil, nil ]
1954
+
1955
+ racc_token_table = {
1956
+ false => 0,
1957
+ Object.new => 1,
1958
+ "|" => 2,
1959
+ :NEG => 3,
1960
+ :MUL => 4,
1961
+ "div" => 5,
1962
+ "mod" => 6,
1963
+ "+" => 7,
1964
+ "-" => 8,
1965
+ "<" => 9,
1966
+ ">" => 10,
1967
+ "<=" => 11,
1968
+ ">=" => 12,
1969
+ "=" => 13,
1970
+ "!=" => 14,
1971
+ "and" => 15,
1972
+ "or" => 16,
1973
+ :PATTERN => 17,
1974
+ "/" => 18,
1975
+ "//" => 19,
1976
+ :Variable => 20,
1977
+ "(" => 21,
1978
+ ")" => 22,
1979
+ :Literal => 23,
1980
+ :Number => 24,
1981
+ :FuncName => 25,
1982
+ "," => 26,
1983
+ "[" => 27,
1984
+ "]" => 28,
1985
+ "." => 29,
1986
+ ".." => 30,
1987
+ "*" => 31,
1988
+ :Name => 32,
1989
+ ":" => 33,
1990
+ :NodeType => 34,
1991
+ "@" => 35,
1992
+ :AxisName => 36,
1993
+ "::" => 37 }
1994
+
1995
+ racc_use_result_var = false
1996
+
1997
+ racc_nt_base = 38
1998
+
1999
+ Racc_arg = [
2000
+ racc_action_table,
2001
+ racc_action_check,
2002
+ racc_action_default,
2003
+ racc_action_pointer,
2004
+ racc_goto_table,
2005
+ racc_goto_check,
2006
+ racc_goto_default,
2007
+ racc_goto_pointer,
2008
+ racc_nt_base,
2009
+ racc_reduce_table,
2010
+ racc_token_table,
2011
+ racc_shift_n,
2012
+ racc_reduce_n,
2013
+ racc_use_result_var ]
2014
+
2015
+ Racc_debug_parser = false
2016
+
2017
+ ##### racc system variables end #####
2018
+
2019
+ # reduce 0 omitted
2020
+
2021
+ module_eval <<'.,.,', 'xpath.ry', 27
2022
+ def _reduce_1( val, _values)
2023
+ []
2024
+ end
2025
+ .,.,
2026
+
2027
+ module_eval <<'.,.,', 'xpath.ry', 30
2028
+ def _reduce_2( val, _values)
2029
+ expr = val[0].expr('.to_ruby')
2030
+ expr.collect! { |i| i or @context }
2031
+ expr
2032
+ end
2033
+ .,.,
2034
+
2035
+ module_eval <<'.,.,', 'xpath.ry', 36
2036
+ def _reduce_3( val, _values)
2037
+ expr = val[0].expr('.to_ruby')
2038
+ expr.collect! { |i| i or @context }
2039
+ expr
2040
+ end
2041
+ .,.,
2042
+
2043
+ # reduce 4 omitted
2044
+
2045
+ module_eval <<'.,.,', 'xpath.ry', 43
2046
+ def _reduce_5( val, _values)
2047
+ val[0] ** val[2]
2048
+ end
2049
+ .,.,
2050
+
2051
+ module_eval <<'.,.,', 'xpath.ry', 46
2052
+ def _reduce_6( val, _values)
2053
+ val[0].logical_or val[2]
2054
+ end
2055
+ .,.,
2056
+
2057
+ module_eval <<'.,.,', 'xpath.ry', 48
2058
+ def _reduce_7( val, _values)
2059
+ val[0].logical_and val[2]
2060
+ end
2061
+ .,.,
2062
+
2063
+ module_eval <<'.,.,', 'xpath.ry', 50
2064
+ def _reduce_8( val, _values)
2065
+ val[0].eq val[2]
2066
+ end
2067
+ .,.,
2068
+
2069
+ module_eval <<'.,.,', 'xpath.ry', 52
2070
+ def _reduce_9( val, _values)
2071
+ val[0].neq val[2]
2072
+ end
2073
+ .,.,
2074
+
2075
+ module_eval <<'.,.,', 'xpath.ry', 54
2076
+ def _reduce_10( val, _values)
2077
+ val[0].lt val[2]
2078
+ end
2079
+ .,.,
2080
+
2081
+ module_eval <<'.,.,', 'xpath.ry', 56
2082
+ def _reduce_11( val, _values)
2083
+ val[0].gt val[2]
2084
+ end
2085
+ .,.,
2086
+
2087
+ module_eval <<'.,.,', 'xpath.ry', 58
2088
+ def _reduce_12( val, _values)
2089
+ val[0].le val[2]
2090
+ end
2091
+ .,.,
2092
+
2093
+ module_eval <<'.,.,', 'xpath.ry', 60
2094
+ def _reduce_13( val, _values)
2095
+ val[0].ge val[2]
2096
+ end
2097
+ .,.,
2098
+
2099
+ module_eval <<'.,.,', 'xpath.ry', 62
2100
+ def _reduce_14( val, _values)
2101
+ val[0] + val[2]
2102
+ end
2103
+ .,.,
2104
+
2105
+ module_eval <<'.,.,', 'xpath.ry', 64
2106
+ def _reduce_15( val, _values)
2107
+ val[0] - val[2]
2108
+ end
2109
+ .,.,
2110
+
2111
+ module_eval <<'.,.,', 'xpath.ry', 66
2112
+ def _reduce_16( val, _values)
2113
+ -val[1]
2114
+ end
2115
+ .,.,
2116
+
2117
+ module_eval <<'.,.,', 'xpath.ry', 68
2118
+ def _reduce_17( val, _values)
2119
+ val[0] * val[2]
2120
+ end
2121
+ .,.,
2122
+
2123
+ module_eval <<'.,.,', 'xpath.ry', 70
2124
+ def _reduce_18( val, _values)
2125
+ val[0] / val[2]
2126
+ end
2127
+ .,.,
2128
+
2129
+ module_eval <<'.,.,', 'xpath.ry', 72
2130
+ def _reduce_19( val, _values)
2131
+ val[0] % val[2]
2132
+ end
2133
+ .,.,
2134
+
2135
+ module_eval <<'.,.,', 'xpath.ry', 75
2136
+ def _reduce_20( val, _values)
2137
+ # Why `**' is used for unionizing node-sets is that its
2138
+ # precedence is higher than any other binary operators
2139
+ # in Ruby.
2140
+ val[0] ** val[2]
2141
+ end
2142
+ .,.,
2143
+
2144
+ # reduce 21 omitted
2145
+
2146
+ # reduce 22 omitted
2147
+
2148
+ module_eval <<'.,.,', 'xpath.ry', 83
2149
+ def _reduce_23( val, _values)
2150
+ val[0] << val[2]
2151
+ end
2152
+ .,.,
2153
+
2154
+ module_eval <<'.,.,', 'xpath.ry', 85
2155
+ def _reduce_24( val, _values)
2156
+ val[0].add_step('descendant-or-self') << val[2]
2157
+ end
2158
+ .,.,
2159
+
2160
+ module_eval <<'.,.,', 'xpath.ry', 89
2161
+ def _reduce_25( val, _values)
2162
+ Expression.new [ nil,'.get_variable(',val[0].dump,')' ]
2163
+ end
2164
+ .,.,
2165
+
2166
+ module_eval <<'.,.,', 'xpath.ry', 92
2167
+ def _reduce_26( val, _values)
2168
+ val[1].unarize
2169
+ end
2170
+ .,.,
2171
+
2172
+ module_eval <<'.,.,', 'xpath.ry', 94
2173
+ def _reduce_27( val, _values)
2174
+ Expression.new StringConstant.new(val[0])
2175
+ end
2176
+ .,.,
2177
+
2178
+ module_eval <<'.,.,', 'xpath.ry', 96
2179
+ def _reduce_28( val, _values)
2180
+ Expression.new NumberConstant.new(val[0])
2181
+ end
2182
+ .,.,
2183
+
2184
+ module_eval <<'.,.,', 'xpath.ry', 98
2185
+ def _reduce_29( val, _values)
2186
+ Expression.new val[0]
2187
+ end
2188
+ .,.,
2189
+
2190
+ module_eval <<'.,.,', 'xpath.ry', 100
2191
+ def _reduce_30( val, _values)
2192
+ val[0].add_predicate val[1]
2193
+ end
2194
+ .,.,
2195
+
2196
+ module_eval <<'.,.,', 'xpath.ry', 104
2197
+ def _reduce_31( val, _values)
2198
+ val[2][0,0] = [ nil, ".funcall(#{val[0].dump}" ]
2199
+ val[2].push(')')
2200
+ end
2201
+ .,.,
2202
+
2203
+ module_eval <<'.,.,', 'xpath.ry', 109
2204
+ def _reduce_32( val, _values)
2205
+ []
2206
+ end
2207
+ .,.,
2208
+
2209
+ module_eval <<'.,.,', 'xpath.ry', 111
2210
+ def _reduce_33( val, _values)
2211
+ val[0].expr.unshift ', '
2212
+ end
2213
+ .,.,
2214
+
2215
+ module_eval <<'.,.,', 'xpath.ry', 113
2216
+ def _reduce_34( val, _values)
2217
+ val[0].push(', ').concat(val[2].expr)
2218
+ end
2219
+ .,.,
2220
+
2221
+ module_eval <<'.,.,', 'xpath.ry', 117
2222
+ def _reduce_35( val, _values)
2223
+ c = @context
2224
+ @context = c.succ
2225
+ c
2226
+ end
2227
+ .,.,
2228
+
2229
+ module_eval <<'.,.,', 'xpath.ry', 123
2230
+ def _reduce_36( val, _values)
2231
+ c = @context
2232
+ @context = _values[-2]
2233
+ c
2234
+ end
2235
+ .,.,
2236
+
2237
+ module_eval <<'.,.,', 'xpath.ry', 129
2238
+ def _reduce_37( val, _values)
2239
+ expr = val[2]
2240
+ valuetype = expr.value_type
2241
+ value = expr.value
2242
+ if valuetype == :number then
2243
+ if value then
2244
+ f = value.to_f
2245
+ if f > 0 and f.truncate == f then
2246
+ [ ".at(#{f.to_i})" ]
2247
+ else
2248
+ [ '.at(0)' ] # clear
2249
+ end
2250
+ else
2251
+ expr.expr('.to_f').
2252
+ unshift('.at(').push(')')
2253
+ end
2254
+ elsif value then
2255
+ if value.true? then
2256
+ []
2257
+ else
2258
+ [ '.at(0)' ] # clear
2259
+ end
2260
+ else
2261
+ c = val[3]
2262
+ if valuetype == :ruby_boolean then
2263
+ conv = '.true?'
2264
+ else
2265
+ conv = '.to_predicate'
2266
+ end
2267
+ a = expr.expr(conv)
2268
+ a.collect! { |i| i or c }
2269
+ a.unshift(".predicate { |#{c}| ").push(' }')
2270
+ end
2271
+ end
2272
+ .,.,
2273
+
2274
+ module_eval <<'.,.,', 'xpath.ry', 164
2275
+ def _reduce_38( val, _values)
2276
+ LocationPath.new.absolute!
2277
+ end
2278
+ .,.,
2279
+
2280
+ module_eval <<'.,.,', 'xpath.ry', 166
2281
+ def _reduce_39( val, _values)
2282
+ val[1].absolute!
2283
+ end
2284
+ .,.,
2285
+
2286
+ module_eval <<'.,.,', 'xpath.ry', 169
2287
+ def _reduce_40( val, _values)
2288
+ path = LocationPath.new
2289
+ path.absolute!
2290
+ path.add_step('descendant-or-self') << val[1]
2291
+ end
2292
+ .,.,
2293
+
2294
+ # reduce 41 omitted
2295
+
2296
+ module_eval <<'.,.,', 'xpath.ry', 176
2297
+ def _reduce_42( val, _values)
2298
+ LocationPath.new.add_step(*val[0])
2299
+ end
2300
+ .,.,
2301
+
2302
+ module_eval <<'.,.,', 'xpath.ry', 178
2303
+ def _reduce_43( val, _values)
2304
+ val[0].add_step(*val[2])
2305
+ end
2306
+ .,.,
2307
+
2308
+ module_eval <<'.,.,', 'xpath.ry', 181
2309
+ def _reduce_44( val, _values)
2310
+ val[0].add_step('descendant-or-self').add_step(*val[2])
2311
+ end
2312
+ .,.,
2313
+
2314
+ module_eval <<'.,.,', 'xpath.ry', 186
2315
+ def _reduce_45( val, _values)
2316
+ c = @context
2317
+ @context = c.succ
2318
+ c
2319
+ end
2320
+ .,.,
2321
+
2322
+ module_eval <<'.,.,', 'xpath.ry', 192
2323
+ def _reduce_46( val, _values)
2324
+ c = @context
2325
+ @context = _values[-2]
2326
+ c
2327
+ end
2328
+ .,.,
2329
+
2330
+ module_eval <<'.,.,', 'xpath.ry', 198
2331
+ def _reduce_47( val, _values)
2332
+ on_error unless is_xpointer?
2333
+ args = val[5]
2334
+ c = val[6]
2335
+ args.collect! { |i| i or c }
2336
+ args[0] = ".funcall(#{val[2].dump}) { |#{c}| ["
2337
+ args.push '] }'
2338
+ val[0].add_predicate args
2339
+ end
2340
+ .,.,
2341
+
2342
+ module_eval <<'.,.,', 'xpath.ry', 208
2343
+ def _reduce_48( val, _values)
2344
+ [ 'self', false, false, false, nil ]
2345
+ end
2346
+ .,.,
2347
+
2348
+ module_eval <<'.,.,', 'xpath.ry', 210
2349
+ def _reduce_49( val, _values)
2350
+ [ 'parent', false, false, false, nil ]
2351
+ end
2352
+ .,.,
2353
+
2354
+ module_eval <<'.,.,', 'xpath.ry', 213
2355
+ def _reduce_50( val, _values)
2356
+ nodetest = val[1]
2357
+ unless nodetest[0] then
2358
+ axis = val[0]
2359
+ if axis != 'attribute' and axis != 'namespace' then
2360
+ nodetest[0] = 'element'
2361
+ end
2362
+ end
2363
+ nodetest[0] = false if nodetest[0] == 'node'
2364
+ nodetest.unshift(val[0]).push(val[2])
2365
+ end
2366
+ .,.,
2367
+
2368
+ # reduce 51 omitted
2369
+
2370
+ module_eval <<'.,.,', 'xpath.ry', 226
2371
+ def _reduce_52( val, _values)
2372
+ (val[0] || []).concat val[1]
2373
+ end
2374
+ .,.,
2375
+
2376
+ module_eval <<'.,.,', 'xpath.ry', 229
2377
+ def _reduce_53( val, _values)
2378
+ [ false, false, false ]
2379
+ end
2380
+ .,.,
2381
+
2382
+ module_eval <<'.,.,', 'xpath.ry', 232
2383
+ def _reduce_54( val, _values)
2384
+ if /:/ =~ val[0] then
2385
+ [ false, $', $` ] #' <= for racc
2386
+ else
2387
+ [ false, val[0], nil ]
2388
+ end
2389
+ end
2390
+ .,.,
2391
+
2392
+ module_eval <<'.,.,', 'xpath.ry', 240
2393
+ def _reduce_55( val, _values)
2394
+ on_error if /:/ =~ val[0]
2395
+ [ false, false, val[0] ]
2396
+ end
2397
+ .,.,
2398
+
2399
+ module_eval <<'.,.,', 'xpath.ry', 245
2400
+ def _reduce_56( val, _values)
2401
+ nodetype = val[0]
2402
+ arg = val[2]
2403
+ if arg and nodetype != 'processing-instruction' then
2404
+ raise CompileError,
2405
+ "nodetest #{nodetype}() requires no argument"
2406
+ end
2407
+ [ nodetype, arg || false, false ]
2408
+ end
2409
+ .,.,
2410
+
2411
+ # reduce 57 omitted
2412
+
2413
+ # reduce 58 omitted
2414
+
2415
+ module_eval <<'.,.,', 'xpath.ry', 258
2416
+ def _reduce_59( val, _values)
2417
+ 'child'
2418
+ end
2419
+ .,.,
2420
+
2421
+ module_eval <<'.,.,', 'xpath.ry', 260
2422
+ def _reduce_60( val, _values)
2423
+ 'attribute'
2424
+ end
2425
+ .,.,
2426
+
2427
+ # reduce 61 omitted
2428
+
2429
+ def _reduce_none( val, _values)
2430
+ val[0]
2431
+ end
2432
+
2433
+ end # class Compiler
2434
+
2435
+
2436
+ #
2437
+ # Client NodeVisitor a NodeAdapter a Node
2438
+ # | | | |
2439
+ # |=| | | |
2440
+ # | |--{visit(node)}-->|=| | |
2441
+ # | | | |---{accept(self)}----------------->|=|
2442
+ # | | |=| | | |
2443
+ # | | | | | |
2444
+ # | | |=|<------------------{on_**(self)}---|=|
2445
+ # | | | | | |
2446
+ # | | | |--{wrap(node)}-->|=| |
2447
+ # | | | | | | |
2448
+ # | | | | |=| |
2449
+ # | |<--[NodeAdapter]--|=| | |
2450
+ # | | | | |
2451
+ # | |-----{request}----------------------->|=| |
2452
+ # | | | | |--{request}--->|=|
2453
+ # | | | | | | |
2454
+ # | | | | |<-----[Data]---|=|
2455
+ # | |<--------------------------[Data]-----|=| |
2456
+ # | | | | |
2457
+ # |=| | | |
2458
+ # | | | |
2459
+ #
2460
+
2461
+
2462
+ class TransparentNodeVisitor
2463
+
2464
+ def visit(node)
2465
+ node
2466
+ end
2467
+
2468
+ end
2469
+
2470
+
2471
+ class NullNodeAdapter
2472
+
2473
+ def node
2474
+ self
2475
+ end
2476
+
2477
+ def root
2478
+ nil
2479
+ end
2480
+
2481
+ def parent
2482
+ nil
2483
+ end
2484
+
2485
+ def children
2486
+ []
2487
+ end
2488
+
2489
+ def each_following_siblings
2490
+ end
2491
+
2492
+ def each_preceding_siblings
2493
+ end
2494
+
2495
+ def attributes
2496
+ []
2497
+ end
2498
+
2499
+ def namespaces
2500
+ []
2501
+ end
2502
+
2503
+ def index
2504
+ 0
2505
+ end
2506
+
2507
+ def node_type
2508
+ nil
2509
+ end
2510
+
2511
+ def name_localpart
2512
+ nil
2513
+ end
2514
+
2515
+ def qualified_name
2516
+ name_localpart
2517
+ end
2518
+
2519
+ def namespace_uri
2520
+ nil
2521
+ end
2522
+
2523
+ def string_value
2524
+ ''
2525
+ end
2526
+
2527
+ def lang
2528
+ nil
2529
+ end
2530
+
2531
+ def select_id(*ids)
2532
+ raise XPath::Error, "selection by ID is not supported"
2533
+ end
2534
+
2535
+ end
2536
+
2537
+
2538
+
2539
+
2540
+ class AxisIterator
2541
+
2542
+ def reverse_order?
2543
+ false
2544
+ end
2545
+
2546
+ end
2547
+
2548
+
2549
+ class ReverseAxisIterator < AxisIterator
2550
+
2551
+ def reverse_order?
2552
+ true
2553
+ end
2554
+
2555
+ end
2556
+
2557
+
2558
+ class SelfIterator < AxisIterator
2559
+
2560
+ def each(node, visitor)
2561
+ yield visitor.visit(node)
2562
+ end
2563
+
2564
+ end
2565
+
2566
+
2567
+ class ChildIterator < AxisIterator
2568
+
2569
+ def each(node, visitor, &block)
2570
+ visitor.visit(node).children.each { |i| yield visitor.visit(i) }
2571
+ end
2572
+
2573
+ end
2574
+
2575
+
2576
+ class ParentIterator < AxisIterator
2577
+
2578
+ def each(node, visitor)
2579
+ parent = visitor.visit(node).parent
2580
+ yield visitor.visit(parent) if parent
2581
+ end
2582
+
2583
+ end
2584
+
2585
+
2586
+ class AncestorIterator < ReverseAxisIterator
2587
+
2588
+ def each(node, visitor)
2589
+ node = visitor.visit(node).parent
2590
+ while node
2591
+ i = visitor.visit(node)
2592
+ parent = i.parent
2593
+ yield i
2594
+ node = parent
2595
+ end
2596
+ end
2597
+
2598
+ end
2599
+
2600
+
2601
+ class AncestorOrSelfIterator < AncestorIterator
2602
+
2603
+ def each(node, visitor)
2604
+ yield visitor.visit(node)
2605
+ super
2606
+ end
2607
+
2608
+ end
2609
+
2610
+
2611
+ class DescendantIterator < AxisIterator
2612
+
2613
+ def each(node, visitor)
2614
+ stack = visitor.visit(node).children.reverse
2615
+ while node = stack.pop
2616
+ i = visitor.visit(node)
2617
+ stack.concat i.children.reverse
2618
+ yield i
2619
+ end
2620
+ end
2621
+
2622
+ end
2623
+
2624
+
2625
+ class DescendantOrSelfIterator < DescendantIterator
2626
+
2627
+ def each(node, visitor)
2628
+ yield visitor.visit(node)
2629
+ super
2630
+ end
2631
+
2632
+ end
2633
+
2634
+
2635
+ class FollowingSiblingIterator < AxisIterator
2636
+
2637
+ def each(node, visitor)
2638
+ visitor.visit(node).each_following_siblings { |i|
2639
+ yield visitor.visit(i)
2640
+ }
2641
+ end
2642
+
2643
+ end
2644
+
2645
+
2646
+ class PrecedingSiblingIterator < ReverseAxisIterator
2647
+
2648
+ def each(node, visitor)
2649
+ visitor.visit(node).each_preceding_siblings { |i|
2650
+ yield visitor.visit(i)
2651
+ }
2652
+ end
2653
+
2654
+ end
2655
+
2656
+
2657
+ class FollowingIterator < DescendantOrSelfIterator
2658
+
2659
+ def each(node, visitor)
2660
+ while parent = (a = visitor.visit(node)).parent
2661
+ a.each_following_siblings { |i| super i, visitor }
2662
+ node = parent
2663
+ end
2664
+ end
2665
+
2666
+ end
2667
+
2668
+
2669
+ class PrecedingIterator < ReverseAxisIterator
2670
+
2671
+ def each(node, visitor)
2672
+ while parent = (adaptor = visitor.visit(node)).parent
2673
+ adaptor.each_preceding_siblings { |i|
2674
+ stack = visitor.visit(i).children.dup
2675
+ while node = stack.pop
2676
+ a = visitor.visit(node)
2677
+ stack.concat a.children
2678
+ yield a
2679
+ end
2680
+ yield visitor.visit(i)
2681
+ }
2682
+ node = parent
2683
+ end
2684
+ end
2685
+
2686
+ end
2687
+
2688
+
2689
+ class AttributeIterator < AxisIterator
2690
+
2691
+ def each(node, visitor)
2692
+ visitor.visit(node).attributes.each { |i| yield visitor.visit(i) }
2693
+ end
2694
+
2695
+ end
2696
+
2697
+
2698
+ class NamespaceIterator < AxisIterator
2699
+
2700
+ def each(node, visitor)
2701
+ visitor.visit(node).namespaces.each { |i| yield visitor.visit(i) }
2702
+ end
2703
+
2704
+ end
2705
+
2706
+
2707
+
2708
+
2709
+ class XPathNodeSet
2710
+
2711
+ class LocationStep < XPathNodeSet
2712
+
2713
+ def initialize(context)
2714
+ @context = context
2715
+ @visitor = context.visitor
2716
+ @nodes = []
2717
+ end
2718
+
2719
+ def set_iterator(iterator)
2720
+ @iterator = iterator
2721
+ end
2722
+
2723
+ def reuse(node)
2724
+ @node = node
2725
+ @nodes.clear
2726
+ end
2727
+
2728
+ def select
2729
+ @iterator.each(@node, @visitor) { |i|
2730
+ node = i.node
2731
+ @nodes.push node if yield(i)
2732
+ }
2733
+ self
2734
+ end
2735
+
2736
+ def select_all
2737
+ @iterator.each(@node, @visitor) { |i| @nodes.push i.node }
2738
+ self
2739
+ end
2740
+
2741
+ end
2742
+
2743
+
2744
+ include XPathObject
2745
+
2746
+ def initialize(context, *nodes)
2747
+ @context = context.dup
2748
+ @visitor = context.visitor
2749
+ nodes.sort! { |a,b| compare_position a, b }
2750
+ @nodes = nodes
2751
+ end
2752
+
2753
+ attr_reader :nodes
2754
+ protected :nodes
2755
+
2756
+
2757
+ def to_str
2758
+ if @nodes.empty? then
2759
+ ''
2760
+ else
2761
+ @visitor.visit(@nodes[0]).string_value
2762
+ end
2763
+ end
2764
+
2765
+ def to_f
2766
+ to_string(@context).to_f
2767
+ end
2768
+
2769
+ def true?
2770
+ not @nodes.empty?
2771
+ end
2772
+
2773
+ def to_ruby
2774
+ @nodes
2775
+ end
2776
+
2777
+
2778
+ def self.def_comparison_operator(*ops)
2779
+ ops.each { |op|
2780
+ module_eval <<_, __FILE__, __LINE__ + 1
2781
+ def #{op}(other)
2782
+ if other.is_a? XPathBoolean then
2783
+ other #{op} self.to_boolean
2784
+ else
2785
+ visitor = @visitor
2786
+ str = @context.make_string('')
2787
+ ret = false
2788
+ @nodes.each { |node|
2789
+ str.replace visitor.visit(node).string_value
2790
+ break if ret = (other #{op} str)
2791
+ }
2792
+ ret
2793
+ end
2794
+ end
2795
+ _
2796
+ }
2797
+ end
2798
+
2799
+ def_comparison_operator '==', '<', '>', '<=', '>='
2800
+
2801
+ class << self
2802
+ undef def_comparison_operator
2803
+ end
2804
+
2805
+ def **(other)
2806
+ super unless other.is_a? XPathNodeSet
2807
+ merge other.nodes
2808
+ self
2809
+ end
2810
+
2811
+
2812
+ def count
2813
+ @nodes.size
2814
+ end
2815
+
2816
+ def first
2817
+ @nodes[0]
2818
+ end
2819
+
2820
+ def each(&block)
2821
+ @nodes.each(&block)
2822
+ end
2823
+
2824
+
2825
+ def funcall(name) # for XPointer
2826
+ raise "BUG" unless block_given?
2827
+ func = ('f_' + name.tr('-', '_')).intern
2828
+ super unless respond_to? func, true
2829
+ size = @nodes.size
2830
+ pos = 1
2831
+ c = @context.dup
2832
+ begin
2833
+ @nodes.collect! { |node|
2834
+ c.reuse node, pos, size
2835
+ pos += 1
2836
+ args = yield(c)
2837
+ send(func, node, *args)
2838
+ }
2839
+ rescue Object::ArgumentError
2840
+ if $@[1] == "#{__FILE__}:#{__LINE__-3}:in `send'" then
2841
+ raise XPath::ArgumentError, "#{$!} for `#{name}'"
2842
+ end
2843
+ raise
2844
+ end
2845
+ self
2846
+ end
2847
+
2848
+
2849
+ private
2850
+
2851
+ def compare_position(node1, node2)
2852
+ visitor = @visitor
2853
+ ancestors1 = []
2854
+ ancestors2 = []
2855
+ p1 = visitor.visit(node1).parent
2856
+ while p1
2857
+ ancestors1.push node1
2858
+ p1 = visitor.visit(node1 = p1).parent
2859
+ end
2860
+ p2 = visitor.visit(node2).parent
2861
+ while p2
2862
+ ancestors2.push node2
2863
+ p2 = visitor.visit(node2 = p2).parent
2864
+ end
2865
+ unless node1 == node2 then
2866
+ raise XPath::Error, "can't compare the positions of given two nodes"
2867
+ end
2868
+ n = -1
2869
+ ancestors1.reverse_each { |node1|
2870
+ node2 = ancestors2[n]
2871
+ unless node1 == node2 then
2872
+ break unless node2
2873
+ return visitor.visit(node1).index - visitor.visit(node2).index
2874
+ end
2875
+ n -= 1
2876
+ }
2877
+ ancestors1.size - ancestors2.size
2878
+ end
2879
+
2880
+
2881
+ def merge(other)
2882
+ if @nodes.empty? or other.empty? then
2883
+ @nodes.concat other
2884
+ elsif (n = compare_position(@nodes.last, other.first)) <= 0 then
2885
+ @nodes.pop if n == 0
2886
+ @nodes.concat other
2887
+ elsif (n = compare_position(other.last, @nodes.first)) <= 0 then
2888
+ other.pop if n == 0
2889
+ @nodes = other.concat(@nodes)
2890
+ else
2891
+ newnodes = []
2892
+ nodes = @nodes
2893
+ until nodes.empty? or other.empty?
2894
+ n = compare_position(nodes.last, other.last)
2895
+ if n > 0 then
2896
+ newnodes.push nodes.pop
2897
+ elsif n < 0 then
2898
+ newnodes.push other.pop
2899
+ else
2900
+ newnodes.push nodes.pop
2901
+ other.pop
2902
+ end
2903
+ end
2904
+ newnodes.reverse!
2905
+ @nodes.concat(other).concat(newnodes)
2906
+ end
2907
+ end
2908
+
2909
+
2910
+ IteratorForAxis = {
2911
+ :self => SelfIterator.new,
2912
+ :child => ChildIterator.new,
2913
+ :parent => ParentIterator.new,
2914
+ :ancestor => AncestorIterator.new,
2915
+ :ancestor_or_self => AncestorOrSelfIterator.new,
2916
+ :descendant => DescendantIterator.new,
2917
+ :descendant_or_self => DescendantOrSelfIterator.new,
2918
+ :following => FollowingIterator.new,
2919
+ :preceding => PrecedingIterator.new,
2920
+ :following_sibling => FollowingSiblingIterator.new,
2921
+ :preceding_sibling => PrecedingSiblingIterator.new,
2922
+ :attribute => AttributeIterator.new,
2923
+ :namespace => NamespaceIterator.new,
2924
+ }
2925
+
2926
+ def get_iterator(axis)
2927
+ ret = IteratorForAxis[axis]
2928
+ unless ret then
2929
+ raise XPath::NameError, "invalid axis `#{axis.id2name.tr('_','-')}'"
2930
+ end
2931
+ ret
2932
+ end
2933
+
2934
+ def make_location_step
2935
+ if defined? @__lstep__ then
2936
+ @__lstep__
2937
+ else
2938
+ @__lstep__ = LocationStep.new(@context)
2939
+ end
2940
+ end
2941
+
2942
+
2943
+ public
2944
+
2945
+ def step(axis)
2946
+ iterator = get_iterator(axis)
2947
+ lstep = make_location_step
2948
+ lstep.set_iterator iterator
2949
+ oldnodes = @nodes
2950
+ @nodes = []
2951
+ oldnodes.each { |node|
2952
+ lstep.reuse node
2953
+ nodes = yield(lstep).nodes
2954
+ nodes.reverse! if iterator.reverse_order?
2955
+ merge nodes
2956
+ }
2957
+ self
2958
+ end
2959
+
2960
+
2961
+ def select_all(axis)
2962
+ iterator = get_iterator(axis)
2963
+ visitor = @visitor
2964
+ oldnodes = @nodes
2965
+ @nodes = []
2966
+ oldnodes.each { |start|
2967
+ nodes = []
2968
+ iterator.each(start, visitor) { |i| nodes.push i.node }
2969
+ nodes.reverse! if iterator.reverse_order?
2970
+ merge nodes
2971
+ }
2972
+ self
2973
+ end
2974
+
2975
+
2976
+ def predicate
2977
+ context = @context
2978
+ size = @nodes.size
2979
+ pos = 1
2980
+ result = nil
2981
+ newnodes = @nodes.reject { |node|
2982
+ context.reuse node, pos, size
2983
+ pos += 1
2984
+ result = yield(context)
2985
+ break if result.is_a? Numeric
2986
+ not result
2987
+ }
2988
+ if result.is_a? Numeric then
2989
+ at result
2990
+ else
2991
+ @nodes = newnodes
2992
+ end
2993
+ self
2994
+ end
2995
+
2996
+
2997
+ def at(pos)
2998
+ n = pos.to_i
2999
+ if n != pos or n <= 0 then
3000
+ node = nil
3001
+ else
3002
+ node = @nodes[n - 1]
3003
+ end
3004
+ @nodes.clear
3005
+ @nodes.push node if node
3006
+ self
3007
+ end
3008
+
3009
+ end
3010
+
3011
+
3012
+
3013
+ class Context
3014
+
3015
+ def initialize(node, namespace = nil, variable = nil, visitor = nil)
3016
+ visitor = TransparentNodeVisitor.new unless visitor
3017
+ @visitor = visitor
3018
+ @node = node
3019
+ @context_position = 1
3020
+ @context_size = 1
3021
+ @variables = variable
3022
+ @namespaces = namespace || {}
3023
+ end
3024
+
3025
+ attr_reader :visitor, :node, :context_position, :context_size
3026
+
3027
+ def reuse(node, pos = 1, size = 1)
3028
+ @variables = nil
3029
+ @node, @context_position, @context_size = node, pos, size
3030
+ end
3031
+
3032
+
3033
+ def get_variable(name)
3034
+ value = @variables && @variables[name] # value should be a XPathObjcect.
3035
+ raise XPath::NameError, "undefined variable `#{name}'" unless value
3036
+ value
3037
+ end
3038
+
3039
+
3040
+ PredefinedNamespace = {
3041
+ 'xml' => 'http://www.w3.org/XML/1998/namespace',
3042
+ }
3043
+
3044
+ def get_namespace(prefix)
3045
+ ret = @namespaces[prefix] || PredefinedNamespace[prefix]
3046
+ raise XPath::Error, "undeclared namespace `#{prefix}'" unless ret
3047
+ ret
3048
+ end
3049
+
3050
+
3051
+ def make_string(str)
3052
+ XPathString.new str
3053
+ end
3054
+
3055
+ def make_number(num)
3056
+ XPathNumber.new num
3057
+ end
3058
+
3059
+ def make_boolean(f)
3060
+ if f then
3061
+ XPathTrue
3062
+ else
3063
+ XPathFalse
3064
+ end
3065
+ end
3066
+
3067
+ def make_nodeset(*nodes)
3068
+ XPathNodeSet.new(self, *nodes)
3069
+ end
3070
+
3071
+
3072
+ def to_nodeset
3073
+ make_nodeset @node
3074
+ end
3075
+
3076
+ def root_nodeset
3077
+ make_nodeset @visitor.visit(@node).root
3078
+ end
3079
+
3080
+
3081
+ def funcall(name, *args)
3082
+ begin
3083
+ send('f_' + name.tr('-', '_'), *args)
3084
+ rescue Object::NameError
3085
+ if $@[0] == "#{__FILE__}:#{__LINE__-2}:in `send'" then
3086
+ raise XPath::NameError, "undefined function `#{name}'"
3087
+ end
3088
+ raise
3089
+ rescue Object::ArgumentError
3090
+ if $@[1] == "#{__FILE__}:#{__LINE__-7}:in `send'" then
3091
+ raise XPath::ArgumentError, "#{$!} for `#{name}'"
3092
+ end
3093
+ raise
3094
+ end
3095
+ end
3096
+
3097
+
3098
+ private
3099
+
3100
+ def must(type, *args)
3101
+ args.each { |i|
3102
+ unless i.is_a? type then
3103
+ s = type.name.sub(/\A.*::(?:XPath)?(?=[^:]+\z)/, '')
3104
+ raise XPath::TypeError, "argument must be #{s}"
3105
+ end
3106
+ }
3107
+ end
3108
+
3109
+ def must_be_nodeset(*args)
3110
+ must XPathNodeSet, *args
3111
+ end
3112
+
3113
+
3114
+ def f_last
3115
+ make_number @context_size.to_f
3116
+ end
3117
+
3118
+ def f_position
3119
+ make_number @context_position.to_f
3120
+ end
3121
+
3122
+ def f_count(nodeset)
3123
+ must_be_nodeset nodeset
3124
+ make_number nodeset.count.to_f
3125
+ end
3126
+
3127
+ def f_id(obj)
3128
+ unless obj.is_a? XPathNodeSet then
3129
+ ids = obj.to_str.strip.split(/\s+/)
3130
+ else
3131
+ ids = []
3132
+ obj.each { |node| ids.push @visitor.visit(node).string_value }
3133
+ end
3134
+ root = @visitor.visit(@node).root
3135
+ make_nodeset(*@visitor.visit(root).select_id(*ids))
3136
+ end
3137
+
3138
+ def f_local_name(nodeset = nil)
3139
+ unless nodeset then
3140
+ n = @node
3141
+ else
3142
+ must_be_nodeset nodeset
3143
+ n = nodeset.first
3144
+ end
3145
+ n = @visitor.visit(n) if n
3146
+ n = n.name_localpart if n
3147
+ n = '' unless n
3148
+ make_string n
3149
+ end
3150
+
3151
+ def f_namespace_uri(nodeset = nil)
3152
+ unless nodeset then
3153
+ n = @node
3154
+ else
3155
+ must_be_nodeset nodeset
3156
+ n = nodeset.first
3157
+ end
3158
+ n = @visitor.visit(n) if n
3159
+ n = n.namespace_uri if n
3160
+ n = '' unless n
3161
+ make_string n
3162
+ end
3163
+
3164
+ def f_name(nodeset = nil)
3165
+ unless nodeset then
3166
+ n = @node
3167
+ else
3168
+ must_be_nodeset nodeset
3169
+ n = nodeset.first
3170
+ end
3171
+ n = @visitor.visit(n) if n
3172
+ n = n.qualified_name if n
3173
+ n = '' unless n
3174
+ make_string n
3175
+ end
3176
+
3177
+
3178
+ def f_string(obj = nil)
3179
+ obj = to_nodeset unless obj
3180
+ obj.to_string self
3181
+ end
3182
+
3183
+ def f_concat(str, str2, *strs)
3184
+ s = str2.to_str.dup
3185
+ strs.each { |i| s << i.to_str }
3186
+ str.to_string(self).concat(s)
3187
+ end
3188
+
3189
+ def f_starts_with(str, sub)
3190
+ make_boolean str.to_string(self).start_with?(sub.to_str)
3191
+ end
3192
+
3193
+ def f_contains(str, sub)
3194
+ make_boolean str.to_string(self).contain?(sub.to_str)
3195
+ end
3196
+
3197
+ def f_substring_before(str, sub)
3198
+ str.to_string(self).substring_before sub.to_str
3199
+ end
3200
+
3201
+ def f_substring_after(str, sub)
3202
+ str.to_string(self).substring_after sub.to_str
3203
+ end
3204
+
3205
+ def f_substring(str, start, len = nil)
3206
+ len = len.to_number(self) if len
3207
+ str.to_string(self).substring start.to_number(self), len
3208
+ end
3209
+
3210
+ def f_string_length(str = nil)
3211
+ if str then
3212
+ str = str.to_string(self)
3213
+ else
3214
+ str = make_string(@node.string_value)
3215
+ end
3216
+ make_number str.size.to_f
3217
+ end
3218
+
3219
+ def f_normalize_space(str = nil)
3220
+ if str then
3221
+ str = str.to_string(self)
3222
+ else
3223
+ str = make_string(@node.string_value)
3224
+ end
3225
+ str.normalize_space
3226
+ end
3227
+
3228
+ def f_translate(str, from, to)
3229
+ str.to_string(self).translate from.to_str, to.to_str
3230
+ end
3231
+
3232
+
3233
+ def f_boolean(obj)
3234
+ obj.to_boolean self
3235
+ end
3236
+
3237
+ def f_not(bool)
3238
+ make_boolean(!bool.true?)
3239
+ end
3240
+
3241
+ def f_true
3242
+ make_boolean true
3243
+ end
3244
+
3245
+ def f_false
3246
+ make_boolean false
3247
+ end
3248
+
3249
+ def f_lang(str)
3250
+ lang = @visitor.visit(@node).lang
3251
+ make_boolean(lang && /\A#{Regexp.quote(str.to_str)}(?:-|\z)/i =~ lang)
3252
+ end
3253
+
3254
+
3255
+ def f_number(obj = nil)
3256
+ obj = to_nodeset unless obj
3257
+ obj.to_number self
3258
+ end
3259
+
3260
+ def f_sum(nodeset)
3261
+ must_be_nodeset nodeset
3262
+ sum = 0.0
3263
+ nodeset.each { |node|
3264
+ sum += make_string(@visitor.visit(node).string_value).to_f
3265
+ }
3266
+ make_number sum
3267
+ end
3268
+
3269
+ def f_floor(num)
3270
+ num.to_number(self).floor
3271
+ end
3272
+
3273
+ def f_ceiling(num)
3274
+ num.to_number(self).ceil
3275
+ end
3276
+
3277
+ def f_round(num)
3278
+ num.to_number(self).round
3279
+ end
3280
+
3281
+ end
3282
+
3283
+
3284
+ end