使用Scala基于词法单元的解析器定制EBNF范式文法解析
前言近期在做Oracle迁移到Spark平台的项目上遇到了一些平台公式翻译为SparkSQL(on Hive)的需求,而Spark采用亲妈语言Scala进行开发。分析过大概需求过后,拟使用编译原理中的EBNF范式模式,进行基于词法的文法解析。于是拟采用传统的正则词法解析到EBNF文法解析的套路来实现,直到发现了StandardTokenParsers这个Scala基于词法单元的解析器类。
平台公式及翻译后的SparkSQL平台公式的样子如下所示:
这里面字段值”邢おb7肮α䵵薇”为这个的目的是为了测试各种字符集是否都能匹配满足。那么对应的SparkSQL应该是这个样子的,由于是使用的Hive on Spark,因而长得跟Oracle的SQL语句差不多:
总体而言比较简单,因为我只是想在这里做一个Demo。
平台公式的EBNF范式及词法解析设计
其中词法定义如下
使用Scala基于词法单元的解析器解析上述EBNF文法Scala基于词法单元的解析器是需要继承StandardTokenParsers这个类的,该类提供了很方便的解析函数,以及词法集合。我们可以通过使用lexical.delimiters列表来存放在文法翻译器执行过程中遇到的分隔符,使用lexical.reserved列表来存放执行过程中的关键字。比如,我们参照平台公式,看到”=”,”>=”,”<=”,”>”,”<”,”!=”,”&&”,”||”,”[“,”]”,”,”,”(“,”)”这些都是分隔符,其实我们也可以把”=”,”>=”,”<=”,”>”,”<”,”!=”,”&&”,”||”当做是关键字,但是我习惯上将带有英文字母的单词作为关键字处理。因而,这里的关键字集合便是”if”,”then”,”SUM”,”COUNT”这些。表现在代码中是酱紫的:
是不是so easy~。我们再来看一下如何使用基于词法单元的解析器解析前面我们设计的EBNF文法呢。我在这里先上代码: