CSDN博客

img leafinwind

ANTLR(语言识别的另一工具)的简介之二[翻译]

发表于2004/2/11 14:08:00  1445人阅读

分类: 编译原理

亲和的ANTLR语法的介绍  

通过例子来逐渐学习ANTLR是最好的。 一个简单计算器常被用来入门,原因很简单:它简单易懂。这有许多给ANTLR的相似例子和教程,但是我会使用我自己的语言来描述一个计算器。首先我们会创建一些可以直接对简单表达式求值的程序。然后,我会生成树结构,并计算这些树来得到同样的答案。

当你知道最终你需要将一个字符输入流分解成多个记号时,则好的开始就是去思考一个表达式的文法结构。

语法向导执行

语言识别

我们接受了包含+,-和*的算术表达式,如3+4*5-1,或是可以增强求值顺序的括号表达式,如(3+4)*5。

全部ANTLR语法都是lexer,语法解析程序和语法树解析程序的子类。既然你应该开始在文法层面思考问题,你因该创建一个文法解析程序的子类。在类的声明之后,你可以使用扩展巴柯斯范式符号指定规则:

class ExprParser extends Parser;

 

expr:   mexpr ((PLUS|MINUS) mexpr)*

    ;     

 

mexpr     

    :   atom (STAR atom)*

    ;   

 

atom:   INT

    |   LPAREN expr RPAREN

    ;

lexer遵从相似的模式,它只需要定义一些操作符和空白符。把lexer放进相同的文件,如expr.g,是要做的最容易的事情:

class ExprLexer extends Lexer;

 

options {

    k=2; // needed for newline junk

    charVocabulary='/u0000'..'/u007F'; // allow ascii

}

 

LPAREN: '(' ;

RPAREN: ')' ;

PLUS  : '+' ;

MINUS : '-' ;

STAR  : '*' ;

INT   : ('0'..'9')+ ;

WS    : ( ' '

        | '/r' '/n'

        | '/n'

        | '/t'

       )

        {$setType(Token.SKIP);}

      ;   

从这个语法定义文件expr.g生成程序(Java),可以运行ANTLR如下:

$ java antlr.Tool expr.g

ANTLR Parser Generator   Version 2.7.2   1989-2003 jGuru.com

$

ANTLR 产生什么?

当发现没有必要完成这个教程时,你可能看到ANTLR在识别程序文件里面生成了什么,并发现这很有启发。ANTLR生成了识别程序,这些程序模拟你通过手工递归下推的语法分析程序来创建的东西;而另一方面,yacc及其朋友在模拟下推自动机的时候生成满是整形数的表。

ANTLR 将产生下列文件:

ExprLexer.java

ExprParser.java

ExprParserTokenTypes.java

ExprParserTokenTypes.txt

如果你看一下里面的内容,比如ExprParser.java,你会看到它为文件expr.g中有解析语法定义的每条规则生成一个方法。比如,mexpr合atom规则的代码看起来类似如下代码:

public void mexpr() {

  atom();

  while ( LA(1)==STAR ) {

    match(STAR);

    atom();

  }

}

 

public void atom() {

  switch ( LA(1) ) { // switch on lookahead token type

    case INT :

      match(INT);

      break;

    case LPAREN :

      match(LPAREN);

      expr();

      match(RPAREN);

      break;

    default :

      // error

  }

}

注意到规则定义被翻译成了方法调用,而记号定义则被译成match(TOKEN)函数调用。则关于创建一种语法parser中仅有的难事就是计算前瞻信息。

记号类别类定义了你的词法分析程序(lexer)和parser所使用到的所有记号类别数字常量:

// $ANTLR 2.7.2: "expr.g" -> "ExprParser.java"$

 

public interface ExprParserTokenTypes {

        int EOF = 1;

        int NULL_TREE_LOOKAHEAD = 3;

        int PLUS = 4;

        int MINUS = 5;

        int STAR = 6;

        int INT = 7;

        int LPAREN = 8;

        int RPAREN = 9;

        int WS = 10;

}

测试lexer/parser

为了在实际中使用在ExprParser.java中作为结果的parser,须像如下所示来使用main()函数:

import antlr.*;

public class Main {

    public static void main(String[] args) throws Exception {

        ExprLexer lexer = new ExprLexer(System.in);

        ExprParser parser = new ExprParser(lexer);

        parser.expr();

    }

}

$ java Main

3+(4*5)

$

给错误的输入:

$ java Main

3++

line 1:3: unexpected token: +

$

或者

$ java Main

3+(4

line 1:6: expecting RPAREN, found 'null'

$

0 0

相关博文

我的热门文章

img
取 消
img