DTDAutomata.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. //
  2. // Mono.Xml.DTDAutomata
  3. //
  4. // Author:
  5. // Atsushi Enomoto ([email protected])
  6. //
  7. // (C)2003 Atsushi Enomoto
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Text;
  12. using System.Xml;
  13. using System.Xml.Schema;
  14. using Mono.Xml.Schema;
  15. namespace Mono.Xml
  16. {
  17. public class DTDAutomataFactory
  18. {
  19. public DTDAutomataFactory (DTDObjectModel root)
  20. {
  21. this.root = root;
  22. }
  23. DTDObjectModel root;
  24. Hashtable choiceTable = new Hashtable ();
  25. Hashtable sequenceTable = new Hashtable ();
  26. public DTDChoiceAutomata Choice (DTDAutomata left, DTDAutomata right)
  27. {
  28. Hashtable rightPool = choiceTable [left] as Hashtable;
  29. if (rightPool == null) {
  30. rightPool = new Hashtable ();
  31. choiceTable [left] = rightPool;
  32. }
  33. DTDChoiceAutomata result = rightPool [right] as DTDChoiceAutomata;
  34. if (result == null) {
  35. result = new DTDChoiceAutomata (root, left, right);
  36. rightPool [right] = result;
  37. }
  38. return result;
  39. }
  40. public DTDSequenceAutomata Sequence (DTDAutomata left, DTDAutomata right)
  41. {
  42. Hashtable rightPool = sequenceTable [left] as Hashtable;
  43. if (rightPool == null) {
  44. rightPool = new Hashtable ();
  45. sequenceTable [left] = rightPool;
  46. }
  47. DTDSequenceAutomata result = rightPool [right] as DTDSequenceAutomata;
  48. if (result == null) {
  49. result = new DTDSequenceAutomata (root, left, right);
  50. rightPool [right] = result;
  51. }
  52. return result;
  53. }
  54. }
  55. public abstract class DTDAutomata
  56. {
  57. public DTDAutomata (DTDObjectModel root)
  58. {
  59. this.root = root;
  60. }
  61. private DTDObjectModel root;
  62. public DTDObjectModel Root {
  63. get { return root; }
  64. }
  65. public DTDAutomata MakeChoice (DTDAutomata other)
  66. {
  67. if (this == Root.Invalid)
  68. return other;
  69. if (other == Root.Invalid)
  70. return this;
  71. if (this == Root.Empty && other == Root.Empty)
  72. return this;
  73. if (this == Root.Any && other == Root.Any)
  74. return this;
  75. else if (other == Root.Empty)
  76. return Root.Factory.Choice (other, this);
  77. else
  78. return Root.Factory.Choice (this, other);
  79. }
  80. public DTDAutomata MakeSequence (DTDAutomata other)
  81. {
  82. if (this == Root.Invalid || other == Root.Invalid)
  83. return Root.Invalid;
  84. if (this == Root.Empty)
  85. return other;
  86. if (other == Root.Empty)
  87. return this;
  88. else
  89. return Root.Factory.Sequence (this, other);
  90. }
  91. public abstract DTDAutomata TryStartElement (string name);
  92. public virtual DTDAutomata TryEndElement ()
  93. {
  94. return Root.Invalid;
  95. }
  96. public virtual bool Emptiable {
  97. get { return false; }
  98. }
  99. }
  100. public class DTDElementAutomata : DTDAutomata
  101. {
  102. public DTDElementAutomata (DTDObjectModel root, string name)
  103. : base (root)
  104. {
  105. this.name = name;
  106. }
  107. private string name;
  108. public string Name {
  109. get { return name; }
  110. }
  111. public override DTDAutomata TryStartElement (string name)
  112. {
  113. if (name == Name)
  114. return Root.Empty;
  115. else
  116. return Root.Invalid;
  117. }
  118. }
  119. public class DTDChoiceAutomata : DTDAutomata
  120. {
  121. public DTDChoiceAutomata (DTDObjectModel root,
  122. DTDAutomata left, DTDAutomata right)
  123. : base (root)
  124. {
  125. this.left = left;
  126. this.right = right;
  127. }
  128. private DTDAutomata left;
  129. private DTDAutomata right;
  130. public DTDAutomata Left {
  131. get { return left; }
  132. }
  133. public DTDAutomata Right {
  134. get { return right; }
  135. }
  136. public override DTDAutomata TryStartElement (string name)
  137. {
  138. return left.TryStartElement (name).MakeChoice (
  139. right.TryStartElement (name));
  140. }
  141. public override DTDAutomata TryEndElement ()
  142. {
  143. if (left == Root.Empty)
  144. return right;
  145. if (right == Root.Empty)
  146. return left;
  147. else
  148. return Root.Invalid;
  149. }
  150. bool hasComputedEmptiable;
  151. bool cachedEmptiable;
  152. public override bool Emptiable {
  153. get {
  154. if (!hasComputedEmptiable) {
  155. cachedEmptiable = left.Emptiable ||
  156. right.Emptiable;
  157. hasComputedEmptiable = true;
  158. }
  159. return cachedEmptiable;
  160. }
  161. }
  162. }
  163. public class DTDSequenceAutomata : DTDAutomata
  164. {
  165. public DTDSequenceAutomata (DTDObjectModel root,
  166. DTDAutomata left, DTDAutomata right)
  167. : base (root)
  168. {
  169. this.left = left;
  170. this.right = right;
  171. }
  172. private DTDAutomata left;
  173. private DTDAutomata right;
  174. public DTDAutomata Left {
  175. get { return left; }
  176. }
  177. public DTDAutomata Right {
  178. get { return right; }
  179. }
  180. public override DTDAutomata TryStartElement (string name)
  181. {
  182. DTDAutomata afterL = left.TryStartElement (name);
  183. DTDAutomata afterR = right.TryStartElement (name);
  184. if (afterL == Root.Invalid)
  185. return (afterL.Emptiable) ? afterR : afterL;
  186. // else
  187. DTDAutomata whenLeftConsumed = afterL.MakeSequence (right);
  188. if (left.Emptiable)
  189. return afterR.MakeChoice (whenLeftConsumed);
  190. else
  191. return whenLeftConsumed;
  192. }
  193. bool hasComputedEmptiable;
  194. bool cachedEmptiable;
  195. public override bool Emptiable {
  196. get {
  197. if (!hasComputedEmptiable) {
  198. cachedEmptiable = left.Emptiable &&
  199. right.Emptiable;
  200. hasComputedEmptiable = true;
  201. }
  202. return cachedEmptiable;
  203. }
  204. }
  205. }
  206. public class DTDOneOrMoreAutomata : DTDAutomata
  207. {
  208. public DTDOneOrMoreAutomata (DTDObjectModel root,
  209. DTDAutomata children)
  210. : base (root)
  211. {
  212. this.children = children;
  213. }
  214. private DTDAutomata children;
  215. public DTDAutomata Children {
  216. get { return children; }
  217. }
  218. public override DTDAutomata TryStartElement (string name)
  219. {
  220. DTDAutomata afterC = children.TryStartElement (name);
  221. if (afterC != Root.Invalid)
  222. return afterC.MakeSequence (
  223. Root.Empty.MakeChoice (this));
  224. else
  225. return Root.Invalid;
  226. }
  227. }
  228. public class DTDEmptyAutomata : DTDAutomata
  229. {
  230. public DTDEmptyAutomata (DTDObjectModel root)
  231. : base (root)
  232. {
  233. }
  234. public override DTDAutomata TryEndElement ()
  235. {
  236. return this;
  237. }
  238. public override DTDAutomata TryStartElement (string name)
  239. {
  240. return Root.Invalid;
  241. }
  242. public override bool Emptiable {
  243. get { return true; }
  244. }
  245. }
  246. public class DTDAnyAutomata : DTDAutomata
  247. {
  248. public DTDAnyAutomata (DTDObjectModel root)
  249. : base (root)
  250. {
  251. }
  252. public override DTDAutomata TryEndElement ()
  253. {
  254. return this;
  255. }
  256. public override DTDAutomata TryStartElement (string name)
  257. {
  258. return this;
  259. }
  260. public override bool Emptiable {
  261. get { return true; }
  262. }
  263. }
  264. public class DTDInvalidAutomata : DTDAutomata
  265. {
  266. public DTDInvalidAutomata (DTDObjectModel root)
  267. : base (root)
  268. {
  269. }
  270. public override DTDAutomata TryEndElement ()
  271. {
  272. return this;
  273. }
  274. public override DTDAutomata TryStartElement (string name)
  275. {
  276. return this;
  277. }
  278. }
  279. }