| author | wenzelm | 
| Fri, 28 Apr 2017 11:50:31 +0200 | |
| changeset 65602 | d9533e9615ad | 
| parent 65523 | 4f2954adc217 | 
| child 66914 | fb3f13a9c756 | 
| permissions | -rw-r--r-- | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 1 | /* Title: Pure/Isar/token.scala | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 3 | |
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 4 | Outer token syntax for Isabelle/Isar. | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 5 | */ | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 6 | |
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 8 | |
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 9 | |
| 59083 | 10 | import scala.collection.mutable | 
| 11 | import scala.util.parsing.input | |
| 12 | ||
| 13 | ||
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 14 | object Token | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 15 | {
 | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 16 | /* tokens */ | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 17 | |
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 18 | object Kind extends Enumeration | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 19 |   {
 | 
| 59081 | 20 | /*immediate source*/ | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 21 |     val COMMAND = Value("command")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 22 |     val KEYWORD = Value("keyword")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 23 |     val IDENT = Value("identifier")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 24 |     val LONG_IDENT = Value("long identifier")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 25 |     val SYM_IDENT = Value("symbolic identifier")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 26 |     val VAR = Value("schematic variable")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 27 |     val TYPE_IDENT = Value("type variable")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 28 |     val TYPE_VAR = Value("schematic type variable")
 | 
| 40290 
47f572aff50a
support for floating-point tokens in outer syntax (coinciding with inner syntax version);
 wenzelm parents: 
38367diff
changeset | 29 |     val NAT = Value("natural number")
 | 
| 
47f572aff50a
support for floating-point tokens in outer syntax (coinciding with inner syntax version);
 wenzelm parents: 
38367diff
changeset | 30 |     val FLOAT = Value("floating-point number")
 | 
| 59081 | 31 |     val SPACE = Value("white space")
 | 
| 32 | /*delimited content*/ | |
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 33 |     val STRING = Value("string")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 34 |     val ALT_STRING = Value("back-quoted string")
 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 35 |     val VERBATIM = Value("verbatim text")
 | 
| 55512 | 36 |     val CARTOUCHE = Value("text cartouche")
 | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 37 |     val COMMENT = Value("comment text")
 | 
| 59081 | 38 | /*special content*/ | 
| 48754 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 39 |     val ERROR = Value("bad input")
 | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 40 |     val UNPARSED = Value("unparsed input")
 | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 41 | } | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 42 | |
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 43 | |
| 55494 | 44 | /* parsers */ | 
| 45 | ||
| 46 | object Parsers extends Parsers | |
| 47 | ||
| 48 | trait Parsers extends Scan.Parsers | |
| 49 |   {
 | |
| 50 | private def delimited_token: Parser[Token] = | |
| 51 |     {
 | |
| 52 |       val string = quoted("\"") ^^ (x => Token(Token.Kind.STRING, x))
 | |
| 53 |       val alt_string = quoted("`") ^^ (x => Token(Token.Kind.ALT_STRING, x))
 | |
| 54 | val verb = verbatim ^^ (x => Token(Token.Kind.VERBATIM, x)) | |
| 55 | val cart = cartouche ^^ (x => Token(Token.Kind.CARTOUCHE, x)) | |
| 56 | val cmt = comment ^^ (x => Token(Token.Kind.COMMENT, x)) | |
| 57 | ||
| 58 | string | (alt_string | (verb | (cart | cmt))) | |
| 59 | } | |
| 60 | ||
| 58900 | 61 | private def other_token(keywords: Keyword.Keywords): Parser[Token] = | 
| 55494 | 62 |     {
 | 
| 63 | val letdigs1 = many1(Symbol.is_letdig) | |
| 62103 | 64 | val sub = one(s => s == Symbol.sub_decoded || s == Symbol.sub) | 
| 55494 | 65 | val id = | 
| 66 | one(Symbol.is_letter) ~ | |
| 67 |           (rep(letdigs1 | (sub ~ letdigs1 ^^ { case x ~ y => x + y })) ^^ (_.mkString)) ^^
 | |
| 68 |         { case x ~ y => x + y }
 | |
| 69 | ||
| 70 | val nat = many1(Symbol.is_digit) | |
| 71 |       val natdot = nat ~ "." ~ nat ^^ { case x ~ y ~ z => x + y + z }
 | |
| 72 |       val id_nat = id ~ opt("." ~ nat) ^^ { case x ~ Some(y ~ z) => x + y + z case x ~ None => x }
 | |
| 73 | ||
| 74 |       val ident = id ~ rep("." ~> id) ^^
 | |
| 75 |         { case x ~ Nil => Token(Token.Kind.IDENT, x)
 | |
| 76 |           case x ~ ys => Token(Token.Kind.LONG_IDENT, (x :: ys).mkString(".")) }
 | |
| 77 | ||
| 78 |       val var_ = "?" ~ id_nat ^^ { case x ~ y => Token(Token.Kind.VAR, x + y) }
 | |
| 79 |       val type_ident = "'" ~ id ^^ { case x ~ y => Token(Token.Kind.TYPE_IDENT, x + y) }
 | |
| 80 |       val type_var = "?'" ~ id_nat ^^ { case x ~ y => Token(Token.Kind.TYPE_VAR, x + y) }
 | |
| 81 | val nat_ = nat ^^ (x => Token(Token.Kind.NAT, x)) | |
| 82 | val float = | |
| 83 |         ("-" ~ natdot ^^ { case x ~ y => x + y } | natdot) ^^ (x => Token(Token.Kind.FLOAT, x))
 | |
| 84 | ||
| 85 | val sym_ident = | |
| 86 | (many1(Symbol.is_symbolic_char) | one(sym => Symbol.is_symbolic(sym))) ^^ | |
| 87 | (x => Token(Token.Kind.SYM_IDENT, x)) | |
| 88 | ||
| 58899 | 89 | val keyword = | 
| 58900 | 90 | literal(keywords.minor) ^^ (x => Token(Token.Kind.KEYWORD, x)) ||| | 
| 91 | literal(keywords.major) ^^ (x => Token(Token.Kind.COMMAND, x)) | |
| 55494 | 92 | |
| 93 | val space = many1(Symbol.is_blank) ^^ (x => Token(Token.Kind.SPACE, x)) | |
| 94 | ||
| 95 | val recover_delimited = | |
| 96 |         (recover_quoted("\"") |
 | |
| 97 |           (recover_quoted("`") |
 | |
| 98 | (recover_verbatim | | |
| 99 | (recover_cartouche | recover_comment)))) ^^ (x => Token(Token.Kind.ERROR, x)) | |
| 100 | ||
| 101 | val bad = one(_ => true) ^^ (x => Token(Token.Kind.ERROR, x)) | |
| 102 | ||
| 103 | space | (recover_delimited | | |
| 104 | (((ident | (var_ | (type_ident | (type_var | (float | (nat_ | sym_ident)))))) ||| | |
| 58899 | 105 | keyword) | bad)) | 
| 55494 | 106 | } | 
| 107 | ||
| 58900 | 108 | def token(keywords: Keyword.Keywords): Parser[Token] = | 
| 109 | delimited_token | other_token(keywords) | |
| 55494 | 110 | |
| 58900 | 111 | def token_line(keywords: Keyword.Keywords, ctxt: Scan.Line_Context) | 
| 55510 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 112 | : Parser[(Token, Scan.Line_Context)] = | 
| 55494 | 113 |     {
 | 
| 114 | val string = | |
| 55510 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 115 |         quoted_line("\"", ctxt) ^^ { case (x, c) => (Token(Token.Kind.STRING, x), c) }
 | 
| 55494 | 116 | val alt_string = | 
| 55510 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 117 |         quoted_line("`", ctxt) ^^ { case (x, c) => (Token(Token.Kind.ALT_STRING, x), c) }
 | 
| 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 118 |       val verb = verbatim_line(ctxt) ^^ { case (x, c) => (Token(Token.Kind.VERBATIM, x), c) }
 | 
| 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 119 |       val cart = cartouche_line(ctxt) ^^ { case (x, c) => (Token(Token.Kind.CARTOUCHE, x), c) }
 | 
| 
1585a65aad64
tuned signature -- emphasize line-oriented aspect;
 wenzelm parents: 
55505diff
changeset | 120 |       val cmt = comment_line(ctxt) ^^ { case (x, c) => (Token(Token.Kind.COMMENT, x), c) }
 | 
| 58900 | 121 |       val other = other_token(keywords) ^^ { case x => (x, Scan.Finished) }
 | 
| 55494 | 122 | |
| 123 | string | (alt_string | (verb | (cart | (cmt | other)))) | |
| 124 | } | |
| 125 | } | |
| 126 | ||
| 127 | ||
| 59083 | 128 | /* explode */ | 
| 129 | ||
| 130 | def explode(keywords: Keyword.Keywords, inp: CharSequence): List[Token] = | |
| 64824 | 131 |     Parsers.parseAll(Parsers.rep(Parsers.token(keywords)), Scan.char_reader(inp)) match {
 | 
| 59083 | 132 | case Parsers.Success(tokens, _) => tokens | 
| 133 |       case _ => error("Unexpected failure of tokenizing input:\n" + inp.toString)
 | |
| 134 | } | |
| 135 | ||
| 136 | def explode_line(keywords: Keyword.Keywords, inp: CharSequence, context: Scan.Line_Context) | |
| 137 | : (List[Token], Scan.Line_Context) = | |
| 138 |   {
 | |
| 64824 | 139 | var in: input.Reader[Char] = Scan.char_reader(inp) | 
| 59083 | 140 | val toks = new mutable.ListBuffer[Token] | 
| 141 | var ctxt = context | |
| 142 |     while (!in.atEnd) {
 | |
| 143 |       Parsers.parse(Parsers.token_line(keywords, ctxt), in) match {
 | |
| 60215 | 144 | case Parsers.Success((x, c), rest) => toks += x; ctxt = c; in = rest | 
| 59083 | 145 | case Parsers.NoSuccess(_, rest) => | 
| 146 |           error("Unexpected failure of tokenizing input:\n" + rest.source.toString)
 | |
| 147 | } | |
| 148 | } | |
| 149 | (toks.toList, ctxt) | |
| 150 | } | |
| 151 | ||
| 64671 | 152 | val newline: Token = explode(Keyword.Keywords.empty, "\n").head | 
| 153 | ||
| 59083 | 154 | |
| 65523 | 155 | /* names */ | 
| 156 | ||
| 157 | def read_name(keywords: Keyword.Keywords, inp: CharSequence): Option[Token] = | |
| 158 |     explode(keywords, inp) match {
 | |
| 159 | case List(tok) if tok.is_name => Some(tok) | |
| 160 | case _ => None | |
| 161 | } | |
| 162 | ||
| 163 | def quote_name(keywords: Keyword.Keywords, name: String): String = | |
| 164 | if (read_name(keywords, name).isDefined) name | |
| 165 |     else quote(name.replace("\"", "\\\""))
 | |
| 166 | ||
| 167 | ||
| 59735 | 168 | /* implode */ | 
| 169 | ||
| 170 | def implode(toks: List[Token]): String = | |
| 171 |     toks match {
 | |
| 172 | case List(tok) => tok.source | |
| 60215 | 173 | case _ => toks.map(_.source).mkString | 
| 59735 | 174 | } | 
| 175 | ||
| 176 | ||
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 177 | /* token reader */ | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 178 | |
| 56464 | 179 | object Pos | 
| 180 |   {
 | |
| 59706 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 181 | val none: Pos = new Pos(0, 0, "", "") | 
| 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 182 | val start: Pos = new Pos(1, 1, "", "") | 
| 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 183 | def file(file: String): Pos = new Pos(1, 1, file, "") | 
| 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 184 | def id(id: String): Pos = new Pos(0, 1, "", id) | 
| 59715 
4f0d0e4ad68d
avoid duplicate header errors, more precise positions;
 wenzelm parents: 
59706diff
changeset | 185 | val command: Pos = id(Markup.COMMAND) | 
| 56464 | 186 | } | 
| 187 | ||
| 59671 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 188 | final class Pos private[Token]( | 
| 59696 | 189 | val line: Int, | 
| 190 | val offset: Symbol.Offset, | |
| 59706 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 191 | val file: String, | 
| 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 192 | val id: String) | 
| 64824 | 193 | extends input.Position | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 194 |   {
 | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 195 | def column = 0 | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 196 | def lineContents = "" | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 197 | |
| 56464 | 198 | def advance(token: Token): Pos = | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 199 |     {
 | 
| 59671 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 200 | var line1 = line | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 201 | var offset1 = offset | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 202 |       for (s <- Symbol.iterator(token.source)) {
 | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 203 | if (line1 > 0 && Symbol.is_newline(s)) line1 += 1 | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 204 | if (offset1 > 0) offset1 += 1 | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 205 | } | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 206 | if (line1 == line && offset1 == offset) this | 
| 59706 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 207 | else new Pos(line1, offset1, file, id) | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 208 | } | 
| 56464 | 209 | |
| 59695 | 210 | private def position(end_offset: Symbol.Offset): Position.T = | 
| 59671 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 211 | (if (line > 0) Position.Line(line) else Nil) ::: | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 212 | (if (offset > 0) Position.Offset(offset) else Nil) ::: | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 213 | (if (end_offset > 0) Position.End_Offset(end_offset) else Nil) ::: | 
| 59706 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 214 | (if (file != "") Position.File(file) else Nil) ::: | 
| 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59705diff
changeset | 215 | (if (id != "") Position.Id_String(id) else Nil) | 
| 59671 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 216 | |
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 217 | def position(): Position.T = position(0) | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 218 | def position(token: Token): Position.T = position(advance(token).offset) | 
| 
9715eb8e9408
more precise position information in Isabelle/Scala, with YXML markup as in Isabelle/ML;
 wenzelm parents: 
59122diff
changeset | 219 | |
| 64728 | 220 | override def toString: String = Position.here(position(), delimited = false) | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 221 | } | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 222 | |
| 64824 | 223 | abstract class Reader extends input.Reader[Token] | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 224 | |
| 56464 | 225 | private class Token_Reader(tokens: List[Token], val pos: Pos) extends Reader | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 226 |   {
 | 
| 34157 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 227 | def first = tokens.head | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 228 | def rest = new Token_Reader(tokens.tail, pos.advance(first)) | 
| 
0a0a19153626
explicit representation of Token_Kind -- cannot really depend on runtime types due to erasure;
 wenzelm parents: 
34143diff
changeset | 229 | def atEnd = tokens.isEmpty | 
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 230 | } | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 231 | |
| 59705 | 232 | def reader(tokens: List[Token], start: Token.Pos): Reader = | 
| 233 | new Token_Reader(tokens, start) | |
| 65335 | 234 | |
| 235 | ||
| 236 | /* XML data representation */ | |
| 237 | ||
| 238 | val encode: XML.Encode.T[Token] = (tok: Token) => | |
| 239 |   {
 | |
| 240 | import XML.Encode._ | |
| 241 | pair(int, string)(tok.kind.id, tok.source) | |
| 242 | } | |
| 243 | ||
| 244 | val decode: XML.Decode.T[Token] = (body: XML.Body) => | |
| 245 |   {
 | |
| 246 | import XML.Decode._ | |
| 247 | val (k, s) = pair(int, string)(body) | |
| 248 | Token(Kind(k), s) | |
| 249 | } | |
| 34139 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 250 | } | 
| 
d1ded303fe0e
Outer lexical syntax for Isabelle/Isar -- Scala version.
 wenzelm parents: diff
