rgen 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. data/CHANGELOG +20 -1
  2. data/MIT-LICENSE +1 -1
  3. data/README +12 -9
  4. data/lib/instantiators/ea_instantiator.rb +36 -0
  5. data/lib/metamodels/uml13_metamodel.rb +559 -0
  6. data/lib/metamodels/uml13_metamodel_ext.rb +26 -0
  7. data/lib/mmgen/metamodel_generator.rb +5 -5
  8. data/lib/mmgen/mm_ext/ecore_ext.rb +95 -0
  9. data/lib/mmgen/mmgen.rb +6 -4
  10. data/lib/mmgen/templates/annotations.tpl +37 -0
  11. data/lib/mmgen/templates/metamodel_generator.tpl +171 -0
  12. data/lib/rgen/ecore/ecore.rb +190 -0
  13. data/lib/rgen/ecore/ecore_instantiator.rb +25 -0
  14. data/lib/rgen/ecore/ecore_transformer.rb +85 -0
  15. data/lib/rgen/environment.rb +9 -24
  16. data/lib/rgen/find_helper.rb +68 -0
  17. data/lib/rgen/{instantiator.rb → instantiator/abstract_instantiator.rb} +6 -2
  18. data/lib/rgen/instantiator/abstract_xml_instantiator.rb +59 -0
  19. data/lib/rgen/instantiator/default_xml_instantiator.rb +117 -0
  20. data/lib/rgen/instantiator/ecore_xml_instantiator.rb +144 -0
  21. data/lib/rgen/instantiator/nodebased_xml_instantiator.rb +157 -0
  22. data/lib/rgen/instantiator/xmi11_instantiator.rb +164 -0
  23. data/lib/rgen/metamodel_builder.rb +103 -9
  24. data/lib/rgen/metamodel_builder/build_helper.rb +26 -4
  25. data/lib/rgen/metamodel_builder/builder_extensions.rb +285 -88
  26. data/lib/rgen/metamodel_builder/builder_runtime.rb +7 -1
  27. data/lib/rgen/metamodel_builder/data_types.rb +67 -0
  28. data/lib/rgen/metamodel_builder/intermediate/annotation.rb +30 -0
  29. data/lib/rgen/metamodel_builder/metamodel_description.rb +232 -0
  30. data/lib/rgen/metamodel_builder/mm_multiple.rb +23 -0
  31. data/lib/rgen/metamodel_builder/module_extension.rb +33 -0
  32. data/lib/rgen/model_comparator.rb +56 -0
  33. data/lib/rgen/model_dumper.rb +5 -5
  34. data/lib/rgen/name_helper.rb +17 -1
  35. data/lib/rgen/template_language.rb +148 -28
  36. data/lib/rgen/template_language/directory_template_container.rb +56 -38
  37. data/lib/rgen/template_language/output_handler.rb +93 -77
  38. data/lib/rgen/template_language/template_container.rb +186 -143
  39. data/lib/rgen/transformer.rb +19 -14
  40. data/lib/transformers/uml13_to_ecore.rb +75 -0
  41. data/redist/xmlscan/ChangeLog +1301 -0
  42. data/redist/xmlscan/README +34 -0
  43. data/redist/xmlscan/THANKS +11 -0
  44. data/redist/xmlscan/doc/changes.html +74 -0
  45. data/redist/xmlscan/doc/changes.rd +80 -0
  46. data/redist/xmlscan/doc/en/conformance.html +136 -0
  47. data/redist/xmlscan/doc/en/conformance.rd +152 -0
  48. data/redist/xmlscan/doc/en/manual.html +356 -0
  49. data/redist/xmlscan/doc/en/manual.rd +402 -0
  50. data/redist/xmlscan/doc/ja/conformance.ja.html +118 -0
  51. data/redist/xmlscan/doc/ja/conformance.ja.rd +134 -0
  52. data/redist/xmlscan/doc/ja/manual.ja.html +325 -0
  53. data/redist/xmlscan/doc/ja/manual.ja.rd +370 -0
  54. data/redist/xmlscan/doc/src/Makefile +41 -0
  55. data/redist/xmlscan/doc/src/conformance.rd.src +256 -0
  56. data/redist/xmlscan/doc/src/langsplit.rb +110 -0
  57. data/redist/xmlscan/doc/src/manual.rd.src +614 -0
  58. data/redist/xmlscan/install.rb +41 -0
  59. data/redist/xmlscan/lib/xmlscan/encoding.rb +311 -0
  60. data/redist/xmlscan/lib/xmlscan/htmlscan.rb +289 -0
  61. data/redist/xmlscan/lib/xmlscan/namespace.rb +352 -0
  62. data/redist/xmlscan/lib/xmlscan/parser.rb +299 -0
  63. data/redist/xmlscan/lib/xmlscan/scanner.rb +1109 -0
  64. data/redist/xmlscan/lib/xmlscan/version.rb +22 -0
  65. data/redist/xmlscan/lib/xmlscan/visitor.rb +158 -0
  66. data/redist/xmlscan/lib/xmlscan/xmlchar.rb +441 -0
  67. data/redist/xmlscan/memo/CONFORMANCE +1249 -0
  68. data/redist/xmlscan/memo/PRODUCTIONS +195 -0
  69. data/redist/xmlscan/memo/contentspec.ry +335 -0
  70. data/redist/xmlscan/samples/chibixml.rb +105 -0
  71. data/redist/xmlscan/samples/getxmlchar.rb +122 -0
  72. data/redist/xmlscan/samples/rexml.rb +159 -0
  73. data/redist/xmlscan/samples/xmlbench.rb +88 -0
  74. data/redist/xmlscan/samples/xmlbench/parser/chibixml.rb +22 -0
  75. data/redist/xmlscan/samples/xmlbench/parser/nqxml.rb +29 -0
  76. data/redist/xmlscan/samples/xmlbench/parser/rexml.rb +62 -0
  77. data/redist/xmlscan/samples/xmlbench/parser/xmlparser.rb +22 -0
  78. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-0.0.10.rb +62 -0
  79. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-chibixml.rb +22 -0
  80. data/redist/xmlscan/samples/xmlbench/parser/xmlscan-rexml.rb +22 -0
  81. data/redist/xmlscan/samples/xmlbench/parser/xmlscan.rb +99 -0
  82. data/redist/xmlscan/samples/xmlbench/xmlbench-lib.rb +116 -0
  83. data/redist/xmlscan/samples/xmlconftest.rb +200 -0
  84. data/redist/xmlscan/test.rb +7 -0
  85. data/redist/xmlscan/tests/deftestcase.rb +73 -0
  86. data/redist/xmlscan/tests/runtest.rb +47 -0
  87. data/redist/xmlscan/tests/testall.rb +14 -0
  88. data/redist/xmlscan/tests/testencoding.rb +438 -0
  89. data/redist/xmlscan/tests/testhtmlscan.rb +752 -0
  90. data/redist/xmlscan/tests/testnamespace.rb +457 -0
  91. data/redist/xmlscan/tests/testparser.rb +591 -0
  92. data/redist/xmlscan/tests/testscanner.rb +1749 -0
  93. data/redist/xmlscan/tests/testxmlchar.rb +143 -0
  94. data/redist/xmlscan/tests/visitor.rb +34 -0
  95. data/test/array_extensions_test.rb +2 -2
  96. data/test/ea_instantiator_test.rb +41 -0
  97. data/test/ecore_self_test.rb +53 -0
  98. data/test/environment_test.rb +11 -6
  99. data/test/metamodel_builder_test.rb +404 -245
  100. data/test/metamodel_roundtrip_test.rb +52 -0
  101. data/test/metamodel_roundtrip_test/TestModel.rb +65 -0
  102. data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +64 -0
  103. data/test/metamodel_roundtrip_test/houseMetamodel.ecore +32 -0
  104. data/test/metamodel_roundtrip_test/houseMetamodel_from_ecore.rb +39 -0
  105. data/test/rgen_test.rb +3 -3
  106. data/test/template_language_test.rb +65 -39
  107. data/test/template_language_test/expected_result.txt +24 -3
  108. data/test/template_language_test/templates/code/array.tpl +11 -0
  109. data/test/template_language_test/templates/content/author.tpl +7 -0
  110. data/test/template_language_test/templates/content/chapter.tpl +1 -1
  111. data/test/template_language_test/templates/root.tpl +17 -8
  112. data/test/template_language_test/testout.txt +24 -3
  113. data/test/testmodel/class_model_checker.rb +119 -0
  114. data/test/{xmi_instantiator_test/testmodel.eap → testmodel/ea_testmodel.eap} +0 -0
  115. data/test/{xmi_instantiator_test/testmodel.xml → testmodel/ea_testmodel.xml} +81 -14
  116. data/test/testmodel/ea_testmodel_partial.xml +317 -0
  117. data/test/testmodel/ecore_model_checker.rb +101 -0
  118. data/test/testmodel/manual_testmodel.xml +22 -0
  119. data/test/testmodel/object_model_checker.rb +67 -0
  120. data/test/transformer_test.rb +18 -10
  121. data/test/xml_instantiator_test.rb +81 -8
  122. data/test/xml_instantiator_test/simple_ecore_model_checker.rb +94 -0
  123. data/test/xml_instantiator_test/simple_xmi_ecore_instantiator.rb +53 -0
  124. data/test/xml_instantiator_test/simple_xmi_metamodel.rb +49 -0
  125. data/test/xml_instantiator_test/simple_xmi_to_ecore.rb +75 -0
  126. metadata +126 -28
  127. data/lib/ea/xmi_class_instantiator.rb +0 -46
  128. data/lib/ea/xmi_helper.rb +0 -26
  129. data/lib/ea/xmi_metamodel.rb +0 -34
  130. data/lib/ea/xmi_object_instantiator.rb +0 -46
  131. data/lib/ea/xmi_to_classmodel.rb +0 -78
  132. data/lib/ea/xmi_to_objectmodel.rb +0 -92
  133. data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +0 -71
  134. data/lib/mmgen/templates/uml_classmodel.tpl +0 -63
  135. data/lib/rgen/xml_instantiator.rb +0 -132
  136. data/lib/uml/objectmodel_instantiator.rb +0 -53
  137. data/lib/uml/uml_classmodel.rb +0 -92
  138. data/lib/uml/uml_objectmodel.rb +0 -65
  139. data/test/metamodel_generator_test.rb +0 -44
  140. data/test/metamodel_generator_test/TestModel.rb +0 -40
  141. data/test/metamodel_generator_test/expected_result.txt +0 -40
  142. data/test/xmi_class_instantiator_test.rb +0 -24
  143. data/test/xmi_instantiator_test/class_model_checker.rb +0 -97
  144. data/test/xmi_object_instantiator_test.rb +0 -65
  145. data/test/xml_instantiator_test/testmodel.xml +0 -7
