欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2025/3/11 编程问答 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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))

}

}

总结

以上是生活随笔为你收集整理的ebnf范式_使用Scala基于词法单元的解析器定制EBNF范式文法解析的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。