文档章节

学习 JFlex 和 BYacc/J 简要笔记

刘军兴
 刘军兴
发布于 2014/01/01 18:16
字数 816
阅读 987
收藏 6

JFlex 是 The Fast Lexical Analyser Generator, 是 lex/flex 的 java 版本, JLex 的升级.

帮助手册地址: http://www.jflex.de/manual.html
中文的一些资料: http://wenku.baidu.com/view/542645350b4c2e3f57276338.html

lex/flex 的规则文件(spec)的三部分为: 1.声明/选项; 2.模式和动作; 3.代码被复制的.

而 JFlex 的规则文件的三部分为: 1. 类之前用户代码(同flex 3); 2. 声明/选项; 3. 模式和动作.
注意顺序有所不同.

第二部分中, 有一些重要的选项中摘录如下: (全部的参见文档)
%class Yylex -- 生成的 lex 类名字, 缺省为 Yylex; 另有 %implements %extends 等指令可
  指定类的基类和实现的接口等选项.
%{ ... 类中代码... %} -- 放到类中间的代码, 如类方法和成员变量等.
%function -- 指定调用 yylex() 的名字, 缺省为 yylex.
%int -- 指定 yylex() 返回类型为 int, 此情况下对 EOF 返回 -1.
%type -- 指定 yylex() 返回类型为 type, 缺省为 Yytoken 类型, EOF 返回 null.
%debug, %stsandalone -- 可用于生成 main() 方法, 用于调试.
%cup, %byacc -- 可用于和 cup, byacc 组合.

=================================================
例子: word count, 从 flex 中改编(需要调整一些代码和结构)
/* 第一部分: 声明 package, import 略. */
%%
/* 第二部分: 选项,类中代码 */
%class WordCountLexer
%function yylex
%int
%{
  /* 类中代码 */
  public int chars, words, lines;
  public static void main(...) 略
%}
%%
/* 第三部分: 规则和动作 */
[a-zA-Z]  { 匹配一个词 print(yytext()); ++words ... }
\n           { 匹配新行 print("NEWLINE"); ++... }
.             { 匹配其它任何字符. print("OTHER CHAR: " +yytext()); ++... }

需要注意的是, 这里 spec 文件结构要根据 jflex 要求更改. 最后生成一个 java 文件, 测试执行通过.
要点: %int 设置返回值类型; 抄一个 main() 函数.

 

====================================================
例子2: 计算器

/* first part */
package calc;

%%
/* second part */
%{
  public static void print(String s) { System.out.print(s); }
%}

%int
%debug

%%
/* third part */
"+"     { print("PLUS\n"); }
"-"     { print("MINUS\n"); }
"*"     { print("TIMES\n"); }
"/"     { print("DIVIDE\n"); }
[0-9]+  { print("NUMBER: " +yytext() +"\n"); }
\n      { print("NEWLINE"); }
[ \t]   { /*space ignored*/ }
.       { print("Mystery Char: " + yytext() + "\n"); }

与 wc 相似, 模式略微增多一些.

方法论:
  1. 在现有例子中 逐步地 修改,添加, 试验.
  2. 找别人工程中已经使用了的 lex/flex 文件改造.

花絮(八卦): lex 是 1975 年 Mike Lesk 和暑期实习生 Eric Schmidt 编写的, 后者现在是 
  Google 的 CEO.

=======================================================
一个 BYacc/J 的例子: calc.y

%token NUMBER  /* 定义 token */
%type <dval> exp  /* 可用于指定 yylval 值类型 */

%% /* begin second part: rules */
calclist: /*empty*/ | calclist exp EOL ...
exp: exp '+' factor | exp '-' factor ...

%% /* third part: user code */
public static void main() { ... }
public int yylex() { ... } /* 连接 jflex 在这里实现 */

生成文件使用: byaccj -J -Jpackage=calc -Jsemantic=double calc.y
  其中 byaccj 指向 yacc.exe (BYacc/J 的可执行文件)
  -Jpackage=calc 指定包名字.
  -Jsemantic=double 表示语义值类型取为 double (计算器例子中为省事)

在 Yylex 中, 需要引用 Parser 生成的 NUMBER 等 token 值. 为给 parser 中设置 yylval 值,
需要在 Yylex 中有 Parser 的引用, 在构造中给出是易用的方式.

 

======================================================

Ant 文件中自动完成 cup, jflex 编译的片段, 供参考用:

<property name="CUPJar" value="lib/java-cup-11a.jar" ></property>
	<property name="JFlexJar" value="lib/JFlex.jar"></property>
	<!-- 定义新任务 cup,jflex -->
	<taskdef name="cup" classname="java_cup.anttask.CUPTask"
	  classpath="${CUPJar}" />
	<taskdef name="jflex" classname="JFlex.anttask.JFlexTask"
		classpath="${JFlexJar}" />
	
	<!-- 使用 cup 编译 'ycalc.cup' -->
	<target name="ycalc_cup" >
		<cup srcfile="src/cup/ycalc.cup"
			destdir="src/cup"
			interface="true"
			package="cup"
			parser="Parser"
			symbols="sym"
		/>
	</target>
	<!-- 使用 jflex 编译 'lcalc.flex' -->
	<target name="lcalc_flex">
		<jflex file="src/cup/lcalc.flex" dot="true"
			/>
	</target>

 

