扩展iQuery使其支持多种编程语言(四) – 兼编译器的语法错误处理简介

扩展iQuery使其支持多种编程语言(四) – 兼编译器的语法错误处理简介css

iQuery是一个开源的自动化测试框架项目,有兴趣的朋友能够在这里下载:https://github.com/vowei/iQuery/downloadshtml

源码位置:https://github.com/vowei/iQueryjava

相关的使用文档,请参看:git

开源类库iQuery Android版使用说明
类jQuery selector的控件查询iQuery开源类库介绍
开源手机自动化测试框架iQuery入门教程(一)
开源手机自动化测试框架iQuery入门教程(二)
开源手机自动化测试框架iQuery入门教程(三)
上一篇文章中,简单介绍了iQuery解释器的语义分析部分。github

ANTLR已经自带了一些对词法和语法错误的处理功能,当一行语句出现语法错误时,ANTLR会尽可能跳过出错的一行代码,恢复编译和解释功能,经过一个回调函数,咱们能够向最终用户显示更细致的错误提示。编程

通常来讲,好的错误提示应该有如下几个性质:
1.    须要指明错误的行号和列号,以便用户快速在源代码中定位出错的那一行代码,这个功能ANTLR会在调用咱们的回调函数时传入这些信息。
2.    须要指明错误缘由,例如“不匹配的字符”这样的错误信息显然没有“第1行,第25列: 没有关闭的语句,指望']',当前碰到的是''<EOF>''!”这样的信息更明确。
3.    须要指明致使出错的文字,例如在编程中,针对使用一个未定义的变量的编程错误,固然须要在错误信息里指出这个未定义的变量名。
4.    最好给出修复错误的建议。框架

在ANTLR里,能够在代码里定义一个getErrorMessage函数,以便ANTLR回调。在Java版本中,getErrorMessage函数的声明形式以下(代码实如今:https://github.com/vowei/iQuery/blob/master/java/iquery/iquery-core/src/main/java/cc/iqa/iquery/iQuery.g):
编程语言

 1: public String getErrorMessage(RecognitionException e,
 2:                                     String[] tokenNames)

当ANTLR碰到词法或者语法错误时,会抛出一个基类为RecognitionException的异常,并传递给getErrorMessage函数,而第二个参数tokenNames就是致使词法/语法错误时的源码符号,getErrorMessage函数的返回值就是细化后的错误消息。函数

ANTLR针对不一样的词/语法错误会生成不一样的RecognitionException的继承类,在这些继承类里,分别定义了一些对细化错误消息有帮助的属性。下面代码是一个细化错误消息的例子,其中MismatchedTokenException表示一个未匹配的语法,在MismatchedTokenException的对象里,能够经过expecting字段获取指望的词法符号(原始代码位置是:https://github.com/vowei/iQuery/blob/master/java/iquery/iquery-core/src/main/java/cc/iqa/iquery/ErrorMessageHelper.java )。测试

 1: if (e instanceof MismatchedTokenException) {
 2:             MismatchedTokenException mte = (MismatchedTokenException) e;
 3:             String tokenName = "<unknown>";
 4:             if (mte.expecting == Token.EOF) {
 5:                 tokenName = "EOF";
 6:             } else if (tokenNames != null) {
 7:                 tokenName = tokenNames[mte.expecting];
 8:             } else {
 9:                 tokenName = new String(new char[] {(char)mte.expecting});
 10:             }
 11:  
 12:             if ( e.token != null ) {
 13:                 msg = String.format("%1$s: 没有关闭的语句,指望%2$s,当前碰到的是'%3$s'!",
 14:                         hdr, tokenName, recognizer.getTokenErrorDisplay(e.token));
 15:             } else {
 16:                 msg = String.format("%1$s: 没有关闭的语句,指望%2$s!",
 17:                         hdr, tokenName);
 18:             }
 19:         }

JavaScript版本里getErrorMessage函数的声明相似,处理方式也相似参考代码:https://github.com/vowei/iQuery/blob/master/iOS/lib/iQuery.ghttps://github.com/vowei/iQuery/blob/master/iOS/lib/error.js ):

 1: function onMismatchedTokenException(mte, tokenNames, recognizer) {
 2:     debug("onMismatchedTokenException");
 3:  
 4:     var tokenName = "<unknown>";
 5:     if (mte.expecting == org.antlr.runtime.Token.EOF) {
 6:         tokenName = "EOF";
 7:     } else if (tokenNames != null) {
 8:         tokenName = tokenNames[mte.expecting];
 9:     } else {
 10:         debug("[onMismatchedTokenException] - mte.expecting: " + mte.expecting);
 11:         tokenName = mte.expecting;
 12:     }
 13:  
 14:     if (mte.token != null) {
 15:         return "没有关闭的语句,指望" + tokenName + ",当前碰到的是'" + recognizer.getTokenErrorDisplay(mte.token) + "'!";
 16:     } else if (tokenName != undefined) {
 17:         return "没有关闭的语句,指望" + tokenName + "!";
 18:     } else {
 19:         return "没有关闭的语句!";
 20:     }
 21: }

因为词法分析器(Lexer)和语法分析器(Parser)是两个类,并且词法和语法分析过程都有可能发生错误,所以须要分别在两个分析器里定义getErrorMessage函数,添加的方式很简单,在antlr的语法定义.g文件里,添加在@lexer::members和@parser::members代码块里便可,例以下面是JavaScript版本的声明方式:

 1: @lexer::members {
 2: _errors = [];
 3: this.getErrorMessage = function(e, tokenNames)
 4: {
 5:     var error = getErrorsHelper(e, null, tokenNames, this);
 6:  
 7:     if ( _errors != undefined && _errors != null ) {
 8:         _errors.push(error);
 9:     }
 10: 
 11:     return error;
 12: }
 13: }
 14:  
 15: @parser::members {
 16: _errors = [];
 17: this.getErrorMessage = function(e, tokenNames)
 18: {
 19:     var error = getErrorsHelper(e, this.input, tokenNames, this);
 20:  
 21:     if ( _errors != undefined && _errors != null ) {
 22:         _errors.push(error);
 23:     }
 24: 
 25:     return error;
 26: }
 27: }
相关文章
相关标签/搜索