changeset | 251 | |
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 252 | |
| 60215 | 253 | sealed case class Token(kind: Token.Kind.Value, source: String) | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 254 | {
 | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 255 | def is_command: Boolean = kind == Token.Kind.COMMAND | 
| 63446 | 256 | def is_command(name: String): Boolean = kind == Token.Kind.COMMAND && source == name | 
| 48718 | 257 | def is_keyword: Boolean = kind == Token.Kind.KEYWORD | 
| 63446 | 258 | def is_keyword(name: String): Boolean = kind == Token.Kind.KEYWORD && source == name | 
| 63450 | 259 | def is_keyword(name: Char): Boolean = | 
| 260 | kind == Token.Kind.KEYWORD && source.length == 1 && source(0) == name | |
| 55505 | 261 | def is_delimiter: Boolean = is_keyword && !Symbol.is_ascii_identifier(source) | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: 
48349diff
changeset | 262 | def is_ident: Boolean = kind == Token.Kind.IDENT | 
| 48605 
e777363440d6
allow negative int values as well, according to real = int | float;
 wenzelm parents: 
48599diff
changeset | 263 | def is_sym_ident: Boolean = kind == Token.Kind.SYM_IDENT | 
| 46943 | 264 | def is_string: Boolean = kind == Token.Kind.STRING | 
| 48349 
a78e5d399599
support Session.Queue with ordering and dependencies;
 wenzelm parents: 
48335diff
changeset | 265 | def is_nat: Boolean = kind == Token.Kind.NAT | 
| 48365 
d88aefda01c4
basic support for stand-alone options with external string representation;
 wenzelm parents: 
48349diff
changeset | 266 | def is_float: Boolean = kind == Token.Kind.FLOAT | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 267 | def is_name: Boolean = | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 268 | kind == Token.Kind.IDENT || | 
| 62969 | 269 | kind == Token.Kind.LONG_IDENT || | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 270 | kind == Token.Kind.SYM_IDENT || | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 271 | kind == Token.Kind.STRING || | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 272 | kind == Token.Kind.NAT | 
| 64471 
c40c2975fb02
more uniform path syntax, as in ML (see 5a7c919a4ada);
 wenzelm parents: 
63477diff
changeset | 273 | def is_embedded: Boolean = is_name || | 
| 
c40c2975fb02
more uniform path syntax, as in ML (see 5a7c919a4ada);
 wenzelm parents: 
63477diff
changeset | 274 | kind == Token.Kind.CARTOUCHE || | 
| 
c40c2975fb02
more uniform path syntax, as in ML (see 5a7c919a4ada);
 wenzelm parents: 
63477diff
changeset | 275 | kind == Token.Kind.VAR || | 
| 
c40c2975fb02
more uniform path syntax, as in ML (see 5a7c919a4ada);
 wenzelm parents: 
63477diff
changeset | 276 | kind == Token.Kind.TYPE_IDENT || | 
| 
c40c2975fb02
more uniform path syntax, as in ML (see 5a7c919a4ada);
 wenzelm parents: 
63477diff
changeset | 277 | kind == Token.Kind.TYPE_VAR | 
| 62969 | 278 | def is_text: Boolean = is_name || kind == Token.Kind.VERBATIM || kind == Token.Kind.CARTOUCHE | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 279 | def is_space: Boolean = kind == Token.Kind.SPACE | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 280 | def is_comment: Boolean = kind == Token.Kind.COMMENT | 
| 51048 
123be08eed88
clarified notion of Command.proper_range (according to Token.is_proper), especially relevant for Active.try_replace_command, to avoid loosing subsequent comments accidentally;
 wenzelm parents: 
48754diff
changeset | 281 | def is_improper: Boolean = is_space || is_comment | 
| 48599 | 282 | def is_proper: Boolean = !is_space && !is_comment | 
| 48754 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 283 | def is_error: Boolean = kind == Token.Kind.ERROR | 
| 47012 
0e246130486b
clarified command span classification: strict Command.is_command, permissive Command.name;
 wenzelm parents: 
46943diff
changeset | 284 | def is_unparsed: Boolean = kind == Token.Kind.UNPARSED | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 285 | |
| 48754 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 286 | def is_unfinished: Boolean = is_error && | 
| 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 287 |    (source.startsWith("\"") ||
 | 
| 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 288 |     source.startsWith("`") ||
 | 
| 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 289 |     source.startsWith("{*") ||
 | 
| 57021 
6a8fd2ac6756
explicit treatment of unfinished cartouches, which is important for Thy_Syntax.consolidate_spans;
 wenzelm parents: 
56998diff
changeset | 290 |     source.startsWith("(*") ||
 | 
| 
6a8fd2ac6756
explicit treatment of unfinished cartouches, which is important for Thy_Syntax.consolidate_spans;
 wenzelm parents: 
56998diff
changeset | 291 | source.startsWith(Symbol.open) || | 
| 
6a8fd2ac6756
explicit treatment of unfinished cartouches, which is important for Thy_Syntax.consolidate_spans;
 wenzelm parents: 
56998diff
changeset | 292 | source.startsWith(Symbol.open_decoded)) | 
| 48754 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 wenzelm parents: 
48718diff
changeset | 293 | |
| 63450 | 294 | def is_open_bracket: Boolean = is_keyword && Word.open_brackets.exists(is_keyword(_)) | 
| 295 | def is_close_bracket: Boolean = is_keyword && Word.close_brackets.exists(is_keyword(_)) | |
| 296 | ||
| 63446 | 297 |   def is_begin: Boolean = is_keyword("begin")
 | 
| 298 |   def is_end: Boolean = is_command("end")
 | |
| 63477 
f5c81436b930
clarified indentation: 'begin' is treated like a separate command without indent;
 wenzelm parents: 
63450diff
changeset | 299 | def is_begin_or_command: Boolean = is_begin || is_command | 
| 43611 | 300 | |
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 301 | def content: String = | 
| 55492 
28d4db6c6e79
tuned signature -- separate Lexicon from Parsers (in accordance to ML version);
 wenzelm parents: 
55137diff
changeset | 302 |     if (kind == Token.Kind.STRING) Scan.Parsers.quoted_content("\"", source)
 | 
| 
28d4db6c6e79
tuned signature -- separate Lexicon from Parsers (in accordance to ML version);
 wenzelm parents: 
55137diff
changeset | 303 |     else if (kind == Token.Kind.ALT_STRING) Scan.Parsers.quoted_content("`", source)
 | 
| 
28d4db6c6e79
tuned signature -- separate Lexicon from Parsers (in accordance to ML version);
 wenzelm parents: 
55137diff
changeset | 304 | else if (kind == Token.Kind.VERBATIM) Scan.Parsers.verbatim_content(source) | 
| 
28d4db6c6e79
tuned signature -- separate Lexicon from Parsers (in accordance to ML version);
 wenzelm parents: 
55137diff
changeset | 305 | else if (kind == Token.Kind.CARTOUCHE) Scan.Parsers.cartouche_content(source) | 
| 
28d4db6c6e79
tuned signature -- separate Lexicon from Parsers (in accordance to ML version);
 wenzelm parents: 
55137diff
changeset | 306 | else if (kind == Token.Kind.COMMENT) Scan.Parsers.comment_content(source) | 
| 36956 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 307 | else source | 
| 
21be4832c362
renamed class Outer_Lex to Token and Token_Kind to Token.Kind;
 wenzelm parents: 
34311diff
changeset | 308 | } |