diff options
author | Paul Phillips <paulp@improving.org> | 2013-03-06 07:39:19 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-09 11:59:07 -0800 |
commit | c6ca941ccc017a8869f4def717cfeb640f965077 (patch) | |
tree | e21038cc55d3a4231544d148913504a754eafdf8 /src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala | |
parent | 9094822181c398b945b7f30ac1e2b05da9796f53 (diff) | |
download | scala-c6ca941ccc017a8869f4def717cfeb640f965077.tar.gz scala-c6ca941ccc017a8869f4def717cfeb640f965077.tar.bz2 scala-c6ca941ccc017a8869f4def717cfeb640f965077.zip |
Moved scaladoc sources into separate directory.
This change is not externally visible. It moves the scaladoc
sources into src/scaladoc and adds an ant target for building
them. The compilation products are still packaged into
scala-compiler.jar as before, but with a small change to
build.xml a separate jar can be created instead.
Diffstat (limited to 'src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala')
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala new file mode 100644 index 0000000000..5781e680dd --- /dev/null +++ b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala @@ -0,0 +1,286 @@ +/* NSC -- new Scala compiler + * Copyright 2010-2013 LAMP/EPFL + * @author Stephane Micheloud + */ + +package scala.tools.nsc.doc.html + +import scala.xml.NodeSeq + +/** Highlight the syntax of Scala code appearing in a `{{{` wiki block + * (see method `HtmlPage.blockToHtml`). + * + * @author Stephane Micheloud + * @version 1.0 + */ +private[html] object SyntaxHigh { + + /** Reserved words, sorted alphabetically + * (see [[scala.reflect.internal.StdNames]]) */ + val reserved = Array( + "abstract", "case", "catch", "class", "def", + "do", "else", "extends", "false", "final", "finally", + "for", "if", "implicit", "import", "lazy", "match", + "new", "null", "object", "override", "package", + "private", "protected", "return", "sealed", "super", + "this", "throw", "trait", "true", "try", "type", + "val", "var", "while", "with", "yield") + + /** Annotations, sorted alphabetically */ + val annotations = Array( + "BeanProperty", "SerialVersionUID", + "beanGetter", "beanSetter", "bridge", + "deprecated", "deprecatedName", "deprecatedOverriding", "deprecatedInheritance", + "elidable", "field", "getter", "inline", + "migration", "native", "noinline", "param", + "remote", "setter", "specialized", "strictfp", "switch", + "tailrec", "throws", "transient", + "unchecked", "uncheckedStable", "uncheckedVariance", + "varargs", "volatile") + + /** Standard library classes/objects, sorted alphabetically */ + val standards = Array ( + "WeakTypeTag", "Any", "AnyRef", "AnyVal", "App", "Array", + "Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest", + "Console", "Double", "Enumeration", "Float", "Function", "Int", + "List", "Long", "Manifest", "Map", + "NoManifest", "None", "Nothing", "Null", "Object", "Option", "OptManifest", + "Pair", "Predef", + "Seq", "Set", "Short", "Some", "String", "Symbol", + "Triple", "TypeTag", "Unit") + + def apply(data: String): NodeSeq = { + val buf = data.getBytes + val out = new StringBuilder + + def compare(offset: Int, key: String): Int = { + var i = offset + var j = 0 + val l = key.length + while (i < buf.length && j < l) { + val bch = buf(i).toChar + val kch = key charAt j + if (bch < kch) return -1 + else if (bch > kch) return 1 + i += 1 + j += 1 + } + if (j < l) -1 + else if (i < buf.length && + ('A' <= buf(i) && buf(i) <= 'Z' || + 'a' <= buf(i) && buf(i) <= 'z' || + '0' <= buf(i) && buf(i) <= '9' || + buf(i) == '_')) 1 + else 0 + } + + def lookup(a: Array[String], i: Int): Int = { + var lo = 0 + var hi = a.length - 1 + while (lo <= hi) { + val m = (hi + lo) / 2 + val d = compare(i, a(m)) + if (d < 0) hi = m - 1 + else if (d > 0) lo = m + 1 + else return m + } + -1 + } + + def comment(i: Int): String = { + val out = new StringBuilder("/") + def line(i: Int): Int = + if (i == buf.length || buf(i) == '\n') i + else { + out append buf(i).toChar + line(i+1) + } + var level = 0 + def multiline(i: Int, star: Boolean): Int = { + if (i == buf.length) return i + val ch = buf(i).toChar + out append ch + ch match { + case '*' => + if (star) level += 1 + multiline(i+1, !star) + case '/' => + if (star) { + if (level > 0) level -= 1 + if (level == 0) i else multiline(i+1, star = true) + } else + multiline(i+1, star = false) + case _ => + multiline(i+1, star = false) + } + } + if (buf(i) == '/') line(i) else multiline(i, star = true) + out.toString + } + + /* e.g. `val endOfLine = '\u000A'`*/ + def charlit(j: Int): String = { + val out = new StringBuilder("'") + def charlit0(i: Int, bslash: Boolean): Int = { + if (i == buf.length) i + else if (i > j+6) { out setLength 0; j } + else { + val ch = buf(i).toChar + out append ch + ch match { + case '\\' => + charlit0(i+1, bslash = true) + case '\'' if !bslash => + i + case _ => + if (bslash && '0' <= ch && ch <= '9') charlit0(i+1, bslash = true) + else charlit0(i+1, bslash = false) + } + } + } + charlit0(j, bslash = false) + out.toString + } + + def strlit(i: Int): String = { + val out = new StringBuilder("\"") + def strlit0(i: Int, bslash: Boolean): Int = { + if (i == buf.length) return i + val ch = buf(i).toChar + out append ch + ch match { + case '\\' => + strlit0(i+1, bslash = true) + case '"' if !bslash => + i + case _ => + strlit0(i+1, bslash = false) + } + } + strlit0(i, bslash = false) + out.toString + } + + def numlit(i: Int): String = { + val out = new StringBuilder + def intg(i: Int): Int = { + if (i == buf.length) return i + val ch = buf(i).toChar + ch match { + case '.' => + out append ch + frac(i+1) + case _ => + if (Character.isDigit(ch)) { + out append ch + intg(i+1) + } else i + } + } + def frac(i: Int): Int = { + if (i == buf.length) return i + val ch = buf(i).toChar + ch match { + case 'e' | 'E' => + out append ch + expo(i+1, signed = false) + case _ => + if (Character.isDigit(ch)) { + out append ch + frac(i+1) + } else i + } + } + def expo(i: Int, signed: Boolean): Int = { + if (i == buf.length) return i + val ch = buf(i).toChar + ch match { + case '+' | '-' if !signed => + out append ch + expo(i+1, signed = true) + case _ => + if (Character.isDigit(ch)) { + out append ch + expo(i+1, signed) + } else i + } + } + intg(i) + out.toString + } + + def parse(pre: String, i: Int): Int = { + out append pre + if (i == buf.length) return i + buf(i) match { + case '\n' => + parse("\n", i+1) + case ' ' => + parse(" ", i+1) + case '&' => + parse("&", i+1) + case '<' if i+1 < buf.length => + val ch = buf(i+1).toChar + if (ch == '-' || ch == ':' || ch == '%') + parse("<span class=\"kw\"><"+ch+"</span>", i+2) + else + parse("<", i+1) + case '>' => + if (i+1 < buf.length && buf(i+1) == ':') + parse("<span class=\"kw\">>:</span>", i+2) + else + parse(">", i+1) + case '=' => + if (i+1 < buf.length && buf(i+1) == '>') + parse("<span class=\"kw\">=></span>", i+2) + else + parse(buf(i).toChar.toString, i+1) + case '/' => + if (i+1 < buf.length && (buf(i+1) == '/' || buf(i+1) == '*')) { + val c = comment(i+1) + parse("<span class=\"cmt\">"+c+"</span>", i+c.length) + } else + parse(buf(i).toChar.toString, i+1) + case '\'' => + val s = charlit(i+1) + if (s.length > 0) + parse("<span class=\"lit\">"+s+"</span>", i+s.length) + else + parse(buf(i).toChar.toString, i+1) + case '"' => + val s = strlit(i+1) + parse("<span class=\"lit\">"+s+"</span>", i+s.length) + case '@' => + val k = lookup(annotations, i+1) + if (k >= 0) + parse("<span class=\"ano\">@"+annotations(k)+"</span>", i+annotations(k).length+1) + else + parse(buf(i).toChar.toString, i+1) + case _ => + if (i == 0 || (i >= 1 && !Character.isJavaIdentifierPart(buf(i-1).toChar))) { + if (Character.isDigit(buf(i)) || + (buf(i) == '.' && i + 1 < buf.length && Character.isDigit(buf(i+1)))) { + val s = numlit(i) + parse("<span class=\"num\">"+s+"</span>", i+s.length) + } else { + val k = lookup(reserved, i) + if (k >= 0) + parse("<span class=\"kw\">"+reserved(k)+"</span>", i+reserved(k).length) + else { + val k = lookup(standards, i) + if (k >= 0) + parse("<span class=\"std\">"+standards(k)+"</span>", i+standards(k).length) + else + parse(buf(i).toChar.toString, i+1) + } + } + } else + parse(buf(i).toChar.toString, i+1) + } + i + } + + parse("", 0) + scala.xml.Unparsed(out.toString) + } +} |