From 7756e3617977357ad6b9896272fed768b927b273 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 15 Jun 2015 14:45:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D1=80=D0=BE=D0=BA=209.=20=D0=A4=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- program.txt | 7 ++- src/com/annimon/ownlang/lib/Function.java | 10 ++++ src/com/annimon/ownlang/lib/Functions.java | 49 +++++++++++++++++++ src/com/annimon/ownlang/parser/Parser.java | 16 ++++++ .../ownlang/parser/ast/FunctionStatement.java | 24 +++++++++ .../parser/ast/FunctionalExpression.java | 45 +++++++++++++++++ 6 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 src/com/annimon/ownlang/lib/Function.java create mode 100644 src/com/annimon/ownlang/lib/Functions.java create mode 100644 src/com/annimon/ownlang/parser/ast/FunctionStatement.java create mode 100644 src/com/annimon/ownlang/parser/ast/FunctionalExpression.java diff --git a/program.txt b/program.txt index 09f8479..c1a59f2 100644 --- a/program.txt +++ b/program.txt @@ -21,7 +21,7 @@ if (40 < 50 || 50 > 60) { i = 0 print "while" while (i < 10) { - print "i = " + i + "\n" + print "i = " + i + sin(i) + "\n" i = i + 1 } print "for" @@ -29,4 +29,7 @@ if (40 < 50 || 50 > 60) { print "i = " + i + "\n" } } -else print "false" \ No newline at end of file +else print "false" + +print "sin(PI) = " + sin(PI/2) +echo(1,2,3,"4","5","text",sin(0),cos(0),sin(PI),cos(PI),PI) \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/Function.java b/src/com/annimon/ownlang/lib/Function.java new file mode 100644 index 0000000..07cb0d9 --- /dev/null +++ b/src/com/annimon/ownlang/lib/Function.java @@ -0,0 +1,10 @@ +package com.annimon.ownlang.lib; + +/** + * + * @author aNNiMON + */ +public interface Function { + + Value execute(Value... args); +} diff --git a/src/com/annimon/ownlang/lib/Functions.java b/src/com/annimon/ownlang/lib/Functions.java new file mode 100644 index 0000000..dfddc69 --- /dev/null +++ b/src/com/annimon/ownlang/lib/Functions.java @@ -0,0 +1,49 @@ +package com.annimon.ownlang.lib; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author aNNiMON + */ +public final class Functions { + + private static final NumberValue ZERO = new NumberValue(0); + private static final Map functions; + + static { + functions = new HashMap<>(); + functions.put("sin", new Function() { + + @Override + public Value execute(Value... args) { + if (args.length != 1) throw new RuntimeException("One arg expected"); + return new NumberValue(Math.sin(args[0].asNumber())); + } + }); + functions.put("cos", (Function) (Value... args) -> { + if (args.length != 1) throw new RuntimeException("One arg expected"); + return new NumberValue(Math.cos(args[0].asNumber())); + }); + functions.put("echo", args -> { + for (Value arg : args) { + System.out.println(arg.asString()); + } + return ZERO; + }); + } + + public static boolean isExists(String key) { + return functions.containsKey(key); + } + + public static Function get(String key) { + if (!isExists(key)) throw new RuntimeException("Unknown function " + key); + return functions.get(key); + } + + public static void set(String key, Function function) { + functions.put(key, function); + } +} diff --git a/src/com/annimon/ownlang/parser/Parser.java b/src/com/annimon/ownlang/parser/Parser.java index d78e502..34e5242 100644 --- a/src/com/annimon/ownlang/parser/Parser.java +++ b/src/com/annimon/ownlang/parser/Parser.java @@ -65,6 +65,9 @@ public final class Parser { if (match(TokenType.FOR)) { return forStatement(); } + if (get(0).getType() == TokenType.WORD && get(1).getType() == TokenType.LPAREN) { + return new FunctionStatement(function()); + } return assignmentStatement(); } @@ -114,6 +117,16 @@ public final class Parser { return new ForStatement(initialization, termination, increment, statement); } + private FunctionalExpression function() { + final String name = consume(TokenType.WORD).getText(); + consume(TokenType.LPAREN); + final FunctionalExpression function = new FunctionalExpression(name); + while (!match(TokenType.RPAREN)) { + function.addArgument(expression()); + match(TokenType.COMMA); + } + return function; + } private Expression expression() { return logicalOr(); @@ -241,6 +254,9 @@ public final class Parser { if (match(TokenType.HEX_NUMBER)) { return new ValueExpression(Long.parseLong(current.getText(), 16)); } + if (get(0).getType() == TokenType.WORD && get(1).getType() == TokenType.LPAREN) { + return function(); + } if (match(TokenType.WORD)) { return new VariableExpression(current.getText()); } diff --git a/src/com/annimon/ownlang/parser/ast/FunctionStatement.java b/src/com/annimon/ownlang/parser/ast/FunctionStatement.java new file mode 100644 index 0000000..d749777 --- /dev/null +++ b/src/com/annimon/ownlang/parser/ast/FunctionStatement.java @@ -0,0 +1,24 @@ +package com.annimon.ownlang.parser.ast; + +/** + * + * @author aNNiMON + */ +public final class FunctionStatement implements Statement { + + private final FunctionalExpression function; + + public FunctionStatement(FunctionalExpression function) { + this.function = function; + } + + @Override + public void execute() { + function.eval(); + } + + @Override + public String toString() { + return function.toString(); + } +} diff --git a/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java b/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java new file mode 100644 index 0000000..9cdeefc --- /dev/null +++ b/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java @@ -0,0 +1,45 @@ +package com.annimon.ownlang.parser.ast; + +import com.annimon.ownlang.lib.Functions; +import com.annimon.ownlang.lib.Value; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author aNNiMON + */ +public final class FunctionalExpression implements Expression { + + private final String name; + private final List arguments; + + public FunctionalExpression(String name) { + this.name = name; + arguments = new ArrayList<>(); + } + + public FunctionalExpression(String name, List arguments) { + this.name = name; + this.arguments = arguments; + } + + public void addArgument(Expression arg) { + arguments.add(arg); + } + + @Override + public Value eval() { + final int size = arguments.size(); + final Value[] values = new Value[size]; + for (int i = 0; i < size; i++) { + values[i] = arguments.get(i).eval(); + } + return Functions.get(name).execute(values); + } + + @Override + public String toString() { + return name + "(" + arguments.toString() + ")"; + } +}