summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-07-07 14:59:10 +0000
committerBurak Emir <emir@epfl.ch>2007-07-07 14:59:10 +0000
commit40430c44da16f8f9231dbfc481f7e316509b081c (patch)
treef60f79561c69e5bfe6918137d14a733e7d9226f1 /src
parentc08f1700cad2b48114a39608c70906b18c192106 (diff)
downloadscala-40430c44da16f8f9231dbfc481f7e316509b081c.tar.gz
scala-40430c44da16f8f9231dbfc481f7e316509b081c.tar.bz2
scala-40430c44da16f8f9231dbfc481f7e316509b081c.zip
JSON parsing by Derek Chen-Becker
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/util/parsing/json/JSON.scala40
-rw-r--r--src/library/scala/util/parsing/json/Lexer.scala75
-rw-r--r--src/library/scala/util/parsing/json/Parser.scala31
3 files changed, 146 insertions, 0 deletions
diff --git a/src/library/scala/util/parsing/json/JSON.scala b/src/library/scala/util/parsing/json/JSON.scala
new file mode 100644
index 0000000000..e0431f5724
--- /dev/null
+++ b/src/library/scala/util/parsing/json/JSON.scala
@@ -0,0 +1,40 @@
+package scala.util.parsing.json
+
+import scala.collection.mutable.HashMap
+
+/** This object mainly shows how a JSON parser maybe instantiated
+ *
+ */
+object JSON extends Parser {
+ def parse(input: String) =
+ phrase(root)(new lexical.Scanner(input)) match {
+ case Success(result, _) => Some(result)
+ case _ => None
+ }
+
+ def parseFull(input: String) = parse(input) match {
+ case Some(data) => resolveType(data)
+ case None => None
+ }
+
+ def resolveType(input: Any): Any =
+ input match {
+ case jo: List[(String,Any)] =>
+ /*println("Resolving object")*/
+ val objMap = new HashMap[String,Any]()
+
+ jo.foreach {
+ case (key,value) =>
+ objMap.update(key,resolveType(value))
+ }
+
+ objMap
+
+ case ja: List[Any] =>
+ /*println("Resolving array"); */
+ ja.toArray
+ case _ @ elem =>
+ /*println("Resolving element"); */
+ elem
+ }
+}
diff --git a/src/library/scala/util/parsing/json/Lexer.scala b/src/library/scala/util/parsing/json/Lexer.scala
new file mode 100644
index 0000000000..6a6b3684a2
--- /dev/null
+++ b/src/library/scala/util/parsing/json/Lexer.scala
@@ -0,0 +1,75 @@
+package scala.util.parsing.json
+
+import scala.util.parsing.combinator._
+import scala.util.parsing.combinator.syntactical._
+import scala.util.parsing.combinator.lexical._
+import scala.util.parsing.input.CharArrayReader.EofCh
+import scala.util.parsing.combinator.~
+
+/**
+ * @author Derek Chen-Becker <java@chen-becker.org>
+ */
+
+class Lexer extends StdLexical with ImplicitConversions {
+
+ override def token: Parser[Token] =
+ ('\"' ~ rep(charSeq | letter) ~ '\"' ^^ lift(StringLit)
+ | number ~ letter ^^ { case n ~ l => ErrorToken("Invalid number format : " + n + l) }
+ | '-' ~ whitespace ~ number ~ letter ^^ {case ws ~ num ~ l => ErrorToken("Invalid number format : -" + num + l) }
+ | '-' ~ whitespace ~ number ^^ {case ws ~ num => NumericLit("-" + num)}
+ | number ^^ NumericLit
+ | EofCh ^^ EOF
+ | delim
+ | '\"' ~ failure("Unterminated string")
+ | rep(letter) ^^ checkKeyword
+ | failure("Illegal character")
+ )
+
+ def checkKeyword(xs : List[Any]) = {
+ val strRep = xs.mkString("")
+ if (reserved.contains(strRep)) Keyword(strRep) else ErrorToken("Not a keyword: " + strRep)
+ }
+
+ override def whitespace = rep(whitespaceChar)
+
+ def number = intPart ~ opt(fracPart) ~ opt(expPart) ^^ { case i ~ f ~ e =>
+ i + optString(".",f) + optString("",e)
+ }
+ def intPart = zero | intList
+ def intList = nonzero ~ rep(digit) ^^ {case x ~ y => (x :: y) mkString ""}
+ def fracPart = '.' ~ rep(digit) ^^ {x => x.mkString("")}
+ def expPart = exponent ~ opt(sign) ~ rep1(digit) ^^ { case e ~ s ~ d =>
+ e + optString("",s) + d.mkString("")
+ }
+
+ def optString[A](pre: String, a: Option[A]) = a match {
+ case Some(x) => pre + x.toString
+ case None => ""
+ }
+
+ def zero: Parser[String] = '0' ^^ toString
+ def nonzero = elem("nonzero digit", d => d.isDigit && d != '0')
+ def exponent = elem("exponent character", d => d == 'e' || d == 'E')
+ def sign = elem("sign character", d => d == '-' || d == '+')
+
+ def charSeq: Parser[String] =
+ ('\\' ~ '\"' ^^ "\""
+ |'\\' ~ '\\' ^^ "\\"
+ |'\\' ~ '/' ^^ "/"
+ |'\\' ~ 'b' ^^ "\b"
+ |'\\' ~ 'f' ^^ "\f"
+ |'\\' ~ 'n' ^^ "\n"
+ |'\\' ~ 'r' ^^ "\r"
+ |'\\' ~ 't' ^^ "\t"
+ |'\\' ~ 'u' ~ unicodeBlock)
+
+ val hexDigits = Set[Char]() ++ "0123456789abcdefABCDEF".toArray
+ def hexDigit = elem("hex digit", hexDigits.contains(_))
+
+ def unicodeBlock = hexDigit ~ hexDigit ~ hexDigit ~ hexDigit ^^ {
+ case a ~ b ~ c ~ d =>
+ new String(Character.toChars(Integer.parseInt(List(a,b,c,d).mkString(""),16)))
+ }
+
+ private def lift[T](f: String => T)(xs: List[Any]): T = f(xs.mkString(""))
+}
diff --git a/src/library/scala/util/parsing/json/Parser.scala b/src/library/scala/util/parsing/json/Parser.scala
new file mode 100644
index 0000000000..8c94e060eb
--- /dev/null
+++ b/src/library/scala/util/parsing/json/Parser.scala
@@ -0,0 +1,31 @@
+package scala.util.parsing.json;
+
+import scala.util.parsing.combinator._
+import scala.util.parsing.combinator.syntactical._
+import scala.util.parsing.combinator.lexical._
+import scala.util.parsing.input.CharArrayReader.EofCh
+import scala.util.parsing.combinator.~
+
+/**
+ * @author Derek Chen-Becker <java@chen-becker.org>
+ */
+
+class Parser extends StdTokenParsers with ImplicitConversions {
+ // Fill in abstract defs
+ type Tokens = Lexer
+ val lexical = new Tokens
+
+ // Configure lexical parsing
+ lexical.reserved ++= List("true", "false", "null")
+ lexical.delimiters ++= List("{", "}", "[", "]", ":", ",")
+
+ // Define the grammar
+ def root = jsonObj | jsonArray
+ def jsonObj = "{" ~ repsep(objEntry,",") ~ "}"
+ def jsonArray = "[" ~ repsep(value, ",") ~ "]"
+ def objEntry = stringVal ~ ":" ~ value ^^ { case x ~ y => (x,y) }
+ def value: Parser[Any] = (jsonObj | jsonArray | number | "true" ^^ true | "false" ^^ false | "null" ^^ null | stringVal)
+ def stringVal = accept("string", {case lexical.StringLit(n) => n})
+ def number = accept("number", {case lexical.NumericLit(n) => n.toDouble})
+}
+