© 著作权归作者所有

共有 人打赏支持
刘军兴
粉丝 56
博文 189
码字总数 231687
作品 0
昌平
私信 提问
加载中

评论(4)

刘军兴
刘军兴

引用来自“小战江湖”的评论

引用来自“刘军兴”的评论

引用来自“小战江湖”的评论

楼主,刚花了半天时间装Jflex,但它具体怎么用啊,这些代码都写在什么地方的,一点头绪都没有

jflex 是 c 系统中 lex/flex 的 java 版本, 想了解 jflex 怎么用, 可先学习 lex/flex 怎么用, 两者是非常相似的.
Flex 的链接: http://www.gnu.org/software/flex/

我们是在上一门课,导师让我用这个软件,也没教我们怎么用。。。请问输入命令是在cmd里面吗,为什么我不能输入任何东西?

jflex/lex 的内容一般写在一个文件如X中, 然后在命令行调用 jflex (java 的 jar), 以该文件X为输入, 输出为 java 语言的解析器. 我看你很多基础知识也需要了解, 不全是jflex的, 请自己多学习吧.
小战江湖

引用来自“刘军兴”的评论

引用来自“小战江湖”的评论

楼主,刚花了半天时间装Jflex,但它具体怎么用啊,这些代码都写在什么地方的,一点头绪都没有

jflex 是 c 系统中 lex/flex 的 java 版本, 想了解 jflex 怎么用, 可先学习 lex/flex 怎么用, 两者是非常相似的.
Flex 的链接: http://www.gnu.org/software/flex/

我们是在上一门课,导师让我用这个软件,也没教我们怎么用。。。请问输入命令是在cmd里面吗,为什么我不能输入任何东西?
刘军兴
刘军兴

引用来自“小战江湖”的评论

楼主,刚花了半天时间装Jflex,但它具体怎么用啊,这些代码都写在什么地方的,一点头绪都没有

jflex 是 c 系统中 lex/flex 的 java 版本, 想了解 jflex 怎么用, 可先学习 lex/flex 怎么用, 两者是非常相似的.
Flex 的链接: http://www.gnu.org/software/flex/
小战江湖
楼主,刚花了半天时间装Jflex,但它具体怎么用啊,这些代码都写在什么地方的,一点头绪都没有
JFlex 1.6.1 发布,语法分析生成器

JFlex 1.6.1 发布,次版本主要有以下更新: Fixed issue #130, "in caseless mode, chars in regexps not accepted caselessly": Caseless option works again as intended. Fixed issue #13......

oschina
2015/03/30
1K
2
FakeScript-Java —— 轻量级嵌入式脚本语言

FakeScript-Java是一款轻量级的嵌入式脚本语言,使用Java语言编写,语法吸取自lua、golang、erlang,基于jflex、cup生成语法树,编译成字节码解释执行。 C/C++版本fakescript...

oschina
2016/08/06
33
0
Jodd 3.4.10 发布,性能提升,MVC模块新增ActionFilter

Jodd = tools + ioc + mvc + db + aop + tx + html < 1.3M 这个版本的主要是带来了一些性能提升,另外MVC模块新增了一个特殊的拦截器-ActionFilter,详情关注官方文档。 [2013-12-19] Relea...

zqq90
2013/12/20
1K
8
JFinal 3.0 发布,重新定义模板引擎

本次回归码坛为小伙伴们带来的是重新定义过的 Template Engine 将极速开发继续贯彻到 View 层。 Java 模板引擎界已被 Freemarker、Velocity 统治多年,但其在这些年的发展可谓乏善可陈,究其...

JFinal
2017/01/22
17.4K
183
语法分析器生成工具--BYACC/J

BYACC/J 是扩展和兼容自 Berkeley v 1.8 YACC 的Java的语法分析器生成工具。Standard YACC takes a YACC source file, and generates one or more C files from it, which if compiled prop......

匿名
2009/02/22
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

ZooKeeper命令大全

创建节点 # 创建节点,-s表示顺序节点,-e表示临时节点,默认是持久节点create [-s] [-e] path data acl # 示例create /zk-book 123 查看节点 ls path [watch] # 示例ls /zk-book 获取...

爱宝贝丶
15分钟前
0
0
QLExpress基本语法

QLExpress基本语法 一、背景介绍 由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。 在阿里集团有...

xiaomin0322
15分钟前
0
0
Elasticsearch节点角色类型node.master和node.data说明s

一般地,ElasticSearch集群中每个节点都有成为主节点的资格,也都存储数据,还可以提供查询服务。这些功能是由两个属性控制的(node.master和node.data)。默认情况下这两个属性的值都是tru...

傲娇字符
31分钟前
5
0
rem的使用

(function (doc, win) { var docEl = doc.documentElement var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize' var recalc = function () { var cl......

Js_Mei
38分钟前
1
0
idea 删除代码的注释

搜索栏使用 正则表达式搜索 (/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/|[ \t]*//.*) 会搜索出来所有注释的代码 用空格replace替换掉就可以了。 或者搜索 (/\*([^*]|[\r\n]|(\*+([^*/]|[\r\...

时刻在奔跑
40分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部