`

利用JavaCC实现生成器失败,暂告一个段落

阅读更多

      公司里面有自定义的一个协议,服务器是C++写的而我的工作则是通过Java和这个服务器通讯,协议主体的解析是参考C++的源文件中定义的结构体来解析,如下所示:

typedef struct ExSecFreeTxtGroup
{
 	unsigned char cHeader;
 	unsigned char cGroupLen;
 	unsigned long sStockCd;
 	char cFreeTxt[2][20];
} ExSecFreeTxtGroup;

 

由于这样的结构体比较多,虽然公司以前也有类似的解析类可以重用,但是有也有弊端,对于现在的准备的新项目扩展不便。所以决定重写一遍这些类,但是由于太多,而且主体部分的解析是重复工作,也就意味着可以自动生成。所以有了借助于javaCC来解析生成Java文件的想法,于是乎看了两天。虽然最终没弄成功,但至少了解了javaCC的一些用法。

 

下面是我编写的.jj文件,简单实现了对结构体的语法分析和提出我想要的关键字并且排除了注释和"#"开始的宏定义.

options {
  LOOKAHEAD = 1;
  CHOICE_AMBIGUITY_CHECK = 2;
  OTHER_AMBIGUITY_CHECK = 1;
  STATIC = false;
  DEBUG_PARSER = true;
  DEBUG_LOOKAHEAD = true;
  DEBUG_TOKEN_MANAGER = false;
  ERROR_REPORTING = true;
  JAVA_UNICODE_ESCAPE = false;
  UNICODE_INPUT = false;
  IGNORE_CASE = false;
  USER_TOKEN_MANAGER = false;
  USER_CHAR_STREAM = false;
  BUILD_PARSER = true;
  BUILD_TOKEN_MANAGER = true; 
  SANITY_CHECK = true;
  FORCE_LA_CHECK = false;
}





PARSER_BEGIN( Std3Parser )
package mislay.util;

import java.util.*;
import mislay.util.std3parser.*;
import mislay.util.std3parser.Std3StructMetaInfo.RowType;
public class Std3Parser {
	private Map<String,Std3StructMetaInfo> structs = new HashMap<String,Std3StructMetaInfo>();
	private Std3StructMetaInfo getStruct(String typeName) {
		Std3StructMetaInfo metaInfo = structs.get(typeName);
		if(metaInfo == null) {
			structs.put(typeName,metaInfo = new Std3StructMetaInfo());
			metaInfo.setTypeName(typeName);
		}
		return metaInfo;
	}
	
	public Map getStructs() {
		return structs;
	}
}
PARSER_END( Std3Parser )
void start() : {}             
{ 
	struct()
}

void struct() : 
{
} 
{ 
	("typedef""struct"structType())*<EOF>
}
  
void structType() :
{
	Token typeName = null;
	Token typeAlias = null;
}
{
	typeName = <IDENTIFIER>
	<LBRACE>(row(typeName.image))+<RBRACE>
	typeAlias = <IDENTIFIER>
	<SEMICOLON>
	{
		Std3StructMetaInfo metaInfo = getStruct(typeName.image);
		metaInfo.setTypeAlias(typeAlias.image);
	}
}

void row(String typeName):
{
	Token unsigneds = null;
	Token type = null;
	Token name = null;
}
{
	[unsigneds = "unsigned"]
	(type = "char" | type = "int" |type = "long" | type = "double" | type = <IDENTIFIER>)
	name = <IDENTIFIER>
	(<ROWNAME>)*
	<SEMICOLON>
	{
		Std3StructMetaInfo metaInfo = getStruct(typeName);
		RowType rowType = null;
		try {
			rowType = RowType.valueOf(type.image.toUpperCase());
		} catch(Exception e) {
			rowType = RowType.REF;
		}
		metaInfo.addRow(unsigneds == null,rowType,name.image);
	}
}
SKIP 	: 
{
	" "
|	"\t"
|	"\n"
|	"\r"
|	<"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")>
|	<"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
|	<"#"  (~["\n","\r"])* ("\n" | "\r" | "\r\n" )*>
}
 
TOKEN : 
{
  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
|
  < #LETTER: ["$","A"-"Z","_","a"-"z"] >
|
  < #DIGIT: ["0"-"9"] >

}

TOKEN : 
{
  < LPAREN: "(" >
| < RPAREN: ")" >
| < LBRACE: "{" >
| < RBRACE: "}" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < SEMICOLON: ";" >
| < COMMA: "," >
| < DOT: "." >
| < ROWNAME: "["(["0"-"9"])+"]" >
}

 

 

如果认真看会发现.jj文件的结构很简单,除了BNF就是剩下的就是java的实现,但是最终没有完成还是因为BNF编写太复杂了.有些读取是有规则的而不是按照顺序读取到底,比如有某几个字段循环读取几次,或者按照某个字段的长度来循环读取,又或者说循环到整个结构的长度结束等等,还有些则是类型的问题。比如char[]一般读取是字符串,但是有的则不是。所以我为了这些条件需要在这个结构的基础上添加一些特殊的注解来表示某一规则比如@Loop(type=serial,length=32),当然还需要在.jj文件中添加BNF表达式了,而且条件比较多对于写这些BNF对于才接触两天的我是个挑战.嘿嘿,索性暂时放下吧,时间关系暂时留个标记在这,以后有时间在拾起吧。

 

后话:如果只考虑特定情况利用JavaCC还是很简单的,如果把所有情况都考虑进去编写.jj文件真的是个挑战。不过如果不考虑比较全面的情况就不会利用JavaCC了.利用正则表达式或许还方便快捷些.

 

如果对编译原理有了解会更加容易。还有就是这里指的BNF并不是标准的BNF。

分享到:
评论

相关推荐

    javacc 词法分析器

    总之,JavaCC是一个强大的工具,用于生成词法分析器和解析器,它支持面向对象的编程,并允许开发者专注于语言文法的定义,而不是底层解析算法的实现。在给定的项目中,`testcc`目录的代码可能包含了一些使用JavaCC...

    JavaCC实现MiniC语言的编译

    在本项目中,"JavaCC实现MiniC语言的编译"是一个实践性的任务,目的是利用JavaCC来构建一个小型的C语言编译器——MiniC。这个编译器能够解析、理解和转换C语言的基本元素,如变量声明、表达式、控制结构等。 1. **...

    使用Javacc做的解释器(超详细)

    在这个“使用Javacc做的解释器”项目中,我们将深入探讨如何利用JavaCC进行词法分析和语法分析,构建一个自定义语言的解释器。 词法分析是编译器或解释器的第一步,它将源代码中的字符流转换为有意义的词法单元...

    编译原理中用javacc实现MiniC的词法分析、语法分析、语义分析

    在语法分析部分利用Javacc实现LL(1)文法,判断源语言是否符合MiniC的语法,如果不符合,给出语法错误信息;语义分析部分是在语法分析的基础上根据属性文法制导翻译,进行语义分析,输出四元式。

    JavaCC词法分析器 单词定义超详细 基于Eclipse插件 能从文件读取源代码 输出种别编码和对应单词

    一旦词法分析器定义完成,JavaCC会自动生成相应的Java源代码,包含一个解析器类和相关的辅助类。这些生成的代码可以与你的应用程序集成,处理用户输入或读取文件内容,执行词法分析,并返回结果。 总结来说,JavaCC...

    Test.rar 使用Javacc编写的简易计算器

    例如,可能会有一个`Calculator`类,它使用JavaCC生成的解析器来解析用户输入,然后执行计算。 在实际开发中,JavaCC通常用于构建自定义的编程语言或解析特定格式的数据文件。它的优势在于灵活性和可扩展性,你可以...

    JavaCC - 用于根据语法构建解析器的解析器生成器 它可以生成 Java、C++ 和 C# 代码 .zip

    内容介绍特征一个例子教程常问问题入门从命令行在 IDE 中重建 JavaCC社区支持文档资源由 JavaCC 提供支持执照介绍特征JavaCC 生成自上而下(递归下降)解析器,而YACC之类的工具则生成自下而上的解析器。这样可以

    javaCC 是一个能生成语法和词法分析器的生成程序。语法和词法分析器是字符串处理软件的重要组件。

    JavaCC,全称为Java Compiler Compiler,是一个开源的解析器生成器,主要用于构建语法和词法分析器,尤其在处理复杂的字符串处理任务时显得尤为重要。它根据用户提供的上下文无关语法(Context-Free Grammar, CFG)...

    CMM语言解释器JAVA实现(javacc5.0)增强版

    总结来说,"CMM语言解释器JAVA实现(javacc5.0)增强版"是一个用Java编程语言,通过javacc5.0工具生成解析器代码的项目,用于理解和执行CMM语言的程序。其增强版可能包括了性能优化和功能扩展,为特定领域的编程提供...

    CMM语言解释器JAVA实现(javacc5.0)

    4. javacc5.0:JavaCC(Java Compiler Compiler)是一个开源的Java解析器生成器,它根据BNF(巴科斯范式)文法定义生成解析器和词法分析器的源代码。在本项目中,javacc5.0用于自动生成处理CMM语言的解析逻辑,简化...

    javacc实现cmm语法分析

    它会生成Java源代码,包含一个解析器和一个词法分析器,用于读取输入,识别符号,并按照预定的语法规则进行解析。 2. **创建CMM语法规则**: 首先,你需要定义CMM语言的BNF(巴科斯范式)或EBNF(扩展巴科斯范式)...

    基于JavaCC的c语言编译器前端实现

    这个项目“基于JavaCC的C语言编译器前端实现”显然旨在教授如何使用JavaCC来创建一个C语言的编译器前端。 在编译器设计中,前端主要负责词法分析、语法分析和语义分析。词法分析是将源代码转换为一系列的单词项...

    javacc使用指南

    JavaCC 是一个解析器生成器和词法分析器生成器。解析器和词法分析器是处理字符序列输入的软件组件。编译器和解释器包含了词法分析器和解析器来解码包含程序的文件。然而,词法分析器和解析器可以广泛应用于其他多种...

    基于Minic的语法分析器(javacc)

    总之,“基于Minic的语法分析器(javacc)”是一个实用的学习资源,它揭示了编译器和解析器的核心工作原理,提供了从文法到执行的完整流程。对于想要深入理解编译技术或提升JavaCC使用技巧的开发者来说,这是一个...

    JavaCC

    总结起来,JavaCC是一个功能强大且灵活的Java语法分析工具,它允许开发者通过定义文法来生成解析器和词法分析器,从而处理各种语言和数据格式的解析任务。通过使用JavaCC,开发者可以轻松地构建自己的编译器、解释器...

    javacc构造编译器的方法

    本文首先简要介绍了语法分析器自动生成的原理,并重点介绍了一个由Sun公司开发的编译器自动生成工具——JavaCC,以及如何利用JavaCC来构造编译器。 #### 二、编译器自动生成原理 编译器是计算机应用中最常用的工具...

    javacc语法分析.zip

    JavaCC(Java Compiler Compiler)是Java语言的一个开源工具,用于生成词法分析器(Lexer)和语法解析器(Parser)的源代码。它基于LL(k)解析算法,并且支持自定义文法,使得开发者能够构建复杂的语法分析器,用于...

    JavaCC语法分析器 基于Eclipse插件 能从文件读取源代码输出语法树

    在这个项目中,JavaCC生成的解析器被封装为一个Eclipse插件,用户可以直接在Eclipse内处理源代码,查看其对应的语法树,这对于理解和调试代码非常有帮助。 Test.java是测试类,通常包含用于验证解析器功能的代码。...

    公式解析器(用javacc实现)

    javaCC是一个很好的解析工具,但针对具体应用自己要写一个脚本来应用,然后应用javaCC工具生成java代码即可使用。 在网上的javaCC的应用比较少,也没有太多资料,希望能帮到大家。 这是一个针对公式解析的脚本,打开...

Global site tag (gtag.js) - Google Analytics