自定义脚本语言

本文介绍使用ANTLR工具(http://www.antlr.org/)实现基本的脚本语言。

一、 脚本的语言需求包含一下几点,具备 max、min和条件表达式。
例如计算: if(max(var1,10) = 10) ? max(100,var2) : min(100, max(var1, var2))

二、编写grammar文件

grammar Expr;

compute:
       compute_expr
;

compute_expr:
        max_expr
        |min_expr
        |if_else_expr
        |identifier
        |INTEGER
;

if_else_expr:
       (INTEGER | identifier | max_expr | min_expr | OPEN_PAR_SYMBOL  compute_expr CLOSE_PAR_SYMBOL) EQUAL_SYMBOL compute_expr
       PARAM_MARKER compute_expr COLON_SYMBOL compute_expr
;


max_expr:
        MAX_SYMBOL OPEN_PAR_SYMBOL compute_expr COMMA_SYMBOL compute_expr COMMA_SYMBOL CLOSE_PAR_SYMBOL
        ;

min_expr:
         MIN_SYMBOL OPEN_PAR_SYMBOL compute_expr  COMMA_SYMBOL compute_expr CLOSE_PAR_SYMBOL
         ;

identifier:
          IDENTIFIER
          | keyword
          ;

keyword:
       MAX_SYMBOL
       | MIN_SYMBOL
       ;

//Lexer rule
MAX_SYMBOL:       'MAX'|'max';
MIN_SYMBOL:       'MIN'|'min';

EQUAL_SYMBOL:     '=';
PARAM_MARKER:     '?';
COLON_SYMBOL:     ':';

COMMA_SYMBOL:     ',';
OPEN_PAR_SYMBOL:  '(';
CLOSE_PAR_SYMBOL: ')';


IDENTIFIER: ('A'..'Z' | 'a'..'z' | '_' ) ('A'..'Z' | 'a'..'z' | '_' | '0'..'9')*;
INTEGER:    ('+'|'-')? ('0'..'9')+;

WHITESPACE: ( ' ' | '\t' | '\f' | '\r'| '\n') -> skip;

三、借助工具创建java源代码

java -jar antlr-4.5.3-complete.jar Expr.g4 -o expr -listener -visitor -encoding UTF-8

-o        java源代码输出路径
-listener 生成listener接口源代码
-visitor  生成visitor接口源代码

四、编写计算树和visitor
自定义脚本语言_第1张图片

计算树如图,计算表达式的值只需要从根节点if开始,遍历各个实现语义的node。最终求出表达式的值
基本思路是:
max, min: 函数,取左子树的值和右子树的值进行比较,并返回。
if : 计算第一棵树和第二棵树的值,进行比较,然后根据比较结构,返回第三棵树的值或者第四棵树的值
变量: 实现一个获取变量的结构,在计算时将变量的值传进去。

五、编写JAVA main函数,调用生成的代码

//main函数:
ANTLRInputStream cs = new ANTLRInputStream(define);
ExprLexer lexer = new ExprLexer("if(max(var1,10) = 10) ? max(100,var2) : min(100, max(var1, var2))");
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokenStream);
ParseTree tree = parser.query();
ExprVisitor<TreeNode> visitor = new ExprFuncVisitor<TreeNode>();
TreeNode node = visitor.visit(tree);

你可能感兴趣的:(编译原理)