Skip to content

Commit 091de12

Browse files
socadriaanm
authored andcommitted
SI-6811 Move scala.util.{automata,regexp} ...
... to scala.xml.dtd.impl and make it private[dtd]
1 parent 1a99bc2 commit 091de12

16 files changed

+733
-13
lines changed

src/library/scala/xml/dtd/ContentModel.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
package scala.xml
1212
package dtd
1313

14-
import scala.util.regexp.WordExp
15-
import scala.util.automata._
14+
import scala.xml.dtd.impl._
1615
import scala.xml.Utility.sbToString
1716
import PartialFunction._
1817

src/library/scala/xml/dtd/DocType.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ package dtd
1818
* @param extID NoExternalID or the external ID of this doctype
1919
* @param intSubset sequence of internal subset declarations
2020
*/
21-
case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl])
22-
{
21+
case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl]) {
2322
if (!Utility.isName(name))
2423
throw new IllegalArgumentException(name+" must be an XML Name")
2524

@@ -33,8 +32,7 @@ case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl])
3332
}
3433
}
3534

36-
object DocType
37-
{
35+
object DocType {
3836
/** Creates a doctype with no external id, nor internal subset declarations. */
3937
def apply(name: String): DocType = apply(name, NoExternalID, Nil)
4038
}

src/library/scala/xml/dtd/ElementValidator.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ package scala.xml
1212
package dtd
1313

1414
import PartialFunction._
15+
import scala.collection.mutable
16+
1517
import ContentModel.ElemName
1618
import MakeValidationException._ // @todo other exceptions
17-
import scala.util.automata._
18-
import scala.collection.mutable
19+
20+
import impl._
1921

2022
/** validate children and/or attributes of an element
2123
* exceptions are created but not thrown.

src/library/scala/xml/dtd/ExternalID.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ package dtd
1414
*
1515
* @author Burak Emir
1616
*/
17-
abstract class ExternalID extends parsing.TokenTests
18-
{
17+
abstract class ExternalID extends parsing.TokenTests {
1918
def quoted(s: String) = {
2019
val c = if (s contains '"') '\'' else '"'
2120
c + s + c
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
10+
11+
package scala.xml.dtd.impl
12+
13+
/** Basic regular expressions.
14+
*
15+
* @author Burak Emir
16+
* @version 1.0
17+
*/
18+
19+
@deprecated("This class will be removed", "2.10.0")
20+
private[dtd] abstract class Base {
21+
type _regexpT <: RegExp
22+
23+
abstract class RegExp {
24+
val isNullable: Boolean
25+
}
26+
27+
object Alt {
28+
/** `Alt( R,R,R* )`. */
29+
def apply(rs: _regexpT*) =
30+
if (rs.size < 2) throw new SyntaxError("need at least 2 branches in Alt")
31+
else new Alt(rs: _*)
32+
// Can't enforce that statically without changing the interface
33+
// def apply(r1: _regexpT, r2: _regexpT, rs: _regexpT*) = new Alt(Seq(r1, r2) ++ rs: _*)
34+
def unapplySeq(x: Alt) = Some(x.rs)
35+
}
36+
37+
class Alt private (val rs: _regexpT*) extends RegExp {
38+
final val isNullable = rs exists (_.isNullable)
39+
}
40+
41+
object Sequ {
42+
/** Sequ( R,R* ) */
43+
def apply(rs: _regexpT*) = if (rs.isEmpty) Eps else new Sequ(rs: _*)
44+
def unapplySeq(x: Sequ) = Some(x.rs)
45+
}
46+
47+
class Sequ private (val rs: _regexpT*) extends RegExp {
48+
final val isNullable = rs forall (_.isNullable)
49+
}
50+
51+
case class Star(r: _regexpT) extends RegExp {
52+
final lazy val isNullable = true
53+
}
54+
55+
// The empty Sequ.
56+
case object Eps extends RegExp {
57+
final lazy val isNullable = true
58+
override def toString() = "Eps"
59+
}
60+
61+
/** this class can be used to add meta information to regexps. */
62+
class Meta(r1: _regexpT) extends RegExp {
63+
final val isNullable = r1.isNullable
64+
def r = r1
65+
}
66+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.xml.dtd.impl
10+
11+
import scala.collection.{ mutable, immutable }
12+
13+
// todo: replace global variable pos with acc
14+
15+
/** This class turns a regular expression over `A` into a
16+
* [[scala.util.automata.NondetWordAutom]] over `A` using the celebrated
17+
* position automata construction (also called ''Berry-Sethi'' or ''Glushkov'').
18+
*/
19+
@deprecated("This class will be removed", "2.10.0")
20+
private[dtd] abstract class BaseBerrySethi {
21+
val lang: Base
22+
import lang.{ Alt, Eps, Meta, RegExp, Sequ, Star }
23+
24+
protected var pos = 0
25+
26+
// results which hold all info for the NondetWordAutomaton
27+
protected var follow: mutable.HashMap[Int, Set[Int]] = _
28+
29+
protected var finalTag: Int = _
30+
31+
protected var finals: immutable.Map[Int, Int] = _ // final states
32+
33+
// constants --------------------------
34+
35+
final val emptySet: Set[Int] = Set()
36+
37+
private def doComp(r: RegExp, compFunction: RegExp => Set[Int]) = r match {
38+
case x: Alt => (x.rs map compFirst).foldLeft(emptySet)(_ ++ _)
39+
case Eps => emptySet
40+
case x: Meta => compFunction(x.r)
41+
case x: Sequ =>
42+
val (l1, l2) = x.rs span (_.isNullable)
43+
((l1 ++ (l2 take 1)) map compFunction).foldLeft(emptySet)(_ ++ _)
44+
case Star(t) => compFunction(t)
45+
case _ => throw new IllegalArgumentException("unexpected pattern " + r.getClass)
46+
}
47+
48+
/** Computes `first(r)` for the word regexp `r`. */
49+
protected def compFirst(r: RegExp): Set[Int] = doComp(r, compFirst)
50+
51+
/** Computes `last(r)` for the regexp `r`. */
52+
protected def compLast(r: RegExp): Set[Int] = doComp(r, compLast)
53+
54+
/** Starts from the right-to-left
55+
* precondition: pos is final
56+
* pats are successor patterns of a Sequence node
57+
*/
58+
protected def compFollow(rs: Seq[RegExp]): Set[Int] = {
59+
follow(0) =
60+
if (rs.isEmpty) emptySet
61+
else rs.foldRight(Set(pos))((p, fol) => {
62+
val first = compFollow1(fol, p)
63+
64+
if (p.isNullable) fol ++ first
65+
else first
66+
})
67+
68+
follow(0)
69+
}
70+
71+
/** Returns the first set of an expression, setting the follow set along the way.
72+
*/
73+
protected def compFollow1(fol1: Set[Int], r: RegExp): Set[Int] = r match {
74+
case x: Alt => Set((x.rs reverseMap (compFollow1(fol1, _))).flatten: _*)
75+
case x: Meta => compFollow1(fol1, x.r)
76+
case x: Star => compFollow1(fol1 ++ compFirst(x.r), x.r)
77+
case x: Sequ =>
78+
x.rs.foldRight(fol1) { (p, fol) =>
79+
val first = compFollow1(fol, p)
80+
81+
if (p.isNullable) fol ++ first
82+
else first
83+
}
84+
case _ => throw new IllegalArgumentException("unexpected pattern: " + r.getClass)
85+
}
86+
87+
/** Returns the "Sethi-length" of a pattern, creating the set of position along the way.
88+
*/
89+
protected def traverse(r: RegExp): Unit = r match {
90+
// (is tree automaton stuff, more than Berry-Sethi)
91+
case x: Alt => x.rs foreach traverse
92+
case x: Sequ => x.rs foreach traverse
93+
case x: Meta => traverse(x.r)
94+
case Star(t) => traverse(t)
95+
case _ => throw new IllegalArgumentException("unexp pattern " + r.getClass)
96+
}
97+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.xml.dtd.impl
10+
11+
import scala.collection.{ mutable, immutable }
12+
13+
/** A deterministic automaton. States are integers, where
14+
* 0 is always the only initial state. Transitions are represented
15+
* in the delta function. A default transitions is one that
16+
* is taken when no other transition can be taken.
17+
* All states are reachable. Accepting states are those for which
18+
* the partial function 'finals' is defined.
19+
*
20+
* @author Burak Emir
21+
* @version 1.0
22+
*/
23+
@deprecated("This class will be removed", "2.10.0")
24+
private[dtd] abstract class DetWordAutom[T <: AnyRef] {
25+
val nstates: Int
26+
val finals: Array[Int]
27+
val delta: Array[mutable.Map[T, Int]]
28+
val default: Array[Int]
29+
30+
def isFinal(q: Int) = finals(q) != 0
31+
def isSink(q: Int) = delta(q).isEmpty && default(q) == q
32+
def next(q: Int, label: T) = delta(q).getOrElse(label, default(q))
33+
34+
override def toString() = {
35+
val sb = new StringBuilder("[DetWordAutom nstates=")
36+
sb.append(nstates)
37+
sb.append(" finals=")
38+
val map = Map(finals.zipWithIndex map (_.swap): _*)
39+
sb.append(map.toString())
40+
sb.append(" delta=\n")
41+
42+
for (i <- 0 until nstates) {
43+
sb append "%d->%s\n".format(i, delta(i))
44+
if (i < default.length)
45+
sb append "_>%s\n".format(default(i))
46+
}
47+
sb.toString
48+
}
49+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
10+
11+
package scala.xml.dtd.impl
12+
13+
14+
/** A fast test of language inclusion between minimal automata.
15+
* inspired by the ''AMoRE automata library''.
16+
*
17+
* @author Burak Emir
18+
* @version 1.0
19+
*/
20+
@deprecated("This class will be removed", "2.10.0")
21+
private[dtd] trait Inclusion[A <: AnyRef] {
22+
23+
val labels: Seq[A]
24+
25+
/** Returns true if `dfa1` is included in `dfa2`.
26+
*/
27+
def inclusion(dfa1: DetWordAutom[A], dfa2: DetWordAutom[A]) = {
28+
29+
def encode(q1: Int, q2: Int) = 1 + q1 + q2 * dfa1.nstates
30+
def decode2(c: Int) = (c-1) / (dfa1.nstates) //integer division
31+
def decode1(c: Int) = (c-1) % (dfa1.nstates)
32+
33+
var q1 = 0 //dfa1.initstate; // == 0
34+
var q2 = 0 //dfa2.initstate; // == 0
35+
36+
val max = 1 + dfa1.nstates * dfa2.nstates
37+
val mark = new Array[Int](max)
38+
39+
var result = true
40+
var current = encode(q1, q2)
41+
var last = current
42+
mark(last) = max // mark (q1,q2)
43+
while (current != 0 && result) {
44+
//Console.println("current = [["+q1+" "+q2+"]] = "+current);
45+
for (letter <- labels) {
46+
val r1 = dfa1.next(q1,letter)
47+
val r2 = dfa2.next(q2,letter)
48+
if (dfa1.isFinal(r1) && !dfa2.isFinal(r2))
49+
result = false
50+
val test = encode(r1, r2)
51+
//Console.println("test = [["+r1+" "+r2+"]] = "+test);
52+
if (mark(test) == 0) {
53+
mark(last) = test
54+
mark(test) = max
55+
last = test
56+
}
57+
}
58+
val ncurrent = mark(current)
59+
if( ncurrent != max ) {
60+
q1 = decode1(ncurrent)
61+
q2 = decode2(ncurrent)
62+
current = ncurrent
63+
} else {
64+
current = 0
65+
}
66+
}
67+
result
68+
}
69+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.xml.dtd.impl
10+
11+
import scala.collection.{ immutable, mutable }
12+
13+
/** A nondeterministic automaton. States are integers, where
14+
* 0 is always the only initial state. Transitions are represented
15+
* in the delta function. Default transitions are transitions that
16+
* are taken when no other transitions can be applied.
17+
* All states are reachable. Accepting states are those for which
18+
* the partial function `finals` is defined.
19+
*/
20+
@deprecated("This class will be removed", "2.10.0")
21+
private[dtd] abstract class NondetWordAutom[T <: AnyRef] {
22+
val nstates: Int
23+
val labels: Seq[T]
24+
val finals: Array[Int] // 0 means not final
25+
val delta: Array[mutable.Map[T, immutable.BitSet]]
26+
val default: Array[immutable.BitSet]
27+
28+
/** @return true if the state is final */
29+
final def isFinal(state: Int) = finals(state) > 0
30+
31+
/** @return tag of final state */
32+
final def finalTag(state: Int) = finals(state)
33+
34+
/** @return true if the set of states contains at least one final state */
35+
final def containsFinal(Q: immutable.BitSet): Boolean = Q exists isFinal
36+
37+
/** @return true if there are no accepting states */
38+
final def isEmpty = (0 until nstates) forall (x => !isFinal(x))
39+
40+
/** @return a immutable.BitSet with the next states for given state and label */
41+
def next(q: Int, a: T): immutable.BitSet = delta(q).getOrElse(a, default(q))
42+
43+
/** @return a immutable.BitSet with the next states for given state and label */
44+
def next(Q: immutable.BitSet, a: T): immutable.BitSet = next(Q, next(_, a))
45+
def nextDefault(Q: immutable.BitSet): immutable.BitSet = next(Q, default)
46+
47+
private def next(Q: immutable.BitSet, f: (Int) => immutable.BitSet): immutable.BitSet =
48+
(Q map f).foldLeft(immutable.BitSet.empty)(_ ++ _)
49+
50+
private def finalStates = 0 until nstates filter isFinal
51+
override def toString = {
52+
53+
val finalString = Map(finalStates map (j => j -> finals(j)) : _*).toString
54+
val deltaString = (0 until nstates)
55+
.map(i => " %d->%s\n _>%s\n".format(i, delta(i), default(i))).mkString
56+
57+
"[NondetWordAutom nstates=%d finals=%s delta=\n%s".format(nstates, finalString, deltaString)
58+
}
59+
}

0 commit comments

Comments
 (0)