antlr 正则表达式解析表达式 包含哪些基础表达式

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)antlr介绍,第一章_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
antlr介绍,第一章
&&antlr入门介绍
阅读已结束,下载本文需要
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩10页未读,
定制HR最喜欢的简历
你可能喜欢java中输入输入“算术表达式”的文本,如何计算表达式的值?例如输入1+2/2+2*(3+1);如何直接给出10.
在动态语言中如python,groovy中,这些根本不是问题,到java语言中,就变成了一件挺难的事。我想到几个解决方案:
1)java中调用动态语言groovy,scala
利用动态语言能支持的这个特性,java集成调用下,当然能完成这个功能
2)手动自定义语言解析器,解析表达式文本,然后执行表达式
具体的做法可参考这篇文章,用解释器模式来做
3)用antlr自定义DSL
这个比较强大,antlr用来作这个有点大材小用,antlr是什么可参见:
参考资料:
出品的 《antlr教材.pdf》
自定义文法:
grammar D;
options{output=AST;}
program:statement+;
statement:expression';'!;
expression:multExpr(('+'^|'-' ^)multExpr)*;
multExpr:atom(('*'^|'/'^)atom)*;
atom:INT| '('!expression')'!;
INT:'0'..'9' +;
WS:(' ' |'\t' |'\n' |'\r' )+{skip();};
然后利用antlrWorks工具,自动生成解析器:DLexer.java,,DParser.java
因为antlr只完成了词法、语法的识别,所以需要自己编写语义:
package org.
import org.antlr.runtime.ANTLRInputS
import org.antlr.runtime.CommonTokenS
import org.antlr.runtime.tree.BaseT
import org.antlr.runtime.tree.T
//1+1*3+(1+1)*3;
public class App {
public static void main(String[] args) throws Exception {
ANTLRInputStream input = new ANTLRInputStream(System.in);
DLexer lexer = new DLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DParser parser = new DParser(tokens);
DParser.program_return r = parser.program();
System.out.println(((BaseTree) r.getTree()).toStringTree());
BaseTree tree = (BaseTree) r.getTree();
System.out.println(calcNode(tree));
public static int calcNode(Tree tree) {
if (tree.getChildCount() == 0) {
return Integer.parseInt(tree.getText());
if (tree.getChildCount() != 2) {
throw new RuntimeException("node " + tree.getText() + "illegal expression"
+ "tree.getChildCount() = " + tree.getChildCount());
int leftChildValue = calcNode(tree.getChild(0));
int rightChildVale = calcNode(tree.getChild(1));
String sign = tree.getText().trim();
return doCalc(sign, leftChildValue, rightChildVale);
private static int doCalc(String sign, int leftChildValue, int rightChildVale) {
if (sign.equals("+")) {
return leftChildValue + rightChildV
} else if (sign.equals("-")) {
return leftChildValue - rightChildV
} else if (sign.equals("*")) {
return leftChildValue * rightChildV
} else if (sign.equals("/")) {
return leftChildValue / rightChildV
throw new RuntimeException("unknown sign " + sign);
输入:1+10/5+12+(2+3)*1+1;
(+ (+ (+ (+ 1 (/ 10 5)) 12) (* (+ 2 3) 1)) 1)
浏览: 271631 次
来自: 杭州
xiaoxuan1130 写道
class Solution {public:
学习了,非常好。http://surenpi.com
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'scala(7)
Spark SQL(6)
Spark SQL表达式解析器-Scala Parser与Antlr4
版权声明:本文为博主原创文章,未经博主允许不得转载。
手动码字不易,请大家尊重劳动成果,谢谢
Spark SQL之所以能支持如此强大的表达式系统,是因为其包含了一套字符串解析并生成表达式树的模块。
Scala Parser
在Spark 2.0之前,Spark SQL使用Scala Parser功能去解析SQL表达式,其解析类为org.apache.spark.sql.catalyst.SqlParser。
对于没用使用过Scala Parser的人来讲,这个类基本上就可以称为天书了。其中用到的几个基本符号:
~ 连接符,并将左右侧匹配结果保留
~& 连接符,仅保留右侧匹配结果,左侧将丢弃
&~ 连接符,仅保留左侧匹配结果,右侧将丢弃。该连接符优先级低于 ~ 和 ~&
^^ 其左侧为词法表达式,右侧为一个函数
例如:p1 ~ p2 ^^ { case a ~ b =& a + b }
这个表达式可以把p1和p2匹配出的结果分别赋值给a和b,
注意:此处的前后两个 ~ 不是同一个函数; ^^ 左右匹配结果的数量必须一致
? 和正则表达式中一样,表示可有可无
和正则表达式中一样,表示可以有零个或多个
*(sep: =& Parser[(U, U) =& U])
表示this (sep this)*
例如:andExpression * (OR ^^^ { (e1: Expression, e2: Expression) =& Or(e1, e2) })
上面表达式的意思就是:
andExpression (OR andExpression)*
将*展开就是:
andExpression OR andExpression OR andExpression ...
一个andExpression后面跟上一堆可重复的 OR andExpression
和正则表达式中一样,表示可以至少有一个
^^^ 如果其左侧匹配成功,则丢弃左边,返回右侧运算结果
Scala Parser原理简介
在Spark 2.0之后,Spark SQL使用Antlr 4来解析SQL表达式,其解析描述文件路径为spark源码根路径\sql\catalyst\src\main\antlr4\org\apache\spark\sql\catalyst\parser\SqlBase.g4。
但是只有描述文件是不能解析表达式的,需要先将其变换成代码。
在spark-catalyst的pom文件里,我们可以看到它引入了antlr4的maven插件:
&org.antlr&
&antlr4-maven-plugin&
&../catalyst/src/main/antlr4&
其中&goal&antlr4&/goal&会在&phase&generate-sources&/phase&生命周期内执行描述文件的解析,并且在target\generated-sources\antlr4下生成表达式解析的java文件:
Antlr 4是一个非常优秀的词法语法分析工具,借助它你可以实现很多自定义表达式解析,甚至可以做一个简单的编译器。Antlr 4使用了Visitor模式和Listener模式来帮助使用者对解析好的表达式进行处理。
Visitor模式即Antlr 4已经将表达式按照你给的规则解析成为一个语法树。然后把语法树的根节点交给你,你去决定该往哪走。
Listener模式即Antlr 4已经将表达式按照你给的规则解析成为一个语法树。然后自己执行深度优先遍历,然后在遍历到每个节点的时候给你发送事件。
我之前学习Antlr 4的时候写过一个表达式解析器,可以通过来查看。这个程序可以解析一个自定义模式的表达式,然后生成Spark SQL可用的表达式。具体实例可以参考代码中的测试用例部分。
如果你使用Spark 2.0之后的版本,你可以下载Antlr 4的IDEA插件来测试SqlBase.g4文件,其中singleStatement为整个SQL语句的解析器,singleExpression为单个表达式的解析器,我在平常工作中测试singleExpression居多,在写代码前先用插件测试下这个表达式的合法性,然后再写到代码里运行,这样可以大大增加代码的运行成功率。
以下是我使用singleExpression对表达式进行解析的结果,右侧为Antlr 4插件生成的表达式树:Antlr4 入门 --程序员不只是增删改查那么简单!Antlr4 入门 --程序员不只是增删改查那么简单!科学与技术百家号Antlr简介ANTLR(Another Tool for Language Recognition),一个通过语法描述来自动构造自定义语言的识别器(recognizer),编译器(parser)和解释器(translator)的框架。它被广泛的用于构建语言,工具,和框架。ANTLR 现在已经支 持了多种当前流行的开发语言,包括 Java、C#、C、C++、Objective-C、Python 和 Ruby.1 等。现实的项目中,我们可以使用 ANTLR ,来解析一些正则表达式无法完成的复杂语法解析,你也可以用它生成自己的SQL语法,甚至是一门新的编程语言。基本概念为了实现一门编程语言,我们需要构建一个程序,读取输入的语句,对其中的词组和输入符号进行正确的处理。一般来说,如果一个程序能够分析识别语句我们称之为语法分析器(parser)。例如一段代码"sp = 100;",我们的语法分析器能将其识别为一个赋值语句,sp是被赋值的目标,100是要被赋予的值。语法分析的过程其实可以分解为两个相似但独立的任务或者说阶段。第一个阶段是词法分析(lexical analysis),将字符聚集为单词或者符号(词法符号,token)的过程。这和我们的大脑阅读英文文本的过程相类似,我们并不是一个字符一个字符地阅读一个句子,而是将句子看作一列单词,先通过潜意识将字符聚集为单词,然后获取每个单词的意义。第二个阶段是实际的语法分析过程,在这个过程中,输入的词法符号被"消费"以识别语句结构,在上例中即为赋值语句。默认情况下,ANTLR生成的语法分析器会建造一种名为语法分析树(parse tree)。下图展示了流动过程。Antlr安装接下来介绍下antlr4+eclipse环境搭建。你可以在eclipse market下载插件。Antlr入门用 ANTLR 开发一个语法分析器大致分三步,第一步:写出要分析内容的 文法。第二步:用 ANTLR 生成相对该文法的语法分析器的代码。第三步:编译运行语法分 析器。 接下来我们举一个简单的例子:1. 新建项目:新建完毕的项目目录如下:2. 在Hello.g4文件中填写如下内容:我们逐条分析一下这个文件里面代码的含义:grammar H // 声明一个叫做Hello的语法,下面所有的语法和词法规则都属于Hello。r : 'hello' ID ; // 说明 r 是一个 'hello'开头,后接 ID 的字符串。ID : [a-z]+ ; // ID 为任意小写字母的组合。WS : [\\n]+ -& // 告诉系统跳过 \t' \n' \n'。3. 右键运行,之后可以在我们的项目底下发现如下代码:4. 使用语法解析器当用户输入"hello jack"时,我们如何利用上述的代码来分析出来是"jack"。这边新建一个java工程,我们运行下anltr生成的代码,在这之前你需要依赖依稀antlr的包:org.antlrantlr44.5.2定义一个visitor(后续会讲,此处我们用来获取一些信息):定义Main函数://读取输入文本ANTLRInputStream inputStream = new ANTLRInputStream("hello jack");//词法分析HelloLexer lexer = new HelloLexer(inputStream);//词法符号CommonTokenStream tokenStream = new CommonTokenStream(lexer);//语法解析HelloParser parser = new HelloParser(tokenStream);// 语法解析树ParseTree parseTree = parser.r();//以文本的形式答应树形结构System.out.println("tree1:"+parseTree.toStringTree(parser));//访问visitorMyHelloVisitor vistor = new MyHelloVisitor();vistor.visit(parseTree);输出:后续内容播报后续我们将介绍更多关于Antlr的支持。Antlr元语言Antlr遍历机制Antlr错误机制Antlr代码嵌入、属性和动作Antlr 竞品分析本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。科学与技术百家号最近更新:简介:科技重点,互联网,风险投资作者最新文章相关文章

我要回帖

更多关于 正则表达式 不包含 的文章

 

随机推荐