之前已经可以在antlrworks中折腾简单的示例代码了:
接下来,就是想办法,将其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中尝试导入:
然后就可以正常导入了antlr的jar包了:
但是写代码去import:
import org.antlr.runtime.*; import org.antlr.runtime.debug.*; import org.antlr.runtime.misc.*; import org.antlr.runtime.tree.*;
是会出错的,显示找不到对应的库。
3.后来经过尝试,需要从文件系统中导入才可以:
然后才是可以正常导入单个的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.runtimePackage 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
找到:
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 ')'! ;
对应的文件为:
(2)用antlrworks-1.4.3.jar去生成对应的code:
生成到output文件夹中的文件为:
8.接下来,就是想办法,把对应的classes:
__Test__.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,所以需要添加进来:
变成:
对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的问题:
现在可以大概看懂了,其中__Test__.java的代码,就是和我们此处写的测试代码,干的是同样的事情,都是去测试。
只不过__Test__.java是调用49100端口,被antlrworks监视,调用antlrworks去调试而已。
而我们此处,由于自己写了测试代码,所以就完全不需要__Test__.java了,所以可以去把__Test__.java删除掉:
而对于
__Test___input.txt
暂时可以先不删除,因为可以用于以后的测试,从此文件中输入测试字符串,而不是当前代码中写入测试字符串。
11.然后就可以接着调试了。
这个是调试期间的CharStream类型的变量:
Lexer类型变量:
Parser变量:
当时没有调试出来接下来的result变量,
所以后来又去参考了:
添加了一行代码:
Object outputTree = result.getTree(); System.out.println(outputTree);
调试出,RuleReturnScope类型变量:
getTree的结果:
【总结】
目前来说,是可以把antlr v3整合到android的app中了。
只是后续还有很多要做的事情,包括:
- 尝试把输入特殊字符串,从变量改为从文件读取:这个不难,参考示例代码,使用ANTLRFileStream应该就可以了;
- 搞懂上述的getTree()返回的值,是否是正确的,是否是我们所需要的:有待研究;
- 如何把示例代码中parse tree部分整合进来:这个估计还是会很复杂的;
转载请注明:在路上 » 【记录】把ANTLR v3整合到Android的App中