ebnf范式_使用Scala基于词法单元的解析器定制EBNF范式文法解析

前言

近期在做Oracle迁移到Spark平台的项目上遇到了一些平台公式翻译为SparkSQL(on Hive)的需求,而Spark采用亲妈语言Scala进行开发。下面是个意外,被论文查重了,移步至我的Leanote博客查看点我,先乱码一段时间[分后,拟使中的EB式,进行基于@#@#@法解析。

平台公式及翻译后的SparkSQL

平台公式的样子如下所示:

if (XX1_m001[D003]="邢おb7肮α䵵薇" || XX1_m001[H003]

这里面字段值"邢おb7肮α䵵薇"为这个的目的是为了测试各种字符集是否都能匹配满足。

那么对应的SparkSQL应该是这个样子的,由于是使用的Hive on Spark,因而长得跟Oracle的SQL语句差不多:

SELECT COUNT(H022) FROM XX1_m001 WHERE (XX1_m001.D003='邢おb7肮α䵵薇' OR XX1_m001.H003

总体而言比较简单,因为我只是想在这里做一个Demo。

平台公式的EBNF范式及词法解析设计

expr-condition ::= tableName "[" valueName "]" comparator Condition

expr-front ::= expr-condition (("&&"|"||")expr-front)*

expr-back ::= tableName "[" valueName "," operator "]"

expr ::= "if" expr-front "then" expr-back

其中词法定义如下

operator => [SUM,COUNT]

tableName,valueName =>ident #ident为关键字

comparator => ["=",">=","<=",">","

Condition => stringLit #stringLit为字符串常量

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

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

我们可以通过使用lexical.delimiters列表来存放在文法翻译器执行过程中遇到的分隔符,使用lexical.reserved列表来存放执行过程中的关键字。

比如,我们参照平台公式,看到"=",">=","<=",">","=","<=",">","

表现在代码中是酱紫的:

lexical.delimiters += ("=",">=","<=",">","

lexical.reserved += ("if","then","SUM","COUNT")

是不是so easy~。

我们再来看一下如何使用基于词法单元的解析器解析前面我们设计的EBNF文法呢。我在这里先上代码:

class ExprParsre extends StandardTokenParsers{

lexical.delimiters += ("=",">=","<=",">","

lexical.reserved += ("if","then","SUM","COUNT")

def expr: Parser[String] = "if" ~ expr_front ~ "then" ~ expr_back ^^{

case "if" ~ exp1 ~ "then" ~ exp2 => exp2 + " WHERE " +exp1

}

def expr_priority: Parser[String] = opt("(") ~ expr_condition ~ opt(")") ^^{

case Some("(") ~ conditions ~ Some(")") => "(" + conditions +")"

case Some("(") ~ conditions ~ None => "(" + conditions

case None ~ conditions ~ Some(")") => conditions +")"

case None ~ conditions ~ None => conditions

}

def expr_condition: Parser[String] = ident ~ "[" ~ ident ~ "]" ~ ("="|">="|"<="|">"|"

case ident1~"["~ident2~"]"~"="~stringList => ident1 + "." + ident2 +"='" + stringList +"'"

case ident1~"["~ident2~"]"~">="~stringList => ident1 + "." + ident2 +">='" + stringList +"'"

case ident1~"["~ident2~"]"~"<="~stringList => ident1 + "." + ident2 +"<='" + stringList +"'"

case ident1~"["~ident2~"]"~">"~stringList => ident1 + "." + ident2 +">'" + stringList +"'"

case ident1~"["~ident2~"]"~" ident1 + "." + ident2 +"

case ident1~"["~ident2~"]"~"!="~stringList => ident1 + "." + ident2 +"!='" + stringList +"'"

}

def comparator: Parser[String] = ("&&"|"||") ^^{

case "&&" => " AND "

case "||" => " OR "

}

def expr_front: Parser[String] = expr_priority ~ rep(comparator ~ expr_priority) ^^{

case exp1 ~ exp2 => exp1 + exp2.map(x =>{x._1 + " " + x._2}).mkString(" ")

}

def expr_back: Parser[String] = ident ~ "[" ~ ident ~ "," ~ ("SUM"|"COUNT") ~ "]" ^^ {

case ident1~"["~ident2~","~"COUNT"~"]" => "SELECT COUNT("+ ident2.toString() +") FROM " + ident1.toString()

case ident1~"["~ident2~","~"SUM"~"]" => "SELECT SUM("+ ident2.toString() +") FROM " + ident1.toString()

}

def parserAll[T]( p : Parser[T], input :String) = {

phrase(p)( new lexical.Scanner(input))

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

钻石指标和完美的计算

钻石的高度计算公式为&#xff1a;钻石的高度直径的三次方&#xff08;单位毫米&#xff09;0.00366(允许有0.03克拉的误差)例如&#xff0c;0.5克拉的钻石直径是5.01毫米&#xff0c;则它的高为&#xff1a;5.01*5.01*5.01*0.003660.46说明0.5克拉的钻石直径只有0.46克拉钻石的…

linux开机自动ZFS,linux – 为什么重新启动导致我的ZFS镜像的一面成为UNAVAIL?

我最近刚刚将批量数据存储池(ZFS OnLinux 0.6.2,Debian Wheezy)从单设备vdev配置迁移到双向镜像vdev配置.之前的池配置是&#xff1a;NAME STATE READ WRITE CKSUMakita ONLINE 0 0 0ST4000NM0033-Z1Z1A0LQ ONLINE 0 0 0在重新启动完成后一切都很好(我在重新启动完成后启动了一…

华为交换机默认vlan都是通的吗_【思唯网络学院】华为交换机常用的三种vlan划分方法...

端口类型在学习划分vlan前&#xff0c;必须要了解华为交换机的端口类型&#xff0c;以及他们的使用方法&#xff0c;因为端口的类型在实际配置中是必须会用到的&#xff0c;因为下面的vlan划分会用到。1、Access类型端口执行命令port default vlan vlan-id&#xff0c;将端口加…

Spark应用日志级别设置

Spark-core包设置默认的日志级别为info&#xff0c;所以我们才看到一大堆日志信息。 开发的时候&#xff0c;把print的日志掩盖了。 方法一&#xff1a; 代码中设置日志级别 JavaSparkContext contextnew JavaSparkContext(conf); context.setLogLevel("warn"); 方…

linux 恢复操作系统,如何恢复Linux操作系统的GRUB引导程?

先使用一张修复盘进入grub&#xff0c;或者利用其他linux恢复盘等等进入linux系统&#xff0c;然后进入grub控制台。总之就是想尽办法进入一个控制台就是了。然后准备引导进入硬盘上的Linux系统。如下&#xff1a;  grub> root (hd0,10)  grub> kernel /boot/vmlinuz…

Centos 7初始化脚本

今天跟大家分享一个我自己写的Linux初始化脚本&#xff0c;自认为写的不是很好。希望看到这篇文章的你&#xff0c;能暂时停留下你的脚步&#xff0c;给些修改意见&#xff0c;或者有什么需要补充的地方都可以提出来&#xff0c;大家共同进步&#xff0c;谢谢&#xff01;此脚本…

Hive-sql与SQL的区别

总体一致&#xff1a; Hive-sql与SQL基本上一样&#xff0c;因为当初的设计目的&#xff0c;就是让会SQL不会编程MapReduce的也能使用Hadoop进行处理数据。 因此&#xff0c;大胆使用SQL的&#xff0c;如果遇到不对的&#xff0c;再查。 区别&#xff1a; Hive没有delete和u…

python闰年多一天_记一个 python datetime 闰年问题

python中datetime是比较常用的&#xff0c;平时用起来也没什么问题&#xff0c;但是今天2020年2月29日服务器却开始报错了&#xff0c;这里有个平时难以注意的坑服务器上跑的是新浪网的爬虫&#xff0c;抓取的页面信息中带有日期 XX月XX日&#xff0c;需要strfptime转化一下&am…

linux find 按类型查找,Linux find查找find命令详解

玩蛇网推荐图文教程&#xff1a;python 列表Linux命令有很多&#xff0c;今天要介绍的是常用的基础命令中的find命令。find是Linux系统管理员所喜爱用的必备工具命令之一&#xff0c;它的作用是可以很轻松地找到你想要的文件&#xff0c;一个命令就可以在众多文件中找到你的目标…

window安装gcc编译器

在使用 GraphLab Create 时&#xff0c;导入包失败&#xff0c;提示libs没有的导入&#xff0c;而这些libs的编译是需要gcc。 1、访问&#xff1a;http://www.mingw.org/ 下载。 2、双击安装 3、安装好后会弹出下面的组件安装界面 3、找到mingw32-gcc-g&#xff08;注意cl…

视频AI,助力体育赛事转播走进智能时代

摘要&#xff1a;2018俄罗斯世界杯经过近20天的激战&#xff0c;已经进入到最关键的阶段。本次赛事除了精彩纷呈的比赛之外&#xff0c;还加入很多高科技的元素&#xff0c;例如门线、VAR技术等等。让本届世界杯成为科技含量最高的一届世界杯。2018俄罗斯世界杯经过近20天的激战…

python求同构数_用c语言求1到1000的同构数_后端开发

python与平台有关吗_后端开发Python与平台无关&#xff0c;因为Python是跨平台的语言&#xff0c;Python作为脚本语言&#xff0c;是解释执行的&#xff0c;所以能跨平台&#xff0c;前提是必须要有一个对应的解释器。具体请看实例&#xff1a;python中count函数的用法详解_后端…

element表格实现树形全选_很实用!word中全选的快捷键介绍及使用方法

全选快捷键可以提高我们在操作word时工作效率&#xff0c;在操作Word2003中怎么对文档中的文字进行全选呢?下面为大家提供几种全选的方法&#xff0c;绝对好用。Word怎样全选?方法一、使用Word全选快捷键“CtrlA”进行全选(也适用于电子表格);方法二、展开菜单栏中的“编辑”…

am3352 linux 内核 编译,am335x uboot, kernel 编译

一、设置环境变量// 写在家目录下面的 .bashrc 里面export KERNEL_PATH~/aplex/kernel3.2.0 // kernel 路径export UBOOT_PATH~/aplex/uboot2011.09 // u-boot 路劲export ROOTFS_PATH~/aplex/filesystemexport TOOLFS_PATH~/aplex/toolsexport ARCHarm // 设置平台类型export …

Docker的应用场景

原文链接&#xff1a;http://blog.csdn.net/dev_csdn/article/details/78424803 ------------------------------------------------------------------- Docker是开发人员和系统管理员构建&#xff0c;发布和运行分布式应用程序的开放平台&#xff0c;可以在笔记本电脑、数据…

cad多段线画圆弧方向_【学员分享】CAD多段线用法

原标题&#xff1a;【学员分享】CAD多段线用法1、执行方法&#xff1a;(1)菜单栏&#xff1a;绘图→多段线(2)绘图功能区&#xff1a;绘图→多段线按钮(3)快捷键&#xff1a;PL2、使用方法(1)多段线与直线的区别&#xff1a;直线每一段都是分开的&#xff0c;图画完后不是一个整…

linux 视频编辑 ffmpeg,ffmpeg转码视频真的好用!(ffmpeg的简单使用方法)

说明转码和编辑视频今天用Android Studio(后面简称AS)里的模拟器给系统录屏&#xff0c;用来展示OpenGL可视化的东西&#xff0c;打算上传B站&#xff0c;后来发现AS只能保存webm格式和GIF格式的视频&#xff0c;并且文件体积巨大&#xff0c;视频图像也是顺时针旋转的。没办法…

requests库入门09-OAUTH认证

实际登陆中&#xff0c;认证用到的token会变的&#xff0c;不过可以在GIthub设置一个私人token。 如图&#xff0c;登录GIthub&#xff0c;然后用户下面选择Settings/Developer settings/Personal access tokens,点击Generate new token&#xff0c;然后随便输个描述&#xff0…

mysql期末考试试卷_mysql试题

net start mysqlfound_rows函数 返回select的总行数哪种操作能够实现实体完整性 设置外键数据模型三要素&#xff1a;数据结构、数据操作、完整性约束&#xff0c;哪项不属于数据模型 网状模型(层次、网状、关系、面向对象模型)触发器主要用于监视某个表的insert、update以及de…

深入了解HashMap

什么是hash&#xff1f;哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值&#xff0c;这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母&#xff0c;随后的哈希都将产生不同的值。要找…