rgen 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +20 -1
- data/MIT-LICENSE +1 -1
- data/README +12 -9
- data/lib/instantiators/ea_instantiator.rb +36 -0
- data/lib/metamodels/uml13_metamodel.rb +559 -0
- data/lib/metamodels/uml13_metamodel_ext.rb +26 -0
- data/lib/mmgen/metamodel_generator.rb +5 -5
- data/lib/mmgen/mm_ext/ecore_ext.rb +95 -0
- data/lib/mmgen/mmgen.rb +6 -4
- data/lib/mmgen/templates/annotations.tpl +37 -0
- data/lib/mmgen/templates/metamodel_generator.tpl +171 -0
- data/lib/rgen/ecore/ecore.rb +190 -0
- data/lib/rgen/ecore/ecore_instantiator.rb +25 -0
- data/lib/rgen/ecore/ecore_transformer.rb +85 -0
- data/lib/rgen/environment.rb +9 -24
- data/lib/rgen/find_helper.rb +68 -0
- data/lib/rgen/{instantiator.rb → instantiator/abstract_instantiator.rb} +6 -2
- data/lib/rgen/instantiator/abstract_xml_instantiator.rb +59 -0
- data/lib/rgen/instantiator/default_xml_instantiator.rb +117 -0
- data/lib/rgen/instantiator/ecore_xml_instantiator.rb +144 -0
- data/lib/rgen/instantiator/nodebased_xml_instantiator.rb +157 -0
- data/lib/rgen/instantiator/xmi11_instantiator.rb +164 -0
- data/lib/rgen/metamodel_builder.rb +103 -9
- data/lib/rgen/metamodel_builder/build_helper.rb +26 -4
- data/lib/rgen/metamodel_builder/builder_extensions.rb +285 -88
- data/lib/rgen/metamodel_builder/builder_runtime.rb +7 -1
- data/lib/rgen/metamodel_builder/data_types.rb +67 -0
- data/lib/rgen/metamodel_builder/intermediate/annotation.rb +30 -0
- data/lib/rgen/metamodel_builder/metamodel_description.rb +232 -0
- data/lib/rgen/metamodel_builder/mm_multiple.rb +23 -0
- data/lib/rgen/metamodel_builder/module_extension.rb +33 -0
- data/lib/rgen/model_comparator.rb +56 -0
- data/lib/rgen/model_dumper.rb +5 -5
- data/lib/rgen/name_helper.rb +17 -1
- data/lib/rgen/template_language.rb +148 -28
- data/lib/rgen/template_language/directory_template_container.rb +56 -38
- data/lib/rgen/template_language/output_handler.rb +93 -77
- data/lib/rgen/template_language/template_container.rb +186 -143
- data/lib/rgen/transformer.rb +19 -14
- data/lib/transformers/uml13_to_ecore.rb +75 -0
- data/redist/xmlscan/ChangeLog +1301 -0
- data/redist/xmlscan/README +34 -0
- data/redist/xmlscan/THANKS +11 -0
- data/redist/xmlscan/doc/changes.html +74 -0
- data/redist/xmlscan/doc/changes.rd +80 -0
- data/redist/xmlscan/doc/en/conformance.html +136 -0
- data/redist/xmlscan/doc/en/conformance.rd +152 -0
- data/redist/xmlscan/doc/en/manual.html +356 -0
- data/redist/xmlscan/doc/en/manual.rd +402 -0
- data/redist/xmlscan/doc/ja/conformance.ja.html +118 -0
- data/redist/xmlscan/doc/ja/conformance.ja.rd +134 -0
- data/redist/xmlscan/doc/ja/manual.ja.html +325 -0
- data/redist/xmlscan/doc/ja/manual.ja.rd +370 -0
- data/redist/xmlscan/doc/src/Makefile +41 -0
- data/redist/xmlscan/doc/src/conformance.rd.src +256 -0
- data/redist/xmlscan/doc/src/langsplit.rb +110 -0
- data/redist/xmlscan/doc/src/manual.rd.src +614 -0
- data/redist/xmlscan/install.rb +41 -0
- data/redist/xmlscan/lib/xmlscan/encoding.rb +311 -0
- data/redist/xmlscan/lib/xmlscan/htmlscan.rb +289 -0
- data/redist/xmlscan/lib/xmlscan/namespace.rb +352 -0
- data/redist/xmlscan/lib/xmlscan/parser.rb +299 -0
- data/redist/xmlscan/lib/xmlscan/scanner.rb +1109 -0
- data/redist/xmlscan/lib/xmlscan/version.rb +22 -0
- data/redist/xmlscan/lib/xmlscan/visitor.rb +158 -0
- data/redist/xmlscan/lib/xmlscan/xmlchar.rb +441 -0
- data/redist/xmlscan/memo/CONFORMANCE +1249 -0
- data/redist/xmlscan/memo/PRODUCTIONS +195 -0
- data/redist/xmlscan/memo/contentspec.ry +335 -0
- data/redist/xmlscan/samples/chibixml.rb +105 -0
- data/redist/xmlscan/samples/getxmlchar.rb +122 -0
- data/redist/xmlscan/samples/rexml.rb +159 -0
- data/redist/xmlscan/samples/xmlbench.rb +88 -0
- data/redist/xmlscan/samples/xmlbench/parser/chibixml.rb +22 -0
- data/redist/xmlscan/samples/xmlbench/parser/nqxml.rb +29 -0
- data/redist/xmlscan/samples/xmlbench/parser/rexml.rb +62 -0
- data/redist/xmlscan/samples/xmlbench/parser/xmlparser.rb +22 -0
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-0.0.10.rb +62 -0
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-chibixml.rb +22 -0
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan-rexml.rb +22 -0
- data/redist/xmlscan/samples/xmlbench/parser/xmlscan.rb +99 -0
- data/redist/xmlscan/samples/xmlbench/xmlbench-lib.rb +116 -0
- data/redist/xmlscan/samples/xmlconftest.rb +200 -0
- data/redist/xmlscan/test.rb +7 -0
- data/redist/xmlscan/tests/deftestcase.rb +73 -0
- data/redist/xmlscan/tests/runtest.rb +47 -0
- data/redist/xmlscan/tests/testall.rb +14 -0
- data/redist/xmlscan/tests/testencoding.rb +438 -0
- data/redist/xmlscan/tests/testhtmlscan.rb +752 -0
- data/redist/xmlscan/tests/testnamespace.rb +457 -0
- data/redist/xmlscan/tests/testparser.rb +591 -0
- data/redist/xmlscan/tests/testscanner.rb +1749 -0
- data/redist/xmlscan/tests/testxmlchar.rb +143 -0
- data/redist/xmlscan/tests/visitor.rb +34 -0
- data/test/array_extensions_test.rb +2 -2
- data/test/ea_instantiator_test.rb +41 -0
- data/test/ecore_self_test.rb +53 -0
- data/test/environment_test.rb +11 -6
- data/test/metamodel_builder_test.rb +404 -245
- data/test/metamodel_roundtrip_test.rb +52 -0
- data/test/metamodel_roundtrip_test/TestModel.rb +65 -0
- data/test/metamodel_roundtrip_test/TestModel_Regenerated.rb +64 -0
- data/test/metamodel_roundtrip_test/houseMetamodel.ecore +32 -0
- data/test/metamodel_roundtrip_test/houseMetamodel_from_ecore.rb +39 -0
- data/test/rgen_test.rb +3 -3
- data/test/template_language_test.rb +65 -39
- data/test/template_language_test/expected_result.txt +24 -3
- data/test/template_language_test/templates/code/array.tpl +11 -0
- data/test/template_language_test/templates/content/author.tpl +7 -0
- data/test/template_language_test/templates/content/chapter.tpl +1 -1
- data/test/template_language_test/templates/root.tpl +17 -8
- data/test/template_language_test/testout.txt +24 -3
- data/test/testmodel/class_model_checker.rb +119 -0
- data/test/{xmi_instantiator_test/testmodel.eap → testmodel/ea_testmodel.eap} +0 -0
- data/test/{xmi_instantiator_test/testmodel.xml → testmodel/ea_testmodel.xml} +81 -14
- data/test/testmodel/ea_testmodel_partial.xml +317 -0
- data/test/testmodel/ecore_model_checker.rb +101 -0
- data/test/testmodel/manual_testmodel.xml +22 -0
- data/test/testmodel/object_model_checker.rb +67 -0
- data/test/transformer_test.rb +18 -10
- data/test/xml_instantiator_test.rb +81 -8
- data/test/xml_instantiator_test/simple_ecore_model_checker.rb +94 -0
- data/test/xml_instantiator_test/simple_xmi_ecore_instantiator.rb +53 -0
- data/test/xml_instantiator_test/simple_xmi_metamodel.rb +49 -0
- data/test/xml_instantiator_test/simple_xmi_to_ecore.rb +75 -0
- metadata +126 -28
- data/lib/ea/xmi_class_instantiator.rb +0 -46
- data/lib/ea/xmi_helper.rb +0 -26
- data/lib/ea/xmi_metamodel.rb +0 -34
- data/lib/ea/xmi_object_instantiator.rb +0 -46
- data/lib/ea/xmi_to_classmodel.rb +0 -78
- data/lib/ea/xmi_to_objectmodel.rb +0 -92
- data/lib/mmgen/mm_ext/uml_classmodel_ext.rb +0 -71
- data/lib/mmgen/templates/uml_classmodel.tpl +0 -63
- data/lib/rgen/xml_instantiator.rb +0 -132
- data/lib/uml/objectmodel_instantiator.rb +0 -53
- data/lib/uml/uml_classmodel.rb +0 -92
- data/lib/uml/uml_objectmodel.rb +0 -65
- data/test/metamodel_generator_test.rb +0 -44
- data/test/metamodel_generator_test/TestModel.rb +0 -40
- data/test/metamodel_generator_test/expected_result.txt +0 -40
- data/test/xmi_class_instantiator_test.rb +0 -24
- data/test/xmi_instantiator_test/class_model_checker.rb +0 -97
- data/test/xmi_object_instantiator_test.rb +0 -65
- 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
|