Java应用中表达式解析器(Java Cup/JFlex)生成器的介绍及示例

  在基于Java的软件系统的构建过程中,开发人员经常会遇到词法解析、语法解析等问题,比如:在报表系统的中一般需要支持单元格计算公式(类似于Excel的公式),在某些系统的数据转换过程要实现自定义的转换规则脚本。面对这一类问题,我们最终需要的是一个针对问题域的词法及语法解析器,通常的实现方式不外乎有以下几种:

1. 自己实现全部过程

当所涉及语法非常简单(一般只有一两句原语)时,可以选择该方式。

优点:最直接,自然而然的选择;如果开发人员理论基础扎实的话不需要额外的学习负担。

缺点:要求有一定的理论基础;不利于扩充、或设计良好利于扩充但随着未来需求的改变及新语法的不断增加使扩充的开发成本不可控;测试成本增加;因未经过应用检验而存在风险;

2.  使用第三方的脚本引擎

当所涉及的语法及其复杂(需要支持比较复杂的脚本,甚至需要实现一种新的程序设计语言时,类似于Brio Query中提供的自定义脚本功能)时,可以选择该方式。目前,在互联网上有很多第三方脚本引擎(如:针对应用有:Netscape Script EngineJavaRhinoBeanShellIBM BSFTcl-Java等,针对Delphi应用有:Innerfuse Pascal Script 3,对微软体系有Microsoft Script Engine这些引擎的具体情况不在这里讨论)可以选择,只需要少量的编程工作这些脚本引擎大多都可以内嵌到宿主应用程序中,为宿主应用程序提供脚本支持功能。

优点:开发工作量少;部分引擎已经得到广泛应用的验证;具有复杂的脚本支持能力,可以提供类似于程序设计语言的处理能力。

缺点:脚本的语法由使用的引擎决定,往往比较复杂,对于处理简单问题的场合显得过于累赘;系统中需要引入第三方的类库/控件;要求最终用户学习引擎所规定的脚本语法;某些引擎在访问应用系统的运行时对象时能力有限。

3. 使用语法解析器生成器

 

使用过Unix的同志一般会知道在Unix中有Yacc/Lex,C语言的编译器生成器。在Java中,也有相应的工具。此方法使用JFlex/Java_Cup生成语法解析源码。本人使用这种方法成功的实现了类似Excel那样的公式,支持多种运算及函数,可以维护上下文,可以在表达式中引用系统的对象体系,可以执行动作,并且可以任意扩展而不需要修改解析源码。

关于JFlex与Java_Cup的文档你需要自己到下面的链接中仔细看看。其中关键的部分是需要定义你的语法及词法分析文件,类似于BNF表达式

主要步骤如下(为了方便,这里仅仅以四则运算为例,这个例子也是编译器构造工具的通用例子,满世界都采用它。):

当然首先你必须下在JFlex与Java_cup,并解压到特定目录,假定二者的目录分别是${JFlex_home}、${Java_Cup_home}。

3.1定义JFlex词法分析文件calc.flex

/*
  This example comes from a short article series in the Linux
  Gazette by Richard A. Sevenich and Christopher Lopes, titled
  "Compiler Construction Tools". The article series starts at

  http://www.linuxgazette.com/issue39/sevenich.html

  Small changes and updates to newest JFlex+Cup versions
  by Gerwin Klein
*/

/*
  Commented By: Christopher Lopes
  File Name: lcalc.flex
  To Create: > jflex lcalc.flex

  and then after the parser is created
  > javac Lexer.java
*/
  
/* --------------------------Usercode Section------------------------ */
  
import java_cup.runtime.*;
     
%%
  
/* -----------------Options and Declarations Section----------------- */
  
/*
   The name of the class JFlex will create will be Lexer.
   Will write the code to the file Lexer.java.
*/
%class Lexer

/*
  The current line number can be accessed with the variable yyline
  and the current column number with the variable yycolumn.
*/
%line
%column
   
/*
   Will switch to a CUP compatibility mode to interface with a CUP
   generated parser.
*/
%cup
  
/*
  Declarations
  
  Code between %{ and %}, both of which must be at the beginning of a
  line, will be copied letter to letter into the lexer class source.
  Here you declare member variables and functions that are used inside
  scanner actions. 
*/
%{  
    /* To create a new java_cup.runtime.Symbol with information about
       the current token, the token will have no value in this
       case. */
    private Symbol symbol(int type) {
        return new Symbol(type, yyline, yycolumn);
    }
   
    /* Also creates a new java_cup.runtime.Symbol with information

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LEX是一个生成词法分析器的工具,它可以根据用户提供的正则表达式和动作列表,生成一个C语言词法分析器。如果要在Java使用LEX生成的词法分析器,可以通过JNI调用C语言的词法分析器,或者使用JFlex这个专门为Java开发的词法分析器生成工具。 下面是使用JFlex生成Java词法分析器的步骤: 1. 安装JFlex 可以在JFlex官网上下载安装包,然后按照说明进行安装。 2. 编写词法规则文件 编写一个包含词法规则的文件,例如: ``` %{ import java.io.*; %} %class Lexer %unicode %public %type String %% "if" { return "IF"; } "else" { return "ELSE"; } "while" { return "WHILE"; } "(" { return "("; } ")" { return ")"; } "{" { return "{"; } "}" { return "}"; } ";" { return ";"; } [ \t\r\n] ; // ignore whitespaces . { throw new IOException("Invalid character: " + yytext()); } %% public static void main(String[] args) throws IOException { Lexer lexer = new Lexer(new FileReader(args[0])); String token; while ((token = lexer.yylex()) != null) { System.out.println(token); } } ``` 上面的规则定义了几个关键字和一些符号,同时忽略了空格和换行符。如果遇到未定义的字符,会抛出异常。 3. 生成词法分析器 使用JFlex生成词法分析器,命令如下: ``` jflex lexer.flex ``` 这会生成一个名为Lexer.java的文件,其包含了词法分析器的代码。 4. 编译运行 将生成的Java文件编译成class文件,然后运行即可: ``` javac Lexer.java java Lexer test.txt ``` 其test.txt是包含源代码的文件。运行结果会输出每个识别出的token。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值