Scala學習整理[第三十一章 連線符解析]
阿新 • • 發佈:2019-02-05
第三十一章 連線符解析(Parser工具)
package SecondWithProgrammingInScala
import scala.util.parsing.combinator.{JavaTokenParsers, RegexParsers}
/**
* 連線符解析
*
* scala提供了一個連線符直譯器 ,可以藉助他實現一個編譯器 ,編譯解釋你自己的文法
* [上下文無關:對於文法G = (N, Σ, P, S) ,其中V->w ,V總是能夠被w替換而與V的所在上下文無關]
* [反例 ,漢語 : '本來'可以去成都的. 拿我的筆記'本來' ,"本來"出現的位置決定他的含義]
*/
class Arith extends JavaTokenParsers {
/**
* JavaTokenParsers 按照Java的格式識別一些引數值
*
* expr ::= term {'+' term | '-' term}
* term ::= factor {'*' factor | '/' factor}
* factor ::= floatingPointNumber | '(' expr ')'
*/
def expr: Parser[Any] = term ~ rep("+" ~ term | "-" ~ term)
def term: Parser[Any] = factor ~ rep("*" ~ factor | "/" ~ factor)
def factor: Parser[Any] = floatingPointNumber | "(" ~ expr ~ ")"
}
object ArithParser extends Arith with App {
println(parseAll(expr, "5+2*7/(3-1)"))
}
object MyParsers extends RegexParsers {
/**
* 按正則表示式匹配
*/
val ident: Parser[String] =
"""[a-zA-Z_]\w*""" .r
}
class JSON extends JavaTokenParsers {
/**
* 物件:用大括號包裹多條屬性
* obj ::= "{" [members] "}"
* 陣列:用中括號包裹多條值
* arr ::= "[" [values] "]"
* 屬性:由key:value構成
* member ::= stringLiteral ":" value
* 多條屬性:屬性間用逗號隔開
* members ::= member {"," member}
* 值:可以是任意物件/陣列/字元/數字/布林值
* value ::=
* 多條值:用逗號分隔
* values ::= value {"," value}
*/
//使用^^指定輸出解析器 ,會一直追溯到最底層
//例如從obj開始解析
// 解析是否是{member}
// 解析member結構
// 呼叫解析器生成(k,v)鍵值對
// 呼叫解析器將m鍵值對加入Map
// 返回形成的屬性Map
//解析obj完成
def obj: Parser[Map[String, Any]] = "{" ~ repsep(member, ",") ~ "}" ^^ { case "{" ~ members ~ "}" => Map() ++ members }
def arr: Parser[List[Any]] = "[" ~ repsep(value, ",") ~ "]" ^^ { case "[" ~ values ~ "]" => values }
def member: Parser[(String, Any)] = stringLiteral ~ ":" ~ value ^^ { case k ~ ":" ~ v => (k, v) }
def value: Parser[Any] =
obj |
arr |
stringLiteral |
floatingPointNumber ^^ (_.toDouble) |
"null" ^^ (x => null) |
"true" ^^ (x => true) |
"false" ^^ (x => false)
}
object JSONParser extends JSON with App {
val json = "{\"country\":{\"name\":\"China\",\"province\":[{\"name\":\"北京\",\"citys\":[\"東城區\"]},{\"name\":\"重慶\",\"citys\":[\"九龍坡\",\"萬州\",\"涪陵\"]},{\"name\":\"上海\",\"citys\":[\"浦東\"]},{\"name\":\"天津\",\"citys\":[\"海港\"]}]}}"
println(parseAll(obj, json))
}