alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (SyntaxHigh.scala)

This example Scala source code file (SyntaxHigh.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Scala source code examples by using tags.

All credit for the original source code belongs to scala-lang.org; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Scala tags/keywords

annotation, app, array, boolean, e, int, string, stringbuilder, symbol, syntaxhigh, unit, xml

The SyntaxHigh.scala Scala example source code

/* NSC -- new Scala compiler
 * Copyright 2010-2013 LAMP/EPFL
 * @author  Stephane Micheloud
 */

package scala
package tools.nsc.doc.html

import scala.xml.NodeSeq
import scala.annotation.tailrec

/** 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
    }

    @tailrec def parse(pre: String, i: Int): Unit = {
      out append pre
      if (i == buf.length) return
      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).toInt) ||
                (buf(i) == '.' && i + 1 < buf.length && Character.isDigit(buf(i+1).toInt))) {
              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)
      }
    }

    parse("", 0)
    scala.xml.Unparsed(out.toString)
  }
}

Other Scala source code examples

Here is a short list of links related to this Scala SyntaxHigh.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.