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.
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,195 @@
1
+ $Id: PRODUCTIONS,v 1.3 2003/01/19 14:35:49 katsu Exp $
2
+
3
+ == $B<BAu$N40N;$7$F$$$k$b$N!#(B
4
+
5
+ $B$3$l$i$N@8@.5,B'$K%^%C%A$9$k$3$H$,4|BT$5$l$kJ8L.$K$*$$$F!"4|BT$5$l$k@8@.5,B'$K(B
6
+ $B%^%C%A$7$J$+$C$?>l9g$O!">o$K(B parse error $B$H$J$k!#(B
7
+
8
+
9
+ XMLScan::XMLScanner $B$G<BAu$5$l$F$$$k$b$N!#(B
10
+
11
+ [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
12
+ | ("'" ([^<&'] | Reference)* "'")
13
+ [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
14
+ [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
15
+ [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))?
16
+ '?>'
17
+ [18] CDSect ::= CDStart CData CDEnd
18
+ [19] CDStart ::= '<![CDATA['
19
+ [20] CData ::= (Char* - (Char* ']]>' Char*))
20
+ [21] CDEnd ::= ']]>'
21
+ [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
22
+ [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
23
+ [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" |
24
+ '"' VersionNum '"')
25
+ [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
26
+ | ('"' ('yes' | 'no') '"'))
27
+ [40] STag ::= '<' Name (S Attribute)* S? '>'
28
+ [41] Attribute ::= Name Eq AttValue
29
+ [42] ETag ::= '</' Name S? '>'
30
+ [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
31
+ [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
32
+ [68] EntityRef ::= '&' Name ';'
33
+ [80] EncodingDecl ::= S 'encoding' Eq
34
+ ('"' EncName '"' | "'" EncName "'")
35
+
36
+
37
+ XMLScan::XMLParser $B$G<BAu$5$l$F$$$k$b$N!#(B
38
+
39
+ [1] document ::= prolog element Misc*
40
+ [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
41
+ [43] content ::= CharData? ((element | Reference | CDSect | PI
42
+ | Comment) CharData?)*
43
+ [39] element ::= EmptyElemTag | STag content ETag
44
+
45
+
46
+
47
+
48
+ == $B<BAu$7$F$$$k$,!"B>$N@8@.5,B'Cf$K%$%s%i%$%s$GE83+$7$?$b$N!#(B
49
+
50
+ XMLScan::XMLScanner $B$G<BAu$5$l$F$$$k$b$N!#(B
51
+
52
+ [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
53
+ [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
54
+ [25] Eq ::= S? '=' S?
55
+ [27] Misc ::= Comment | PI | S
56
+ [67] Reference ::= EntityRef | CharRef
57
+ [75] ExternalID ::= 'SYSTEM' S SystemLiteral
58
+ | 'PUBLIC' S PubidLiteral S SystemLiteral
59
+
60
+
61
+
62
+
63
+ == $B<BAu$7$F$$$k$,!"@8@.5,B'$K<c43JQ99$r2C$($F$$$k$b$N!#(B
64
+
65
+ XMLScan::XMLScanner $B$O(B ExternalID $B$N@8@.5,B'$r(B
66
+ ExternalID ::= 'SYSTEM' S SystemLiteral
67
+ | 'PUBLIC' S PubidLiteral S SystemLiteral?
68
+ $B$H$7$F2r@O!#(BXMLScan::XMLParser $B$,(B SystemLiteral $B$r;}$?$J$$8x3+<1JL;R$N(B
69
+ $B%A%'%C%/$r9T$&!#(B
70
+
71
+ [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
72
+ ('[' (markupdecl | DeclSep)* ']' S?)? '>'
73
+
74
+
75
+
76
+
77
+ == $BL$Ce<j$@$,Ce<jM=Dj$N$b$N!#(B
78
+
79
+ $BFbIt(B DTD $B%5%V%;%C%H$K4X$9$k$b$N!#(B
80
+
81
+ [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
82
+ | ("'" ([^%&'] | PEReference | Reference)* "'")
83
+ [28a] DeclSep ::= PEReference | S
84
+ [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl
85
+ | NotationDecl | PI | Comment
86
+ [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
87
+ [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
88
+ [53] AttDef ::= S Name S AttType S DefaultDecl
89
+ [54] AttType ::= StringType | TokenizedType | EnumeratedType
90
+ [55] StringType ::= 'CDATA'
91
+ [56] TokenizedType ::= 'ID'
92
+ [57] EnumeratedType ::= NotationType | Enumeration
93
+ [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
94
+ [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
95
+ [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue
96
+ [69] PEReference ::= '%' Name ';'
97
+ [70] EntityDecl ::= GEDecl | PEDecl
98
+ [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
99
+ [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
100
+ [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
101
+ [74] PEDef ::= EntityValue | ExternalID
102
+ [76] NDataDecl ::= S 'NDATA' S Name
103
+ [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID)
104
+ S? '>'
105
+ [83] PublicID ::= 'PUBLIC' S PubidLiteral
106
+
107
+
108
+
109
+ == $BCe<jM=DjL5$+$C$?$1$ICe<j$7$A$c$C$?$b$N!#(B
110
+
111
+ $BMWAGFbMF%b%G%k$N@53N$J9=J82r@O$O$d$i$J$$$+$b!#(B
112
+ $B$C$F8@$C$F$?$N$K(B($B>P(B)$B!#(B> contentspec.ry
113
+
114
+ [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
115
+ [47] children ::= (choice | seq) ('?' | '*' | '+')?
116
+ [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
117
+ [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
118
+ [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
119
+ [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
120
+ | '(' S? '#PCDATA' S? ')'
121
+
122
+
123
+
124
+ == $BL$Ce<j$GCe<jM=Dj$N$J$$$b$N!#(B
125
+
126
+ $B30It<BBN$K4X$9$k$b$NEy!#(B
127
+
128
+ $B$3$l$i$O30It(BDTD$B%5%V%;%C%H$G$J$$$HMQL5$7!#(B
129
+
130
+ [30] extSubset ::= TextDecl? extSubsetDecl
131
+ [31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)*
132
+ [61] conditionalSect ::= includeSect | ignoreSect
133
+ [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
134
+ [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
135
+ [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
136
+ [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
137
+
138
+ $B$3$l$i$O30It2r@OBP>]<BBN$G$J$$$HMQL5$7!#(B
139
+
140
+ [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
141
+ [78] extParsedEnt ::= TextDecl? content
142
+
143
+ $B$3$l$i$OB0@-CM$NBEEv@-$r8!>Z$7$J$$$J$iMQL5$7!#(B
144
+
145
+ [6] Names ::= Name (S Name)*
146
+ [8] Nmtokens ::= Nmtoken (S Nmtoken)*
147
+
148
+
149
+
150
+
151
+ == $BJ8;z$dL>A0$K4X$9$k$b$N!#(B
152
+
153
+ /[ \t\n\r]+/ $B$H$7$FB>$N@8@.5,B'Fb$KE83+$5$l$k!#(B
154
+ Ruby $B$N(B \s $B$O(B #xC $B$r4^$s$G$7$^$&$N$G87L)$K$O(B S $B$H0lCW$7$J$$$3$H$KCm0U!#(B
155
+
156
+ [3] S ::= (#x20 | #x9 | #xD | #xA)+
157
+
158
+
159
+ $B0J2<$O87L)$K<BAu$9$k$HIi2Y$,$+$+$C$F7y$J$N$G%G%U%)%k%H$G$OL58z!#(B
160
+ $B%*%W%7%g%s$H$7$FA*Br$9$k$3$H$,$G$-$k!#(B
161
+
162
+
163
+ XMLScan::XMLChar::valid_char?
164
+
165
+ [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
166
+ | [#x10000-#x10FFFF]
167
+
168
+ XMLScan::XMLChar::valid_nmtoken?
169
+
170
+ [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
171
+ | CombiningChar | Extender
172
+ [7] Nmtoken ::= (NameChar)+
173
+ [84] Letter ::= BaseChar | Ideographic
174
+ [85] BaseChar ::= ...
175
+ [86] Ideographic ::= ...
176
+ [87] CombiningChar ::= ...
177
+ [88] Digit ::= ...
178
+ [89] Extender ::= ...
179
+
180
+ XMLScan::XMLChar::valid_name?
181
+
182
+ [5] Name ::= (Letter | '_' | ':') (NameChar)*
183
+
184
+ XMLScan::XMLChar::valid_pubid?
185
+
186
+ [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9]
187
+ | [-'()+,./:=?;!*#@$_%]
188
+
189
+ XMLScan::XMLChar::valid_versionnum?
190
+
191
+ [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
192
+
193
+ XMLScan::XMLChar::valid_encname?
194
+
195
+ [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
@@ -0,0 +1,335 @@
1
+ # $Id: contentspec.ry,v 1.2 2003/01/19 22:38:46 katsu Exp $
2
+
3
+ #[46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
4
+ #[47] children ::= (choice | seq) ('?' | '*' | '+')?
5
+ #[48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6
+ #[49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
7
+ #[50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
8
+ #[51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
9
+ # | '(' S? '#PCDATA' S? ')'
10
+ # �����Ǥ�դ�������ǽ�������� ? * + ��ľ���˶�����֤��ʤ���
11
+
12
+
13
+ # + positive closure (������)
14
+ # * kleene closure (����)
15
+ # ?
16
+ # | union (����)
17
+ # , concatenation (Ϣ��)
18
+
19
+
20
+ class ContentSpecParser
21
+
22
+ options no_result_var
23
+
24
+ rule
25
+
26
+ contentspec: 'EMPTY'
27
+ | 'ANY'
28
+ { @result.push :ANY }
29
+ | mixed
30
+ | children
31
+
32
+ mixed: '(' mixedelem ')*'
33
+ { @result.push :* }
34
+ | '(' '#PCDATA' ')'
35
+ { @result.push :PCDATA }
36
+ | '(' '#PCDATA' ')*'
37
+ { @result.push :PCDATA, :- }
38
+
39
+ mixedelem: '#PCDATA' '|' Name
40
+ { @result.push :PCDATA, val[2], :| }
41
+ | mixedelem '|' Name
42
+ { @result.push val[2], :| }
43
+
44
+ children: choice
45
+ | seq
46
+
47
+ choice: '(' choicelist listend
48
+
49
+ choicelist: cp '|' cp
50
+ { @result.push :| }
51
+ | choicelist '|' cp
52
+ { @result.push :| }
53
+
54
+ seq: '(' seqlist listend
55
+
56
+ seqlist: cp
57
+ | seqlist ',' cp
58
+ { @result.push :** }
59
+
60
+ listend: ')'
61
+ | ')?'
62
+ { @result.push :- }
63
+ | ')*'
64
+ { @result.push :* }
65
+ | ')+'
66
+ { @result.push :+ }
67
+
68
+ cp: Name
69
+ { @result.push val[0] }
70
+ | NameQ
71
+ { @result.push val[0], :- }
72
+ | NameA
73
+ { @result.push val[0], :* }
74
+ | NameP
75
+ { @result.push val[0], :+ }
76
+ | choice
77
+ | seq
78
+
79
+ end
80
+
81
+
82
+ ---- inner ----
83
+
84
+ def next_token
85
+ @tokens.shift
86
+ end
87
+
88
+ def parse(src)
89
+ @tokens = []
90
+ first = true
91
+ src.scan(/([^ \t\n\r(|,)?*+]+[?*+]?)|([(|,]|\)[?*+]?)|([^ \t\n\r][\S\s]*)/
92
+ ) { |name,delim,error|
93
+ if name then
94
+ if first and (name == 'EMPTY' or name == 'ANY') then
95
+ @tokens.push [ name, name ]
96
+ elsif name == '#PCDATA' then
97
+ @tokens.push [ name, name ]
98
+ else
99
+ c = name[-1]
100
+ if c == ?? then
101
+ name.chop!
102
+ @tokens.push [ :NameQ, name ]
103
+ elsif c == ?* then
104
+ name.chop!
105
+ @tokens.push [ :NameA, name ]
106
+ elsif c == ?+ then
107
+ name.chop!
108
+ @tokens.push [ :NameP, name ]
109
+ else
110
+ @tokens.push [ :Name, name ]
111
+ end
112
+ end
113
+ elsif delim then
114
+ @tokens.push [ delim, delim ]
115
+ else
116
+ raise error
117
+ end
118
+ }
119
+ @tokens.push [ false, nil ]
120
+ @yydebug = true
121
+ @result = []
122
+ do_parse
123
+ @result
124
+ end
125
+
126
+ ---- footer ----
127
+
128
+
129
+
130
+
131
+ module XMLScan
132
+
133
+ class DTDScanner
134
+
135
+ def parse_error(msg)
136
+ print " #{caller[0]}: ", msg, "\n"
137
+ end
138
+
139
+ ClosureMark = { ?? => :-, ?* => :*, ?+ => :+ }
140
+ SeqDelim = { ?, => :**, ?| => :| }
141
+
142
+ def scan_contentspec(src)
143
+ dst = []
144
+ parenstack = []
145
+ pcdata = false
146
+ parenallow = true
147
+ if src == 'EMPTY' then
148
+ return []
149
+ elsif src == 'ANY' then
150
+ return [:ANY]
151
+ end
152
+ src.scan(
153
+ /([^ \t\n\r(|,)?*+%;]+[?*+]?)|([(|,]|\)[?*+]?)|([^ \t\n\r][\S\s]*)/
154
+ ) { |name,delim,error|
155
+ if name then
156
+ if not parenallow or parenstack.empty? then
157
+ parse_error "parse error at `#{name}'"
158
+ break
159
+ # RECOVERY-01: insert a `(' before Name. Also insert `,(' if needed
160
+ parenstack.push nil if parenstack.empty?
161
+ parenstack[-1] = (:**) unless parenstack.last
162
+ parenstack.push nil
163
+ end
164
+ mark = ClosureMark[name[-1]]
165
+ name.chop! if mark
166
+ if name == '#PCDATA' then
167
+ if mark or not dst.empty? or parenstack.size > 1 then
168
+ parse_error "parse error at `#{name}#{mark&&mark.chr}'"
169
+ break
170
+ dst.push '#PCDATA' # RECOVERY-02: regard as an element type.
171
+ dst.push mark if mark
172
+ mark = parenstack.last
173
+ dst.push mark if mark
174
+ else
175
+ dst.push :PCDATA
176
+ pcdata = true
177
+ parenstack[-1] = :|
178
+ end
179
+ else
180
+ dst.push name
181
+ dst.push mark if mark
182
+ mark = parenstack.last
183
+ dst.push mark if mark
184
+ end
185
+ parenallow = false
186
+ elsif delim then
187
+ mark = delim[1]
188
+ delim = delim[0]
189
+ if delim == ?( then
190
+ if not parenallow or pcdata then
191
+ parse_error "parse error at `('"
192
+ break
193
+ if pcdata then # RECOVERY-03: allow it with limitation.
194
+ parenstack.push :|
195
+ else # RECOVERY-04: insert a `,' before `('.
196
+ parenstack[-1] = (:**) unless parenstack.last
197
+ parenstack.push nil
198
+ parenallow = true
199
+ end
200
+ else
201
+ parenstack.push nil
202
+ end
203
+ elsif delim == ?) then
204
+ if parenallow then
205
+ parse_error "parse error at `)#{mark&&mark.chr}'"
206
+ parenstack.pop ; break
207
+ mark = nil # RECOVERY-05: allow it but ignore any marks.
208
+ parenallow = false
209
+ end
210
+ if parenstack.empty? then
211
+ parse_error "unbalanced `)'"
212
+ break
213
+ # RECOVERY-06: allow it.
214
+ end
215
+ parenstack.pop
216
+ if pcdata then
217
+ if dst.size > 1 then
218
+ unless parenstack.empty? then
219
+ # here is continuation of RECOVERY-03: ignore any marks.
220
+ else
221
+ unless mark == ?* then
222
+ parse_error "parse error at `)#{mark&&mark.chr}'"
223
+ break
224
+ # RECOVERY-07: replace the mark with a `*'.
225
+ end
226
+ dst.push :*
227
+ end
228
+ elsif mark then
229
+ if mark == ?* then
230
+ dst.push :-
231
+ else
232
+ parse_error "parse error at `)#{mark&&mark.chr}'"
233
+ break
234
+ # RECOVERY-08: ignore it.
235
+ end
236
+ end
237
+ else
238
+ mark = ClosureMark[mark]
239
+ dst.push mark if mark
240
+ mark = parenstack.last
241
+ dst.push mark if mark
242
+ end
243
+ else # | or ,
244
+ if parenallow or parenstack.empty? then
245
+ parse_error "parse error at `#{delim.chr}'"
246
+ break
247
+ # RECOVERY-09: ignore it.
248
+ else
249
+ mark = SeqDelim[delim]
250
+ if parenstack.last then
251
+ unless parenstack.last == mark then
252
+ parse_error "parse error at `#{delim.chr}'"
253
+ break
254
+ # RECOVERY-10: regard that it is same as the previous one.
255
+ end
256
+ else
257
+ parenstack[-1] = mark
258
+ end
259
+ parenallow = true
260
+ end
261
+ end
262
+ elsif error then
263
+ parse_error "parse error `#{error}'"
264
+ break
265
+ parenallow = false # RECOVERY-11: ignore all after.
266
+ parenstack.clear
267
+ end
268
+ }
269
+ #parse_error "unexpected termination of content model" if parenallow
270
+ parse_error "unbalanced `('" unless parenstack.empty?
271
+ dst
272
+ end
273
+
274
+ end
275
+
276
+ end
277
+
278
+
279
+
280
+ Examples = [
281
+ "EMPTY",
282
+ "ANY",
283
+ "(a,b,c)",
284
+ "(a,b*,c)",
285
+ "(a,b*,c+)",
286
+ "(a,(b*,c)+)",
287
+ "(a,(b*|(c,e)?)+,d)+",
288
+ "(a,(b,(c,(d,(e)))))",
289
+ "(a,b,c,d,e)",
290
+ "(((((a),b),c),d),e)",
291
+ "(#PCDATA|a|b|c)",
292
+ "(#PCDATA|a)*",
293
+ "(#PCDATA|a|b|c)*",
294
+ "(a|#PCDATA|a|b|c)*",
295
+ "()*",
296
+ "(a,)?",
297
+ "((a,b,),c)?",
298
+ "(a))",
299
+ "((a))",
300
+ "(a)b)",
301
+ "(a(b))",
302
+ "(a)",
303
+ "(a)*",
304
+ "(#PCDATA)",
305
+ "(#PCDATA)*",
306
+ "(#PCDATA)?",
307
+ "(a,(#PCDATA|b|c)*,d)",
308
+ "a*",
309
+ "a|b",
310
+ "EMPTY|b",
311
+ '(a|b,c)',
312
+ '(#PCDATA|(a|b)|c)*',
313
+ '(#PCDATA|a|(b|c))*',
314
+ ',a',
315
+ '(a)(b,c)',
316
+ '(#PCDATA)(a,b)',
317
+ '(a,,b)',
318
+ ]
319
+
320
+ Examples.each { |s|
321
+ p s
322
+ puts
323
+ begin
324
+ print ' ', ContentSpecParser.new.parse(s).inspect, "\n"
325
+ rescue => e
326
+ print " ERROR: #{caller[0]}: ", e.message.strip, " (#{e.class.name})\n"
327
+ end
328
+ puts
329
+ begin
330
+ print ' ', XMLScan::DTDScanner.new.scan_contentspec(s).inspect, "\n"
331
+ rescue => e
332
+ print " ERROR: #{caller[0]}: ", e.message, " (#{e.class.name})\n"
333
+ end
334
+ puts
335
+ }