antlr 介绍以及脚本编写(一)

来源:互联网 发布:tgp检测网络环境异常 编辑:程序博客网 时间:2024/05/23 02:05

1、 介绍
ANTLR—Another Tool for Language Recognition,antlr是指可以根据输入自动生成语法树并可视化的显示出来的开源语法分析器。

antlr主要内容有三个: 词法分析器(Lexer)、语法分析器(Parser)、树分析器 (tree parser)。无论是Lexer还是Parser都是一种识别器,Lexer是字符序列识别器而Parser是Token序列识别器。他们在本质上是类似的东西,而只是在分工上有所不同而已;树分析器可以用于对语法分析生成的抽象语法树进行遍历,并能执行一些相关的操作

一般分成两个阶段;
第一阶段: 大脑会下意识的将字符组成单词,然后像查询字典一样识别它们的意思(词法分析 lexical analysis: lex)
第二阶段:大脑会根据已识别的单词去识别句子的结构(parser 默认为antlr会构建出一棵分析树(parser tree)或叫语法树(syntax tree));

2、 启动ui和运行
需要jar包为: antlr-3.1.3.jar(运行包)、antlrworks-1.4.jar(ui界面包)
启动ui: java -cp jar包的路径 org.antlr.works.IDE
运行: java -cp jar包的路径 org.antlr.Tool *.g

3、 运行计算方法:
1. 脚本里加入action
2. 构建AST(abstract syntax tree);

3、 脚本编写实例
实例1:
parser和lexer结合

grammar Expr;//parser ruleexpr returns [int value=0]: a=INT PLUS b=INT {    int aValue = Integer.parseInt(a.getText());    int bValue = Integer.parseInt(b.getText());    $value = aValue + bValue;}// lexer rulePLUS: '+';INT: ('0'..'9')+;备注: lexer rule 要求字符首字母大写,一般默认整个单词都大写parser rule 要求首字母小写,一般默认整个单词小写字符串一般加单引号每行结束符需要加分好执行命令后会生成 Expr.tokens/ExprLexer.java/ExprParser.java

实例2:
parser lexer tree三个结合

// 分为两个.g文件// 1. parser和lexer  Expr.ggrammar Expr;options {    ASTLabelType = CommonTree;    language = Java;    output = AST;}// tokens 分词  构建AST需要tokens {    PROG;    STAT;    NUM;    VAR;    // AND = 'and';}//parser ruleprog: stat -> ^(PROG stat); //构建语法树stat: expr EOF -> ^(STAT expr);expr: multiExpr (('+'^|'-'^) multiExpr)*;multiExpr : atom (('*'^|'/'^) atom)*;atom: '('expr')' -> expr    |   INT ->^(NUM INT)    |   ID -> ^(VAR ID );// lexer ruleID: ('a'..'z'|'A'..'Z')+;INT: ('0'..'9')+;NEWLINE: '\r'?'\n';WS: (' ' | '\t'|'\n'|'\r')+ {skip{};}; // 空行,一般执行跳过动作// 2 tree 文件  Eval.g  执行命令后会生成Eval.tokens/Eval.javatree grammar Eval;options {    tokenVocab = Expr; // parser文件名    ASTLabelType = CommonTree;    language = Java;}// tokens 分词  构建AST需要tokens {    PROG;    STAT;    NUM;    VAR;    // AND = 'and';}@header {import java.util.Random;}//tree parser ruleprog: ^(PROG s=stat) { // prog要执行的方法体 System.out.println("Computer result:" +  s.intValue());};stat returns [Integer value]: ^(STAT e=expr) {    $value = e.intValue();};expr  returns [Integer value]:  ^('+' e1=expr e2=expr) {$value = e1.intValue() + e2.intValue();}    | ^('-' e1=expr e2=expr) {$value = e1.intValue() - e2.intValue();}    | a = atom {$value = a.intValue();};atom returns [Integer value]: ^(NUM i=INT) {$value = Integer.parseInt(i.getText());};//备注: 1. 整个两个文件在执行org.antlr.Tool 的时候,格式为org.antlr.Tool *.g,确保Expr.tokens 和 Eval.tokens一致才行

4、个人总结:
1. 编写.g脚本的时候,里面的语言可以java/c++等
2. 编写tree的脚本的时候,需要根据AST树的情况来确定最终的结果。一般需要设计成迭代执行。
3. parser rule 和tree rule 冒号左边都是方法名。

5、 java代码调用

String rule= "111=222 AND 333=444";ANTLRStringStream input = new ANTLRStringStream(rule);// 生成的lexer类FilterRuleLexer lexer = new FilterRuleLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);// 生成的parser类FilterRuleParser parser = new FilterRuleParser(tokens);// parser中的主规则, parser中的任何规则都可以返回commontree, 一般默认调用主规则CommonTree tree = (CommonTree)parser.rule().getTree();CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);nodes.setTokenStream(tokens);//生成的treerule类FilterTreeRule treeRule = new FilterTreeRule(nodes);System.out.println(treeRule.rule());// tree rule类中的主规则System.out.println(tree.token);
0 0