1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2010, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.xml
package parsing
import scala.xml.dtd._
import scala.util.logging.Logged
abstract class ValidatingMarkupHandler extends MarkupHandler with Logged {
var rootLabel:String = _
var qStack: List[Int] = Nil
var qCurrent: Int = -1
var declStack: List[ElemDecl] = Nil
var declCurrent: ElemDecl = null
final override val isValidating = true
override def log(msg: String) {}
/*
override def checkChildren(pos: Int, pre: String, label:String,ns:NodeSeq): Unit = {
Console.println("checkChildren()");
val decl = lookupElemDecl(label);
// @todo: nice error message
val res = decl.contentModel.validate(ns);
Console.println("res = "+res);
if(!res)
//system.error("invalid!");
}
*/
override def endDTD(n:String) = {
rootLabel = n
}
override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding) {
def advanceDFA(dm:DFAContentModel) = {
val trans = dm.dfa.delta(qCurrent)
log("advanceDFA(dm): " + dm)
log("advanceDFA(trans): " + trans)
trans.get(ContentModel.ElemName(label)) match {
case Some(qNew) => qCurrent = qNew
case _ => reportValidationError(pos, "DTD says, wrong element, expected one of "+trans.keys);
}
}
// advance in current automaton
log("[qCurrent = "+qCurrent+" visiting "+label+"]")
if (qCurrent == -1) { // root
log(" checking root")
if (label != rootLabel)
reportValidationError(pos, "this element should be "+rootLabel)
} else {
log(" checking node")
declCurrent.contentModel match {
case ANY =>
case EMPTY =>
reportValidationError(pos, "DTD says, no elems, no text allowed here")
case PCDATA =>
reportValidationError(pos, "DTD says, no elements allowed here")
case m @ MIXED(r) =>
advanceDFA(m)
case e @ ELEMENTS(r) =>
advanceDFA(e)
}
}
// push state, decl
qStack = qCurrent :: qStack
declStack = declCurrent :: declStack
declCurrent = lookupElemDecl(label)
qCurrent = 0
log(" done now")
}
override def elemEnd(pos: Int, pre: String, label: String) {
log(" elemEnd")
qCurrent = qStack.head
qStack = qStack.tail
declCurrent = declStack.head
declStack = declStack.tail
log(" qCurrent now" + qCurrent)
log(" declCurrent now" + declCurrent)
}
final override def elemDecl(name: String, cmstr: String) {
decls = ElemDecl(name, ContentModel.parse(cmstr)) :: decls
}
final override def attListDecl(name: String, attList: List[AttrDecl]) {
decls = AttListDecl(name, attList) :: decls
}
final override def unparsedEntityDecl(name: String, extID: ExternalID, notat: String) {
decls = UnparsedEntityDecl(name, extID, notat) :: decls
}
final override def notationDecl(notat: String, extID: ExternalID) {
decls = NotationDecl(notat, extID) :: decls;
}
final override def peReference(name: String) {
decls = PEReference(name) :: decls
}
/** report a syntax error */
def reportValidationError(pos: Int, str: String): Unit
}
|