summaryrefslogtreecommitdiff
path: root/src/library/scala/xml/dtd/Scanner.scala
blob: 0bb8d99b74e1321792291e8801328620659309bb (plain) (blame)
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
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.xml.dtd


/** Scanner for regexps (content models in DTD element declarations)
 *  todo: cleanup
 */
class Scanner extends Tokens with parsing.TokenTests {

  final val ENDCH = '\u0000'

  var token:Int = END
  var value:String = _

  private var it: Iterator[Char] = null
  private var c: Char = 'z'

  /** initializes the scanner on input s */
  final def initScanner(s: String) {
    value = ""
    it = (s).elements
    token = 1+END
    next
    nextToken
  }

  /** scans the next token */
  final def nextToken {
    if (token != END) token = readToken
  }

  // todo: see XML specification... probably isLetter,isDigit is fine
  final def isIdentChar = ( ('a' <= c && c <= 'z')
                           || ('A' <= c && c <= 'Z'));

  final def next = if (it.hasNext) c = it.next else c = ENDCH

  final def acc(d: Char) {
    if (c == d) next else error("expected '"+d+"' found '"+c+"' !");
  }

  final def accS(ds: Seq[Char]) {
    val jt = ds.elements
    while (jt.hasNext) { acc(jt.next) }
  }

  final def readToken: Int =
    if (isSpace(c)) {
      while (isSpace(c)) c = it.next
      S
    } else c match {
      case '('   => next; LPAREN
      case ')'   => next; RPAREN
      case ','   => next; COMMA
      case '*'   => next; STAR
      case '+'   => next; PLUS
      case '?'   => next; OPT
      case '|'   => next; CHOICE
      case '#'   => next; accS( "PCDATA" ); TOKEN_PCDATA
      case ENDCH => END
      case _     =>
        if (isNameStart(c)) name; // NAME
        else { error("unexpected character:"+c); END }
    }

  final def name = {
    val sb = new StringBuilder()
    do { sb.append(c); next } while (isNameChar(c));
    value = sb.toString()
    NAME
  }

}