diff options
author | Jakob Odersky <jakob@odersky.com> | 2019-10-22 00:55:50 -0400 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2019-11-08 22:34:57 -0500 |
commit | 99dfd5a3ececf39ae3fd30cbf9581c2fb5da2ba5 (patch) | |
tree | 59dd8a2f5283d436b300478b7197bb8ec9f5164e /yamlesque/src/main | |
parent | 70141fc60ec3341057627e9a8f5b83a22c74f0ea (diff) | |
download | yamlesque-0.2.0.tar.gz yamlesque-0.2.0.tar.bz2 yamlesque-0.2.0.zip |
Major refactor for version 0.2.00.2.0
Diffstat (limited to 'yamlesque/src/main')
-rw-r--r-- | yamlesque/src/main/scala/YamlParser.scala | 258 | ||||
-rw-r--r-- | yamlesque/src/main/scala/YamlPrinter.scala | 48 | ||||
-rw-r--r-- | yamlesque/src/main/scala/formats.scala | 8 | ||||
-rw-r--r-- | yamlesque/src/main/scala/package.scala | 26 | ||||
-rw-r--r-- | yamlesque/src/main/scala/yamlValues.scala | 23 |
5 files changed, 0 insertions, 363 deletions
diff --git a/yamlesque/src/main/scala/YamlParser.scala b/yamlesque/src/main/scala/YamlParser.scala deleted file mode 100644 index f7a0f9b..0000000 --- a/yamlesque/src/main/scala/YamlParser.scala +++ /dev/null @@ -1,258 +0,0 @@ -package yamlesque - -import annotation.{switch, tailrec} -import scala.collection.mutable.ListBuffer - -object YamlParser extends (Iterator[Char] => YamlValue) { - - sealed trait TokenKind - object TokenKind { - case object EOF extends TokenKind - case object BAD extends TokenKind - case object DOCSTART extends TokenKind - case object DOCEND extends TokenKind - case object MAPPING extends TokenKind - case object ITEM extends TokenKind - case object IDENTIFIER extends TokenKind - case object COMMENT extends TokenKind - } - import TokenKind._ - - case class Token(val kind: TokenKind, value: String = "") { - var line: Int = 0 - var col: Int = 0 - def setPos(line: Int, col: Int): this.type = { - this.col = col - this.line = line - this - } - override def toString() = { - s"($line, $col): " + super.toString - } - } - - object Chars { - final val LF = '\u000A' - final val CR = '\u000D' - final val SU = '\u001A' - - @inline def isSpace(ch: Char): Boolean = ch match { - case ' ' | '\t' => true - case _ => false - } - - @inline def isBlank(ch: Char): Boolean = ch match { - case ' ' | '\t' | CR | LF | SU => true - case _ => false - } - } - - class Scanner(chars: Iterator[Char]) extends Iterator[Token] { - import Chars._ - - private var ch0: Char = 0 - private var ch1: Char = 0 - private var ch2: Char = 0 - private var pos: Long = 0 - private var line: Int = 0 - private var col: Int = 0 - - private def skipChar(): Unit = { - val ch: Char = if (chars.hasNext) { - chars.next() - } else { - SU - } - pos += 1 - col += 1 - ch0 = ch1 - ch1 = ch2 - ch2 = ch - } - private def skipChars(n: Int): Unit = { - var i = 0 - while (i < n) { skipChar(); i += 1 } - } - def init() = { - skipChars(3) - pos = 0 - col = 0 - line = 0 - } - - private var buffer = new StringBuilder() - private def putChar(): Unit = { - buffer.append(ch0) - skipChars(1) - } - private def tokenValue(): String = { - val str = buffer.result() - buffer.clear() - str - } - - private var token: Token = Token(BAD, "not yet initialized") - - @tailrec private def fetchToken(): Unit = { - ch0 match { - case ':' if isBlank(ch1) => - token = Token(MAPPING).setPos(line, col) - skipChars(1) - case '-' if isBlank(ch1) => - token = Token(ITEM).setPos(line, col) - skipChars(1) - case '-' if ch1 == '-' && ch2 == '-' => - token = Token(DOCSTART).setPos(line, col) - skipChars(3) - case '.' if ch1 == '.' && ch2 == '.' => - token = Token(DOCEND).setPos(line, col) - skipChars(3) - case '#' => - val l = line - val c = col - skipChars(1) - while (ch0 != LF && ch0 != SU) { - putChar() - } - token = Token(COMMENT, tokenValue()).setPos(l, c) - buffer.clear() - case c if isSpace(c) => - skipChars(1) - fetchToken() - case LF => - skipChars(1) - col = 0 - line += 1 - fetchToken() - case CR => - skipChars(1) - if (ch0 == LF) { - skipChars(1) - } - col = 0 - line += 1 - fetchToken() - case SU => - token = Token(EOF).setPos(line, col) - skipChars(1) - case _ => fetchScalar() - } - } - - private def fetchScalar(): Unit = { - val l = line - val c = col - @tailrec def fetchRest(): Unit = ch0 match { - case ':' if isBlank(ch1) => - token = Token(IDENTIFIER, tokenValue()) - case LF => - token = Token(IDENTIFIER, tokenValue()) - case SU => - token = Token(IDENTIFIER, tokenValue()) - case c => - putChar() - fetchRest() - } - fetchRest() - token.setPos(l, c) - } - - override def hasNext: Boolean = true - override def next(): Token = { - fetchToken() - token - } - init() - } - - def parse(tokens: Iterator[Token]): YamlValue = { - var token0 = tokens.next() - var token1 = tokens.next() - - def readNext(): Unit = { - token0 = token1 - token1 = tokens.next() - } - - def fatal(message: String, token: Token) = { - val completeMessage = - s"parse error at line ${token.line}, column ${token.col}: $message" - throw new ParseException(completeMessage) - } - - def wrongKind(found: Token, required: TokenKind*) = { - fatal( - s"token kind not allowed at this position\n" + - s" found: ${found.kind}\n" + - s" required: ${required.mkString(" or ")}\n" + - " " * found.col + found.value + "\n" + - " " * found.col + "^", - found - ) - } - - def nextSequence() = { - val startCol = token0.col - val items = new ListBuffer[YamlValue] - while (startCol <= token0.col && token0.kind != EOF) { - token0.kind match { - case ITEM => - readNext() - items += nextBlock(startCol + 1) - case _ => wrongKind(token0, ITEM) - } - } - YamlSequence(items.toVector) - } - - def nextMapping() = { - val startCol = token0.col - val fields = new ListBuffer[(String, YamlValue)] - while (startCol <= token0.col && token0.kind != EOF) { - token0.kind match { - case IDENTIFIER => - val key = token0.value - readNext() - token0.kind match { - case MAPPING => - readNext() - val value = nextBlock(startCol + 1) - fields += key -> value - case _ => wrongKind(token0, MAPPING) - } - - case _ => wrongKind(token0, IDENTIFIER) - } - } - YamlMapping(fields.toMap) - } - - def nextBlock(startCol: Int): YamlValue = { - if (token0.col < startCol) { - YamlEmpty - } else { - token0.kind match { - case IDENTIFIER => - if (token1.kind == MAPPING && token0.line == token1.line) { - nextMapping() - } else { - val y = YamlScalar(token0.value) - readNext() - y - } - case ITEM => - nextSequence() - case EOF => YamlEmpty - case _ => wrongKind(token0, IDENTIFIER, ITEM) - } - } - } - - nextBlock(0) - } - - def apply(data: Iterator[Char]): YamlValue = parse(new Scanner(data)) - -} - -class ParseException(val message: String) extends Exception(message) diff --git a/yamlesque/src/main/scala/YamlPrinter.scala b/yamlesque/src/main/scala/YamlPrinter.scala deleted file mode 100644 index 083a8a8..0000000 --- a/yamlesque/src/main/scala/YamlPrinter.scala +++ /dev/null @@ -1,48 +0,0 @@ -package yamlesque - -import annotation.tailrec - -class YamlPrinter(compact: Boolean = true) extends (YamlValue => String) { - - def apply(value: YamlValue): String = { - val str = new StringBuilder() - def p(value: YamlValue, indentation: Int): Unit = value match { - case YamlScalar(value) => - str ++= " " * indentation - str ++= value - str += '\n' - case YamlSequence(items) => - for (item <- items) { - str ++= " " * indentation - item match { - case YamlScalar(v) if compact => - str ++= "- " - str ++= v - str += '\n' - case _ => - str ++= "-\n" - p(item, indentation + 1) - } - } - case YamlMapping(fields) => - for ((key, value) <- fields) { - str ++= " " * indentation - str ++= key - value match { - case YamlScalar(v) if compact => - str ++= ": " - str ++= v - str += '\n' - case _ => - str ++= ":\n" - p(value, indentation + 1) - } - } - case YamlEmpty => - str += '\n' - } - p(value, 0) - str.toString - } - -} diff --git a/yamlesque/src/main/scala/formats.scala b/yamlesque/src/main/scala/formats.scala deleted file mode 100644 index 0dbbacc..0000000 --- a/yamlesque/src/main/scala/formats.scala +++ /dev/null @@ -1,8 +0,0 @@ -package yamlesque - -trait YamlReader[A] { - def read(yaml: YamlValue): A -} -trait YamlWriter[A] { - def write(a: A): YamlValue -} diff --git a/yamlesque/src/main/scala/package.scala b/yamlesque/src/main/scala/package.scala deleted file mode 100644 index c40ca70..0000000 --- a/yamlesque/src/main/scala/package.scala +++ /dev/null @@ -1,26 +0,0 @@ -package yamlesque - -object `package` { - - def deserializationError(msg: String, - cause: Throwable = null, - fieldNames: List[String] = Nil) = - throw new DeserializationException(msg, cause, fieldNames) - def serializationError(msg: String) = throw new SerializationException(msg) - - implicit class RichAny[A](val any: A) extends AnyVal { - def toYaml(implicit writer: YamlWriter[A]): YamlValue = writer.write(any) - } - - implicit class RichString(val str: String) extends AnyVal { - def parseYaml: YamlValue = YamlParser(str.toIterator) - } - -} - -case class DeserializationException(msg: String, - cause: Throwable = null, - fieldNames: List[String] = Nil) - extends RuntimeException(msg, cause) - -class SerializationException(msg: String) extends RuntimeException(msg) diff --git a/yamlesque/src/main/scala/yamlValues.scala b/yamlesque/src/main/scala/yamlValues.scala deleted file mode 100644 index 4432b9d..0000000 --- a/yamlesque/src/main/scala/yamlValues.scala +++ /dev/null @@ -1,23 +0,0 @@ -package yamlesque - -sealed trait YamlValue { - def print: String = YamlValue.DefaultPrinter(this) - def convertTo[A: YamlReader]: A = implicitly[YamlReader[A]].read(this) -} -object YamlValue { - val DefaultPrinter = new YamlPrinter(compact = true) -} - -case class YamlMapping(fields: Map[String, YamlValue]) extends YamlValue -object YamlMapping { - def apply(items: (String, YamlValue)*) = new YamlMapping(Map(items: _*)) -} - -case class YamlSequence(items: Vector[YamlValue]) extends YamlValue -object YamlSequence { - def apply(items: YamlValue*) = new YamlSequence(items.toVector) -} - -case class YamlScalar(value: String) extends YamlValue - -case object YamlEmpty extends YamlValue |