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
|
package scala.xml.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)
error("invalid!");
}
*/
override def endDTD(n:String) = {
rootLabel = n;
}
override def elemStart(pos: int, pre: String, label: String, attrs: MetaData, scope:NamespaceBinding): Unit = {
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.toString);
}
}
// 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): Unit = {
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): Unit =
decls = ElemDecl( name, ContentModel.parse(cmstr)) :: decls;
final override def attListDecl(name: String, attList: List[AttrDecl]): Unit =
decls = AttListDecl( name, attList) :: decls;
final override def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit = {
decls = UnparsedEntityDecl( name, extID, notat) :: decls;
}
final override def notationDecl(notat: String, extID: ExternalID): Unit =
decls = NotationDecl( notat, extID) :: decls;
final override def peReference(name: String): Unit =
decls = PEReference( name ) :: decls;
/** report a syntax error */
def reportValidationError(pos: Int, str: String): Unit;
}
|