本文来自: http://fair-jm.iteye.com 转截请注明出处
最近几天看了些文章(Learn by Example: Scala Parser Combinators,An Introduction To Scala Parser Combinators )学习了scala中的Parser的一些使用 这边以一个解析JSON的例子来记录一些笔记
首先是一些连接符(翻译自第一篇文章):
- | 选择连接符,当左边或右边的Parser成功时成功。
- ~ 序列连接符,当左右的Parser都成功时成功
- ~> 和~类似 不同的是左边的结果不会包含在最后的结果中
- <~ 和~类似 右边的结果不会包含在最后的结果中
- ^^ 转换连接符,当左边的操作成功时可以通过这个连接符操作结果
- rep repeat的意思 重复
如果说看起来比较难懂的话 在使用之后就会觉得容易理解得多
我没有学过编译原理(选修课没选惭愧...听到别人说一星期两节课要上两章就退缩了...) 对一些专用术语不是很理解 这边的Parser使用更加像是使用正则表达式(这主要也有继承了RegexParser的因素在)
首先看JSON的组成 从ECMA-404的文档中可以看到:
主要有 object array number string bool(true|false) null 这几个元素构成
为了编码方便 我让类继承自JavaTokenParsers:
class JsonParser extends JavaTokenParsers
对以上一些元素进行了定义(和ECMA-404的规范有些许差别 其实很多地方需要重写正则表达式的...)
//来自JavaTokenParser的floatingPointNumber parser def jNum: Parser[Double] = floatingPointNumber ^^ (_.toDouble) //stringLiteral 也来自JavaTokenParser 这边解析出来的结果会是例如"string"的形式 我们需要把双引号给去掉 def jStr: Parser[String] = stringLiteral ^^ (s => s.substring(1, s.length() - 1)) //正则表达式会被隐式转换为Parser def jBool: Parser[Boolean] = "(true|false)".r ^^ (_.toBoolean) def jNull: Parser[Null] = "null".r ^^ (t => null)
接下去还差对object和array的定义
在ECMA-404中他们的定义如下:
其中他们内的value是可以包括所有类型的(包括object和array)
可能有多个 这样需要用到rep连接符
具体的编码不是很困难 scala的模式匹配用起来比较舒服:
这边将JsonArray转化为List的形式 将JsonObject转换为Map的形式:
def term = jsonArray | jsonObject | jNum | jBool | jNull | jStr def jsonArray: Parser[List[Any]] = "[" ~> rep(term <~ ",?".r) <~ "]" ^^ (l => l) //String也会被隐式转化为Parser的形式 def jsonObject: Parser[Map[String, Any]] = "{" ~> rep((ident ~ ":" ~ jNum | ident ~ ":" ~ jBool | ident ~ ":" ~ jNull | ident ~ ":" ~ jsonObject | ident ~ ":" ~ jsonArray | ident ~ ":" ~ jStr) <~ ",?".r) <~ "}" ^^ { os => var map = Map[String, Any]() os.foreach(o => o match { case k ~ ":" ~ v => map = map ++ Map(k -> v) }) map }
最后来实验一下:
虽然number的形式有点问题(我用了JavaTokenParser中的一个Parser) 但总体结果还是正确的 使用起来也是相当简单
对于解析JSON来说 用scala提供的Parser并不困难 本文并未对其中的原理有任何描述 可以看上面参考的第二篇文章 里面有比较详尽的分析
希望对初学scala的Parser的人有所帮助^_^
相关推荐
argonaut:scala中的纯功能JSON解析器和库
ShEx紧凑语法解析器是使用以下基于该的Antlr语法(以前的版本使用Scala Parser Combinators)实现的 JSON编码和解码使用此处定义的Json结构,并使用Circe实现 相容性测试 我们还通过了ShEx测试套件。 更多信息 ...
快速解析器 FastParsers 是一个 Scala 解析器库,它使用宏将易于编写的解析器组合器转换为高效的递归下降回溯解析器。 生成的解析器比快 20 倍左右,即使它的接口保持不变。例子这是一个基本 JSON 解析器的示例 val ...
String path parser和Scala DSL句法字符串路径解析器: 以下是受支持的运算符的列表: 操作员描述例子/ 路径分割/foo : 数组切片(像python一样) /-1:-3 (后3个元素) , 名称或索引的集合/foo,bar或/foo/1,-1,2 *...
:此示例展示了如何使用Scallion构建基本的JSON解析器。 :此示例显示了如何与解析器一起免费获得漂亮的打印机。 :此示例说明如何使用operators组合器轻松处理具有各种关联性和优先级的运算符。 :此示例展示了...
总览Jawn包含四个部分: 快速,通用的JSON解析器( jawn-parser ) 一个小的,有点贫血的AST( jawn-ast ) 解析到第三方AST的支持程序包一些有用的实用程序( jawn-util实用程序) 目前,Jawn在速度最快的Java JSON...
它基本上与 ig-json-parser 做同样的事情。 但... 区别在于: 不要使用注释来生成解析器。 但使用 Scala 原始值,如: lazy val Tag = ObjectType ( " Tag " , Seq ( Field ( " value " , " value " , StringType )...
埃斯卡利马Escalima是的Scala包装器,用于将JavaScript解析为ast。 它可以在JVM以及ScalaJS中使用。 esprima返回的ast既可以作为json字符串接收,也可以作为整洁的scala类包装结构接收。文档化。例子 val parser = ...
1.2.3:scala代码优化 7 二:sparkSQL运行架构 8 2.1:Tree和Rule 9 2.1.1:Tree 10 2.1.2:Rule 10 2.2:sqlContext的运行过程 12 2.3:hiveContext的运行过程 14 2.4:catalyst优化器 16 三:sparkSQL组件之解析 ...
AST浏览器 将代码粘贴或拖放到编辑器中,并在上检查生成的AST。... 复制AST或将包含AST的文件到窗口中将解析AST并使用更新代码。 否则,文本编辑器的内容将替换为文件的内容(即,您可以拖放JS文件)。 在多个
一组基于的流数据解析器。 有关更多详细信息和文档,请访问 发展历程 该项目使用构建。 编译所有内容: sbt compile 编译并运行所有测试: sbt test 运行基准测试(您可以在最后提供参数): sbt benchmarks/...