Antlr(ANother Tool for LanguageRecognition)
ü 一种语言识别工具
ü Antlr提供了一种语言工具框架
ü 定义标示符,关键字(词法分析)
ü 定义表达式(语法分析)
ü 可以将文本转换成抽象语法树(AST)
ü 树的解析(树分析器)
(1)词法分析器Lexer
ü 词法分析识别的是字符流
ü 通过词法规则,依次读入字符,并转换成记号(Token)
例如,s e l e ct--->select 关键字的过程就是一个词法分析的过程
ü 词法分析过程是一个ASCII分类整理的过程,哪些地方可以跳过(空格、换行、注释) ,哪些记号属于标识符,哪些记号属于字符串、整数、浮点数等。
ü 词法部分的定义以大写字母开头
词法分析器常见定义:
ID : ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;//定义一个字符
INT : '0'..'9'+
;//定义一个正整数
FLOAT
: ('0'..'9')+ '.' ('0'..'9')*EXPONENT?
| '.' ('0'..'9')+ EXPONENT?
| ('0'..'9')+ EXPONENT
;//定义一个浮点数
COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n'{$channel=HIDDEN;}
| '/*' ( options {greedy=false;}: . )* '*/' {$channel=HIDDEN;}
;//定义一个多行注释
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;//定义一个可以忽略的字符
STRING
: '"' ( ESC_SEQ |~('\\'|'"') )* '"'
;//定义一个字符串
CHAR: '\'' ( ESC_SEQ | ~('\''|'\\') ) '\''
;
fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC
: '\\' ('0'..'3') ('0'..'7')('0'..'7')
| '\\' ('0'..'7') ('0'..'7')
| '\\' ('0'..'7')
;
fragment
UNICODE_ESC
: '\\' 'u' HEX_DIGIT HEX_DIGITHEX_DIGIT HEX_DIGIT
;
(2)语法分析器(Parser)
ü 根据词法分析输出的记号流,分析语法结构,并添加代表语法结构的抽象单词(如:表达式、类、方法等),按照语法结构生成语法树的过程
ü 语法分析定义了输入字符串的合法性
ü 语法分析将词与词之间的关系用一个语法树表达出来
ü 语法部分的定义由小写字母开头、
ü 语法分析可以生成抽象语法树(AST)
(3)树分析器(TreeParser)
ü 树分析器可以用于对语法分析生成的抽象语法树进行遍历,并能执行一些相关的操作。
grammar Expr;
@header {
package test;
importjava.util.HashMap;
}
@lexer::header{package test;}
@members {
/** Mapvariable name to Integer object holding value */
HashMap memory= new HashMap();
}
prog: stat+ ;
stat: expr NEWLINE{System.out.println($expr.value);}
| ID '=' expr NEWLINE
{memory.put($ID.text, newInteger($expr.value));}
| NEWLINE
;
expr returns[int value]
: e=multExpr {$value = $e.value;}
( '+' e=multExpr {$value += $e.value;}
| '-' e=multExpr {$value -= $e.value;}
)*
;
multExprreturns [int value]
: e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})*
;
atom returns[int value]
: INT {$value = Integer.parseInt($INT.text);}
| ID
{
Integer v =(Integer)memory.get($ID.text);
if ( v!=null ) $value = v.intValue();
else System.err.println("#ff0000variable "+$ID.text);
}
| '(' e=expr ')' {$value = $e.value;}
;
ID : ('a'..'z'|'A'..'Z')+ ;
INT : '0'..'9'+ ;
NEWLINE:'"r'?'"n' ;
WS : (''|'"t')+ {skip();} ;