我一直在学习 http://bkiers.blogspot.de/2011/03/creating-your-own-programming-language.html 上的教程。 。简而言之,开发了一种具有最少算术运算集的小型语言。 “println”和“print”是直接映射的函数,调用 System.out.print()
。
从此,我尝试通过更改该系列文章中开发的语言的一些属性来实现我自己的 DSL。我想做java.lang.Math
可以从我的 DSL 中访问,但想不出无需手动映射每个函数的好方法。
该语言不支持任何导入。我可以引入一个新的语法规则来匹配 Math.<function>(<parameters>)
.
最佳答案
您可以通过将 Math
设置为保留字并进行以下更改来做到这一点:
语法补充
functionCall
: Identifier '(' exprList? ')' -> ^(FUNC_CALL Identifier exprList?)
| Println '(' expression? ')' -> ^(FUNC_CALL Println expression?)
| Print '(' expression ')' -> ^(FUNC_CALL Print expression)
| Assert '(' expression ')' -> ^(FUNC_CALL Assert expression)
| Size '(' expression ')' -> ^(FUNC_CALL Size expression)
| Math '.' Identifier '(' exprList ')' -> ^(FUNC_CALL Math Identifier exprList) // added
;
// ...
Math : 'Math'; // added
树语法添加
functionCall returns [TLNode node]
: ^(FUNC_CALL Identifier exprList?) {node = new FunctionCallNode($Identifier.text, $exprList.e, functions);}
| ^(FUNC_CALL Println expression?) {node = new PrintlnNode($expression.node);}
| ^(FUNC_CALL Print expression) {node = new PrintNode($expression.node);}
| ^(FUNC_CALL Assert expression) {node = new AssertNode($expression.node);}
| ^(FUNC_CALL Size expression) {node = new SizeNode($expression.node);}
| ^(FUNC_CALL Math Identifier exprList) {node = new MathCallNode($Identifier.text, $exprList.e);} // added
;
新的数学节点类
package tl.tree;
import tl.TLValue;
import java.util.ArrayList;
import java.util.List;
public class MathCallNode implements TLNode {
private String methodName;
private List<TLNode> params;
public MathCallNode(String nm, List<TLNode> ps) {
methodName = nm;
params = ps;
}
@Override
public TLValue evaluate() {
if(methodName.equals("sqrt"))
return new TLValue(Math.sqrt(params.get(0).evaluate().asDouble()));
else if(methodName.equals("min"))
return new TLValue(Math.min(params.get(0).evaluate().asDouble(), params.get(1).evaluate().asDouble()));
// TODO implement more Math-methods
else
throw new RuntimeException("unknown method: Math." + methodName + "(...)");
}
}
现在您不需要在自己的类中实现所有单独的方法,但当然仍然需要检查在 MathCallNode
的 evaluate()
方法中调用了哪个方法。
如果您现在评估:
println(Math.sqrt(9));
println(Math.min(9, -42));
将打印以下内容:
3.0
-42.0
关于java - 具有 Java 互操作性的 ANTLR DSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10280327/