Scala parser

Posted 凡普NBSP

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala parser相关的知识,希望对你有一定的参考价值。

请输入标题     bcdef

众所周知Scala是一个是一门多范式的编程语,除了能给强大函数支持以外,Scala还有提供强大的语法解析功能,它就是Scala parser combinators。如果你需要构建一个解析引擎,如:json解析,sql解析,甚至是构建一门编程语言,它都能帮助到你。

请输入标题     abcdefg

Scala parser combinators,它完全是从 Scala 的函数性方面构建的。解析器组合子使我们可以将语言的各种片段 “组合” 成部件,这些部件可以提供不需要代码生成,而且看上去像是一种语言规范的解决方案。而且是语言级别原生支持的。

Scala parser combinators 有两种解析器,一个是基于正则的解析器RegexParsers,另一个是基于词法的文法解析的解析器StandardTokenParsers。StandardTokenParsers十分强大,著名的Spark sql的sql解析器就是基于StandardTokenParsers开发出来的。

 

下面我们用StandardTokenParsers构建一个简单的计算器语言,用于获取并计算数学表达式。其实,这里的目标是要创建一个小型DSL,这个DSL能够允许用户来输入相对简单的代数表达式,然后这个代码来为它求值并产生结果。

该DSL的各种选项的树结构:

 1.加/减/乘/除运算符

 2.一元运算符

 3.数值


怎么来构建这个DSL?

我们不得不提到编译理论中最精华的部分,一个语言处理器(包括解释器和编译器)的基本运算至少由两个阶段组成:

  1.解析器,用于获取输入的文本并将其转换成 Abstract Syntax Tree(AST)。

  2.代码生成器(在编译器的情况下),用于获取 AST 并从中生成所需字节码;或是求值器(在解释器的情况下),用于获取 AST 并计算它在 AST 里面所发现的内容。

StandardTokenParsers就是解析DSL生成为AST,供下一个阶段来处理。Scala 有 case :一种提供了丰富数据、使用了非常薄的封装的类,它们所具有的一些特性使它们很适合构建 AST。

DSL的语法规则是基于BNF(巴科斯范式),BNF是描述编程语言的文法。自然语言存在不同程度的二义性。这种模糊、不确定的方式无法精确定义一门程序设计语言。必须设计一种准确无误地描述程序设计语言的语法结构,这种严谨、简洁、易读的形式规则描述的语言结构模型称为文法。最著名的文法描述形式是由Backus定义Algol60语言时提出的Backus-Naur范式(Backus-Naur Form, BNF)及其扩展形式EBNF。BNF能以一种简洁、灵活的方式描述语言的语法。

现在,几乎新编程语言都使用巴科斯范式来定义编程语言的语法规则。


用 BNF 形式来表达:

其中花括号({})表明内容可能重复(0 次或多次),竖线(|)表明也/或的关系。因此一个 factor 可能是一个 floatingPointNumber,或者一个左括号加上一个 expr 再加上一个右括号。


使用Scala基于词法单元的解析器解析上述EBNF文法

Scala基于词法单元的解析器是需要继承Standard Token Parsers这个类的,该类提供了很方便的解析函数,以及词法集合。

我们可以通过使用lexical.delimiters列表来存放在文法翻译器执行过程中遇到的分隔符,使用lexical.reserved列表来存放执行过程中的关键字。
比如,计算器中,看到"+","-","*","/","(",")"这些都是分隔符,其实我们也可以把它们当做是关键字,但是我习惯上将带有英文字母的单词作为关键字处理。因而,关键字集合便是存放在lexical.reserve这里,当然这个计算器的例子没有关键字,如果有"if","then","SUM","COUNT"这些,就要放到lexical.reserve中。


Scala parser还有一些简单的用法。

见下图:

Scala parser


具体的实现:

DSL 为1+1,ast的结构为Op(+,Num(1),Num(1))

DSL (1+1)+1ast的结构为Op(+,Op(+,Num(1),Num(1)),Num(1))

DSL (1+2)+(2*3+7)ast的结构为Op(+,Op(+,Num(1),Num(2)),Op(+,Op(*,Num(2),Num(3)),Num(7)))

ast是Arithmetic函数的参数,传递到Arithmetic函数中进行具体的计算。


这是相对比较简单实现,要真正掌握Scala parser combinators,还是系统学习一下Scala这门语言的,一旦掌握,你会发现构建一个DSL引擎是很有趣的事情。







以上是关于Scala parser的主要内容,如果未能解决你的问题,请参考以下文章

python OptionParser

python的命令行参数处理

c++ 函数调用前的类型声明?

从旧 API 转换 GetNextDocument() - 新 API YAMLcpp

iOS - OC - XML 解析 - NSXMLParser

python wav 转c 数组 bin功能实现