一、ANTLR简介
ANTLR(ANother Tool for Language Recognition),简单的说,就是让你能够自己定义一种新的语言,然后ANTLR将根据你的定义,生成出这种新语言的识别与翻译程序。请记住三个关键词:
Lexer:词法分析器
Parser:语法分析器
Tree walker:抽象语法树遍历器
所谓词法分析器,简单的说,就是根据输入的字符流,识别出符合语言定义的单词。假设我们已经定义了一个计算四则运算表达式的语言。当我们输入一个字符流时,比如"1 + 2*(10+15)"。对于Lexer来说,
它接收到的输入是:'1','_','+','_','2','*','(','1','0','+','1','5',')'。
而Lexer的输出则是:'1','+','2','*','(','10','+','15',')'。
不具有含义的空格被去掉。完整的整数被识别出来。这样我们就能够得到一个单词流,而非字符流。
所谓语法分析器,则更进一步。简单的说,就是根据输入的单词流,识别出其中的语法结构。对于Parser来说:
它接收到的输入是:'1','+','2','*','(','10','+','15',')'。
而Parser的输出则是一个AST(抽象语法树,这个概念下一次再详细解释):
所谓抽象语法树遍历器,就是一个对AST进行计算的工具。这里的计算具有SICP中所提出的计算那样的广义。就是根据一个用户对于TreeWalker的定义,决定在具体遍历一颗AST时,将进行何种操作或者计算。如果用户定义一个“正儿八经”的TreeWalker,比如像这样:
class ExpressionTreeWalker extends TreeParser;
expr returns [double r]
{ double a,b; r=0; }
: #(PLUS a=expr b=expr) { r=a+b; }
| #(MINUS a=expr b=expr) { r=a-b; }
| #(MUL a=expr b=expr) { r=a*b; }
| #(DIV a=expr b=expr) { r=a/b; }
| #(MOD a=expr b=expr) { r=a%b; }
| #(POW a=expr b=expr) { r=Math.pow(a,b); }
| i:INT { r=(double)Integer.parseInt(i.getText()); }
;
那么ANTLR就能够根据这个定义,生成一个ExpressionTreeWalker类,来对输入的AST,进行计算,并最终返回一个double类型的计算结果。
因此,用户需要做的工作就是,理解ANTLR的语法,定义一个或多个*.g文件,在g文件中,定义具体的Lexer、Parser、TreeWalker,然后由ANTLR来生成代码,这样的代码,就能够理解你所定义的某种新语言的语法,并为你工作了。
(未完待续)