2017编程提高第8.5节课——ANTLR
LanyuanXiaoyao's Blog ヽ(✿゚▽゚)ノ

2017编程提高第8.5节课——ANTLR


为什么我需要构建自己的脚本语言?

If user.account.balance > 500000 then
  add_to_vip user
end

如何把一种语言变成另外一种语言(通常高级语言 → 机器语言) ?

词法分析

例子: position := initial + rate * 60 •词法分析(线性分析),形成一个符号表

  1. 标识符 position
  2. 赋值符号 :=
  3. 标识符 initial
  4. 加号 +
  5. 标识符 rate
  6. 乘号 *
  7. 数字 60

语法分析

例子: position := initial + rate * 60

语句 ::=
标识符 “:=“ 表达式
表达式 ::=
标识符 |
数字 |
表达式 “+” 表达式 |
表达式 “\*” 表达式 |
“(“表达式 “)”

BNF : Java 的例子

class_declaration  ::= 
 < modifier >  "class" identifier 
 [  "extends" class_name ] 
 [  "implements" interface_name  <  "," interface_name >  ] 
 "{"  < field_declaration >  "}“

modifier ::=  "public" |  "private" | "protected" | "static" | "final" | "native" | "synchronized" | "abstract" | "threadsafe"|  "transient"  

identifier  ::= "a..z,$,_"  <  "a..z,$,_,0..9,unicode character over 00C0"  >

例子:

public class Employee extends Person{
......略……
}

语义分析

  • 例子: position := initial + rate * 60
  • 类型检查,控制流检查,类型转换 等等

代码生成

简单的脚本

a = 5
b = 3
if a>4 AND b>2 then
  c = a + 5
end
(c*2)+6
……

关键是形成抽象语法树(AST)

形成抽象语法树的方法

  • 自己动手写
    • 需要实现词法分析和语法分析
    • 繁琐并且容易出错
  • 利用工具
    • Lex, Yacc  – Unix
    • Java CC
    • ANTLR

定义表达式计算的规则

似乎有点问题

expr : expr '*' expr	// 匹配由“*”运算符连接的子表达式
  | expr '+' expr		// 匹配由“+”运算符连接的子表达式
  | INT					// 匹配简单整数
  ;

可以改写一下

把规则变成java class

  • 命令行 Antlr4 Expr.g4 -o .\expr -no-listener -visitor -encoding UTF-8
  • 插件

CalculatorVisitor中有什么内容?

一个很有用的工具:grun

grun Expr prog -gui test.data

还可以输出为lisp格式

ExprLexer lexer = new ExprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
ParseTree tree = <u>parser.prog();</u>
System.out.println(tree.toStringTree(parser));

实现if 分支


评论