【记录】把ANTLR v3整合到Android的App中

之前已经可以在antlrworks中折腾简单的示例代码了:

【记录】尝试使用ANTLRWorks 1.5开发

接下来,就是想办法,将其antlr v3的整套环境,集成到Android的app中。


1.目前用的是基于Eclipse的ADT开发环境,所以第一步就是先把对应的antlr的jar包,比如antlr-3.4-complete.jar,集成到ADT中,使得可以调用。

注:其中之所以选择

antlr-3.4-complete.jar

而不选择

antlr-3.5-complete.jar

是因为,1.5版本的antlrworks用的就是3.5,然后无法正常调试。

而旧版本的,都是用的3.4,都是可以正常调试的。

详见:

【已解决】ANTLRWorks 1.5编译代码出错:Compiler failed with result code 1

 

2.ADT中,新建了个android项目,然后去对于libs中尝试导入:

adt libs import

general archive file next

choose antlr complete jar

然后就可以正常导入了antlr的jar包了:

imported antlr jar package

但是写代码去import:

import org.antlr.runtime.*;
import org.antlr.runtime.debug.*;
import org.antlr.runtime.misc.*;
import org.antlr.runtime.tree.*;

是会出错的,显示找不到对应的库。

3.后来经过尝试,需要从文件系统中导入才可以:

select import from file system

choose dir and select jar

然后才是可以正常导入单个的jar包,并且代码也是正常的:

imported antlr 3.4 complete jar

 

4.接下来,好像就是,参考上面的:

How do I use ANTLR v3 generated Lexer and Parser from Java?

去写测试代码了。

 

5. 其中,对应的所包含的库和函数,都可以在:

http://www.antlr3.org/api/Java/index.html

中找到。

现把整体的api架构摘录如下:

http://www.antlr3.org/api/Java/org/antlr/runtime/package-tree.html

Hierarchy For Package org.antlr.runtime

Package Hierarchies:

Class Hierarchy

Interface Hierarchy

 

6.貌似

http://www.antlr.org/wiki/pages/viewpage.action?pageId=789

中提到的java.g可以在这里:

http://www.antlr3.org/grammar/list.html

找到:

Java 1.6 grammar

http://openjdk.java.net/projects/compiler-grammar/antlrworks/Java.g

不过,目前发现,那个示例代码,还是有点复杂。

所以,还是先用我们自己的,简单的测试代码去尝试。

7.现在的前提是:

所用测试代码为:

(1)ExprSimple.g:

grammar ExprSimple;

options {
	output = AST;
	ASTLabelType = CommonTree; // type of $stat.tree ref etc...
}

INT		:	'0'..'9'+ ;
NEWLINE	:	'\r'? '\n' ;
WS		:	(' '|'\t')+ {skip();} ;

prog	:	stat+ ;

stat	:	expr NEWLINE	-> expr
		;
	
expr	:	multExpr (('+'^|'-'^) multExpr)*
		;

multExpr:	atom ('*'^ atom)* ;

atom	:	INT
		|	'('! expr ')'!
		;

对应的文件为:

g file src

 

(2)用antlrworks-1.4.3.jar去生成对应的code:

use antlrworks to generate code

generated code in output dir

生成到output文件夹中的文件为:

ouput java and tokens

classes for lexer and parser

8.接下来,就是想办法,把对应的classes:

__Test__.class

ExprSimpleLexer.class

ExprSimpleParser$atom_return.class

ExprSimpleParser$expr_return.class

ExprSimpleParser$multExpr_return.class

ExprSimpleParser$prog_return.class

ExprSimpleParser$stat_return.class

ExprSimpleParser.class

都先导入到当前android项目中,才能供后面代码所引用。

关于如何将java的class文件导入到Android的adt中,详见:

【已解决】Android的ADT中导入Java的class文件

 

9.不过,余下一个小问题,原本的

ExprSimpleLexer.java

中,都没有包含对应的package,所以需要添加进来:

add package declaration to ours

变成:

added package declaration

对ExprSimpleParser.java也同样操作即可。

即可完全消除语法错误,可以继续编译java文件,可以正常使用class类,调用其中的函数了。

 

10.再去写代码测试。

期间,学习示例代码过程中,示例代码中的:

RuleReturnScope result = parser.compilationUnit();

对应的compilationUnit是原始的java.g

(之前提到过了,下载地址是:

http://openjdk.java.net/projects/compiler-grammar/antlrworks/Java.g

)

中的:

/********************************************************************************************
                          Parser section
*********************************************************************************************/
           
compilationUnit 
    :   (   (annotations
            )?
            packageDeclaration
        )?
        (importDeclaration
        )*
        (typeDeclaration
        )*
    ;

表示入口执行函数,所以,我们此处,应该改为对应的,我们此处ExprSimple.g中的prog。

 

最终写出来了测试代码:

package com.mm.antlrv3demo;

import org.antlr.runtime.*;
//import org.antlr.runtime.ANTLRStringStream;
//import org.antlr.runtime.CharStream;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class DDParser extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_ddparser);
		
		antlrV3Demo();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_ddparser, menu);
		return true;
	}
	
	public void antlrV3Demo()
	{
		String inputStr = "1*2+(3*4)";
		CharStream cs = new ANTLRStringStream(inputStr);
		
		ExprSimpleLexer lexer = new ExprSimpleLexer(cs);
		CommonTokenStream tokens = new CommonTokenStream();
		tokens.setTokenSource(lexer);
		
		ExprSimpleParser parser = new ExprSimpleParser(tokens);
		try {
			RuleReturnScope result = parser.prog();
		} catch (RecognitionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
//		final fsqParser.formula_return parserResult = parser.expr();
		
	}

}

想要去debu,结果却出错。

发现是__Test__.java的问题:

when run __test__ errors

现在可以大概看懂了,其中__Test__.java的代码,就是和我们此处写的测试代码,干的是同样的事情,都是去测试。

只不过__Test__.java是调用49100端口,被antlrworks监视,调用antlrworks去调试而已。

而我们此处,由于自己写了测试代码,所以就完全不需要__Test__.java了,所以可以去把__Test__.java删除掉:

__Test_.java remove it

而对于

__Test___input.txt

暂时可以先不删除,因为可以用于以后的测试,从此文件中输入测试字符串,而不是当前代码中写入测试字符串。

 

11.然后就可以接着调试了。

这个是调试期间的CharStream类型的变量:

charstream variable runtime

Lexer类型变量:

lexer type variable runtime variable

commontokenstream type value runtime

Parser变量:

parser type value runtime

当时没有调试出来接下来的result变量,

所以后来又去参考了:

RuleReturnScope

添加了一行代码:

			Object outputTree = result.getTree();
			System.out.println(outputTree);

调试出,RuleReturnScope类型变量:

RuleReturnScope result value runtime

getTree的结果:

result tree runtime

 

【总结】

目前来说,是可以把antlr v3整合到android的app中了。

只是后续还有很多要做的事情,包括:

  • 尝试把输入特殊字符串,从变量改为从文件读取:这个不难,参考示例代码,使用ANTLRFileStream应该就可以了;
  • 搞懂上述的getTree()返回的值,是否是正确的,是否是我们所需要的:有待研究;
  • 如何把示例代码中parse tree部分整合进来:这个估计还是会很复杂的;


发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量