これを行うには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 + "(...)");
}
}
これで、すべての個別のメソッドを独自のクラスに実装する必要はありませんが、もちろん、のevaluate()
メソッドで呼び出されるメソッドを確認する必要がありMathCallNode
ます。
今評価する場合:
println(Math.sqrt(9));
println(Math.min(9, -42));
以下が印刷されます。
3.0
-42.0