@@ -0,0 +1,352 @@
1
+ #
2
+ # xmlscan/namespace.rb
3
+ #
4
+ # Copyright (C) Ueno Katsuhiro 2002
5
+ #
6
+ # $Id: namespace.rb,v 1.13 2003/01/22 13:06:18 katsu Exp $
7
+ #
8
+
9
+ require 'xmlscan/parser'
10
+
11
+
12
+ module XMLScan
13
+
14
+ class NSParseError < ParseError ; end
15
+ class NSNotWellFormedError < NotWellFormedError ; end
16
+ class NSNotValidError < NotValidError ; end
17
+
18
+
19
+ module NSVisitor
20
+
21
+ include Visitor
22
+
23
+ def ns_parse_error(msg)
24
+ raise NSParseError.new(msg)
25
+ end
26
+
27
+ def ns_wellformed_error(msg)
28
+ raise NSNotWellFormedError.new(msg)
29
+ end
30
+
31
+ def ns_valid_error(msg)
32
+ raise NSNotValidError.new(msg)
33
+ end
34
+
35
+ #
36
+ # <foo:bar hoge:fuga='' hoge='' >
37
+ # <foo hoge:fuga='' hoge='' >
38
+ # ^ ^ ^ ^ ^ ^
39
+ # 1 2 3 4 5 6
40
+ #
41
+ # The following method will be called with the following arguments
42
+ # when the parser reaches the above point;
43
+ #
44
+ # 1: on_stag_ns ('foo:bar', 'foo', 'bar')
45
+ # or
46
+ # on_stag_ns ('foo', '', 'foo')
47
+ # 2: on_attribute_ns ('hoge:fuga', 'hoge', 'fuga')
48
+ # 3: on_attribute_end ('hoge:fuga')
49
+ # 4: on_attribute_ns ('hoge', nil, 'hoge')
50
+ # 5: on_attribute_end ('hoge')
51
+ # 6: on_stag_end_ns ('foo:bar', { 'foo' => '', ... })
52
+ # or
53
+ # on_stag_end_empty_ns ('foo:bar', { 'foo' => '', ... })
54
+ #
55
+
56
+ def on_stag_ns(qname, prefix, localpart)
57
+ end
58
+
59
+ def on_attribute_ns(qname, prefix, localpart)
60
+ end
61
+
62
+ def on_stag_end_ns(qname, namespaces)
63
+ end
64
+
65
+ def on_stag_end_empty_ns(qname, namespaces)
66
+ end
67
+
68
+ end
69
+
70
+
71
+
72
+
73
+ class XMLNamespaceDecoration < Decoration
74
+
75
+ proc {
76
+ h = {'foo'=>true} ; h['foo'] = nil
77
+ raise "requires Ruby-1.6 or above" unless h.key? 'foo'
78
+ }.call
79
+
80
+ PredefinedNamespace = {
81
+ 'xml' => 'http://www.w3.org/XML/1998/namespace',
82
+ 'xmlns' => 'http://www.w3.org/2000/xmlns/',
83
+ }
84
+
85
+ ReservedNamespace = PredefinedNamespace.invert
86
+
87
+
88
+ def ns_parse_error(msg)
89
+ @orig_visitor.ns_parse_error msg
90
+ end
91
+
92
+ def ns_wellformed_error(msg)
93
+ @orig_visitor.ns_wellformed_error msg
94
+ end
95
+
96
+ def ns_valid_error(msg)
97
+ @orig_visitor.ns_valid_error msg
98
+ end
99
+
100
+
101
+ def on_start_document
102
+ @namespace = {} #PredefinedNamespace.dup
103
+ @ns_hist = []
104
+ @ns_undeclared = {} # for checking undeclared namespace prefixes.
105
+ @prev_prefix = {} # for checking doubled attributes.
106
+ @dont_same = [] # ditto.
107
+ @xmlns = NamespaceDeclaration.new(self)
108
+ @orig_visitor = @visitor
109
+ @visitor.on_start_document
110
+ end
111
+
112
+
113
+ def on_stag(name)
114
+ @ns_hist.push nil
115
+ unless /:/n =~ name then
116
+ @visitor.on_stag_ns name, '', name
117
+ else
118
+ prefix, localpart = $`, $'
119
+ if localpart.include? ?: then
120
+ ns_parse_error "localpart `#{localpart}' includes `:'"
121
+ end
122
+ if prefix == 'xmlns' then
123
+ ns_wellformed_error \
124
+ "prefix `xmlns' is not used for namespace prefix declaration"
125
+ end
126
+ unless @namespace.key? prefix then
127
+ if uri = PredefinedNamespace[prefix] then
128
+ @namespace[prefix] = uri
129
+ else
130
+ @ns_undeclared[prefix] = true
131
+ end
132
+ end
133
+ @visitor.on_stag_ns name, prefix, localpart
134
+ end
135
+ end
136
+
137
+
138
+ def on_attribute(name)
139
+ if /:/n =~ name then
140
+ prefix, localpart = $`, $'
141
+ if localpart.include? ?: then
142
+ ns_parse_error "localpart `#{localpart}' includes `:'"
143
+ end
144
+ unless @namespace.key? prefix then
145
+ if uri = PredefinedNamespace[prefix] then
146
+ @namespace[prefix] = uri
147
+ else
148
+ @ns_undeclared[prefix] = true
149
+ end
150
+ end
151
+ if prefix == 'xmlns' then
152
+ @visitor = @xmlns
153
+ @xmlns.on_xmlns_start localpart
154
+ else
155
+ if prev = @prev_prefix[localpart] then
156
+ @dont_same.push [ prev, prefix, localpart ]
157
+ end
158
+ @prev_prefix[localpart] = prefix
159
+ @visitor.on_attribute_ns name, prefix, localpart
160
+ end
161
+ elsif name == 'xmlns' then
162
+ @visitor = @xmlns
163
+ @xmlns.on_xmlns_start ''
164
+ else
165
+ @visitor.on_attribute_ns name, nil, name
166
+ end
167
+ end
168
+
169
+
170
+ class NamespaceDeclaration
171
+
172
+ include XMLScan::Visitor
173
+
174
+ def initialize(parent)
175
+ @parent = parent
176
+ end
177
+
178
+ def on_xmlns_start(prefix)
179
+ @prefix = prefix
180
+ @nsdecl = ''
181
+ end
182
+
183
+ def on_attr_value(str)
184
+ @nsdecl << str
185
+ end
186
+
187
+ def on_attr_entityref(ref)
188
+ @parent.ns_wellformed_error \
189
+ "xmlns includes undeclared entity reference"
190
+ end
191
+
192
+ def on_attr_charref(code)
193
+ @nsdecl << [code].pack('U')
194
+ end
195
+
196
+ def on_attr_charref_hex(code)
197
+ @nsdecl << [code].pack('U')
198
+ end
199
+
200
+ def on_attribute_end(name)
201
+ @parent.on_xmlns_end @prefix, @nsdecl
202
+ end
203
+
204
+ end
205
+
206
+
207
+ def on_xmlns_end(prefix, uri)
208
+ @visitor = @orig_visitor
209
+ if PredefinedNamespace.key? prefix then
210
+ if prefix == 'xmlns' then
211
+ ns_wellformed_error \
212
+ "prefix `xmlns' can't be bound to any namespace explicitly"
213
+ elsif (s = PredefinedNamespace[prefix]) != uri then
214
+ ns_wellformed_error \
215
+ "prefix `#{prefix}' can't be bound to any namespace except `#{s}'"
216
+ end
217
+ end
218
+ if uri.empty? then
219
+ if prefix.empty? then
220
+ uri = nil
221
+ else
222
+ ns_parse_error "`#{prefix}' is bound to empty namespace name"
223
+ end
224
+ elsif ReservedNamespace.key? uri then
225
+ unless (s = ReservedNamespace[uri]) == prefix then
226
+ ns_wellformed_error \
227
+ "namespace `#{uri}' is reserved for prefix `#{s}'"
228
+ end
229
+ end
230
+ (@ns_hist.last || @ns_hist[-1] = {})[prefix] = @namespace[prefix]
231
+ @namespace[prefix] = uri
232
+ @ns_undeclared.delete prefix
233
+ end
234
+
235
+
236
+ def fix_namespace
237
+ unless @ns_undeclared.empty? then
238
+ @ns_undeclared.each_key { |i|
239
+ @visitor.ns_wellformed_error "prefix `#{i}' is not declared"
240
+ }
241
+ @ns_undeclared.clear
242
+ end
243
+ unless @dont_same.empty? then
244
+ @dont_same.each { |n1,n2,l|
245
+ if @namespace[n1] == @namespace[n2] then
246
+ ns_wellformed_error \
247
+ "doubled localpart `#{l}' in the same namespace"
248
+ end
249
+ }
250
+ @dont_same.clear
251
+ end
252
+ @prev_prefix.clear
253
+ end
254
+
255
+
256
+ def on_stag_end(name)
257
+ fix_namespace
258
+ @visitor.on_stag_end_ns name, @namespace
259
+ end
260
+
261
+
262
+ def on_etag(name)
263
+ h = @ns_hist.pop and @namespace.update h
264
+ @visitor.on_etag name
265
+ end
266
+
267
+
268
+ def on_stag_end_empty(name)
269
+ fix_namespace
270
+ @visitor.on_stag_end_empty_ns name, @namespace
271
+ h = @ns_hist.pop and @namespace.update h
272
+ end
273
+
274
+
275
+ def on_doctype(root, pubid, sysid)
276
+ if root.count(':') > 1 then
277
+ ns_parse_error "qualified name `#{root}' includes `:'"
278
+ end
279
+ @visitor.on_doctype root, pubid, sysid
280
+ end
281
+
282
+
283
+ def on_pi(target, pi)
284
+ if target.include? ?: then
285
+ ns_parse_error "PI target `#{target}' includes `:'"
286
+ end
287
+ @visitor.on_pi target, pi
288
+ end
289
+
290
+
291
+ def on_entityref(ref)
292
+ if ref.include? ?: then
293
+ ns_parse_error "entity reference `#{ref}' includes `:'"
294
+ end
295
+ @visitor.on_entityref ref
296
+ end
297
+
298
+
299
+ def on_attr_entityref(ref)
300
+ if ref.include? ?: then
301
+ ns_parse_error "entity reference `#{ref}' includes `:'"
302
+ end
303
+ @visitor.on_attr_entityref ref
304
+ end
305
+
306
+ end
307
+
308
+
309
+
310
+ class XMLParserNS < XMLParser
311
+
312
+ def initialize(*)
313
+ super
314
+ @visitor = @decoration = XMLNamespaceDecoration.new(@visitor)
315
+ end
316
+
317
+ end
318
+
319
+ end
320
+
321
+
322
+
323
+
324
+
325
+ if $0 == __FILE__ then
326
+ class TestVisitor
327
+ include XMLScan::NSVisitor
328
+ def parse_error(msg)
329
+ STDERR.printf("%s:%d: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
330
+ end
331
+ def wellformed_error(msg)
332
+ STDERR.printf("%s:%d: WFC: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
333
+ end
334
+ def warning(msg)
335
+ STDERR.printf("%s:%d: warning: %s\n", $s.path,$s.lineno, msg) if $VERBOSE
336
+ end
337
+ def ns_parse_error(msg)
338
+ STDERR.printf("%s:%d: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
339
+ end
340
+ def ns_wellformed_error(msg)
341
+ STDERR.printf("%s:%d: NSC: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
342
+ end
343
+ end
344
+
345
+ $s = scan = XMLScan::XMLParserNS.new(TestVisitor.new)
346
+ src = ARGF
347
+ def src.path; filename; end
348
+ t1 = Time.times.utime
349
+ scan.parse src
350
+ t2 = Time.times.utime
351
+ STDERR.printf "%2.3f sec\n", t2 - t1
352
+ end
@@ -0,0 +1,299 @@
1
+ #
2
+ # xmlscan/parser.rb
3
+ #
4
+ # Copyright (C) Ueno Katsuhiro 2002
5
+ #
6
+ # $Id: parser.rb,v 1.10 2003/01/22 13:06:18 katsu Exp $
7
+ #
8
+
9
+ require 'xmlscan/scanner'
10
+
11
+
12
+ module XMLScan
13
+
14
+ class XMLParser < XMLScanner
15
+
16
+ class AttributeChecker < Hash
17
+ # AttributeChecker inherits Hash only for speed.
18
+
19
+ def check_unique(name)
20
+ not key? name and store(name, true)
21
+ end
22
+
23
+ end
24
+
25
+
26
+ #PredefinedEntity = {
27
+ # 'lt' => '<',
28
+ # 'gt' => '>',
29
+ # 'amp' => '&',
30
+ # 'quot' => '"',
31
+ # 'apos' => "'",
32
+ #}
33
+
34
+
35
+ def parse(*)
36
+ @elem = []
37
+ @attr = AttributeChecker.new
38
+ @standalone = nil
39
+ super
40
+ end
41
+
42
+
43
+ private
44
+
45
+ def on_xmldecl_version(str)
46
+ unless str == '1.0' then
47
+ warning "unsupported XML version `#{str}'"
48
+ end
49
+ @visitor.on_xmldecl_version str
50
+ end
51
+
52
+
53
+ def on_xmldecl_standalone(str)
54
+ if str == 'yes' then
55
+ @standalone = true
56
+ elsif str == 'no' then
57
+ @standalone = false
58
+ else
59
+ parse_error "standalone declaration must be either `yes' or `no'"
60
+ end
61
+ @visitor.on_xmldecl_standalone str
62
+ end
63
+
64
+
65
+ def on_doctype(name, pubid, sysid)
66
+ if pubid and not sysid then
67
+ parse_error "public external ID must have both public ID and system ID"
68
+ end
69
+ @visitor.on_doctype name, pubid, sysid
70
+ end
71
+
72
+
73
+ def on_prolog_space(s)
74
+ # just ignore it.
75
+ end
76
+
77
+
78
+ def on_pi(target, pi)
79
+ if target.downcase == 'xml' then
80
+ parse_error "reserved PI target `#{target}'"
81
+ end
82
+ @visitor.on_pi target, pi
83
+ end
84
+
85
+
86
+ #def on_entityref(ref)
87
+ # rep = PredefinedEntity[ref]
88
+ # if rep then
89
+ # @visitor.on_chardata rep
90
+ # else
91
+ # @visitor.on_entityref ref
92
+ # end
93
+ #end
94
+
95
+
96
+ #def on_attr_entityref(ref)
97
+ # rep = PredefinedEntity[ref]
98
+ # if rep then
99
+ # @visitor.on_attr_value rep
100
+ # else
101
+ # @visitor.on_attr_entityref ref
102
+ # end
103
+ #end
104
+
105
+
106
+ #def on_charref_hex(code)
107
+ # on_charref code
108
+ #end
109
+
110
+
111
+ #def on_attr_charref_hex(code)
112
+ # on_attr_charref code
113
+ #end
114
+
115
+
116
+ def on_stag(name)
117
+ @elem.push name
118
+ @visitor.on_stag name
119
+ @attr.clear
120
+ end
121
+
122
+ def on_attribute(name)
123
+ unless @attr.check_unique name then
124
+ wellformed_error "doubled attribute `#{name}'"
125
+ end
126
+ @visitor.on_attribute name
127
+ end
128
+
129
+ def on_attr_value(str)
130
+ str.tr! "\t\r\n", ' ' # normalize
131
+ @visitor.on_attr_value str
132
+ end
133
+
134
+ def on_stag_end_empty(name)
135
+ # @visitor.on_stag_end name
136
+ # @elem.pop
137
+ # @visitor.on_etag name
138
+ @visitor.on_stag_end_empty name
139
+ @elem.pop
140
+ end
141
+
142
+ def on_etag(name)
143
+ last = @elem.pop
144
+ if last == name then
145
+ @visitor.on_etag name
146
+ elsif last then
147
+ wellformed_error "element type `#{name}' is not matched"
148
+ @visitor.on_etag last
149
+ else
150
+ parse_error "end tag `#{name}' appears alone"
151
+ end
152
+ end
153
+
154
+
155
+ public
156
+
157
+
158
+ def scan_content(s)
159
+ elem = @elem # for speed
160
+ src = @src # for speed
161
+ found_root_element = false
162
+
163
+ begin
164
+
165
+ # -- first start tag --
166
+ elem.clear
167
+ found_stag = false
168
+
169
+ while s and not found_stag
170
+ if (c = s[0]) == ?< then
171
+ if (c = s[1]) == ?/ then
172
+ # should be a parse error
173
+ scan_etag s
174
+ elsif c == ?! then
175
+ if s[2] == ?- and s[3] == ?- then
176
+ scan_comment s
177
+ elsif /\A<!\[CDATA\[/n =~ s then
178
+ parse_error "CDATA section is found outside of root element"
179
+ scan_cdata $'
180
+ else
181
+ scan_bang_tag s
182
+ end
183
+ elsif c == ?? then
184
+ scan_pi s
185
+ else
186
+ found_root_element = true
187
+ found_stag = true
188
+ scan_stag s
189
+ end
190
+ else
191
+ parse_error "content of element is found outside of root element"
192
+ scan_chardata s
193
+ end
194
+ s = src.get
195
+ end
196
+
197
+ if not found_root_element and not found_stag then
198
+ parse_error "no root element was found"
199
+ end
200
+
201
+ # -- contents --
202
+ while s and not elem.empty?
203
+ if (c = s[0]) == ?< then
204
+ if (c = s[1]) == ?/ then
205
+ scan_etag s
206
+ elsif c == ?! then
207
+ if s[2] == ?- and s[3] == ?- then
208
+ scan_comment s
209
+ elsif /\A<!\[CDATA\[/n =~ s then
210
+ scan_cdata $'
211
+ else
212
+ scan_bang_tag s
213
+ end
214
+ elsif c == ?? then
215
+ scan_pi s
216
+ else
217
+ scan_stag s
218
+ end
219
+ else
220
+ scan_chardata s
221
+ end
222
+ s = src.get
223
+ end
224
+
225
+ unless elem.empty? then
226
+ while name = elem.pop
227
+ parse_error "unclosed element `#{name}' meets EOF"
228
+ @visitor.on_etag name
229
+ end
230
+ end
231
+
232
+ # -- epilogue --
233
+ finish = true
234
+
235
+ while s
236
+ if (c = s[0]) == ?< then
237
+ if (c = s[1]) == ?/ then
238
+ finish = false # content out of root element
239
+ break
240
+ elsif c == ?! then
241
+ if s[2] == ?- and s[3] == ?- then
242
+ scan_comment s
243
+ else
244
+ finish = false # content out of root element
245
+ break
246
+ end
247
+ elsif c == ?? then
248
+ scan_pi s
249
+ else
250
+ parse_error "another root element is found" # stag
251
+ finish = false
252
+ break
253
+ end
254
+ else
255
+ if s.strip.empty? then
256
+ on_prolog_space s
257
+ else
258
+ finish = false # content out of root element
259
+ break
260
+ end
261
+ end
262
+ s = src.get
263
+ end
264
+
265
+ end until finish
266
+
267
+ end
268
+ end
269
+
270
+
271
+ end
272
+
273
+
274
+
275
+
276
+
277
+
278
+ if $0 == __FILE__ then
279
+ class TestVisitor
280
+ include XMLScan::Visitor
281
+ def parse_error(msg)
282
+ STDERR.printf("%s:%d: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
283
+ end
284
+ def wellformed_error(msg)
285
+ STDERR.printf("%s:%d: WFC: %s\n", $s.path, $s.lineno, msg) if $VERBOSE
286
+ end
287
+ def warning(msg)
288
+ STDERR.printf("%s:%d: warning: %s\n", $s.path,$s.lineno, msg) if $VERBOSE
289
+ end
290
+ end
291
+
292
+ $s = scan = XMLScan::XMLParser.new(TestVisitor.new)
293
+ src = ARGF
294
+ def src.path; filename; end
295
+ t1 = Time.times.utime
296
+ scan.parse src
297
+ t2 = Time.times.utime
298
+ STDERR.printf "%2.3f sec\n", t2 - t1
299
+ end