From 8a440f00d8bcec13f1c4c96c51a76a6e3871757d Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 20 May 2015 14:59:16 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D1=80=D0=BE=D0=BA=203.=20=D0=9E=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B0=D1=82=D0=BE=D1=80=20=D0=BF=D1=80=D0=B8=D1=81?= =?UTF-8?q?=D0=B2=D0=BE=D0=B5=D0=BD=D0=B8=D1=8F,=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/com/annimon/ownlang/Main.java | 18 ++++++---- src/com/annimon/ownlang/lib/Constants.java | 30 ---------------- src/com/annimon/ownlang/lib/Variables.java | 34 ++++++++++++++++++ src/com/annimon/ownlang/parser/Lexer.java | 3 +- src/com/annimon/ownlang/parser/Parser.java | 36 ++++++++++++++++--- src/com/annimon/ownlang/parser/TokenType.java | 1 + .../parser/ast/AssignmentStatement.java | 29 +++++++++++++++ .../annimon/ownlang/parser/ast/Statement.java | 10 ++++++ ...pression.java => VariabletExpression.java} | 10 +++--- 9 files changed, 124 insertions(+), 47 deletions(-) delete mode 100644 src/com/annimon/ownlang/lib/Constants.java create mode 100644 src/com/annimon/ownlang/lib/Variables.java create mode 100644 src/com/annimon/ownlang/parser/ast/AssignmentStatement.java create mode 100644 src/com/annimon/ownlang/parser/ast/Statement.java rename src/com/annimon/ownlang/parser/ast/{ConstantExpression.java => VariabletExpression.java} (60%) diff --git a/src/com/annimon/ownlang/Main.java b/src/com/annimon/ownlang/Main.java index 0463ca5..d8ddbab 100644 --- a/src/com/annimon/ownlang/Main.java +++ b/src/com/annimon/ownlang/Main.java @@ -1,9 +1,10 @@ package com.annimon.ownlang; +import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.parser.Lexer; import com.annimon.ownlang.parser.Parser; import com.annimon.ownlang.parser.Token; -import com.annimon.ownlang.parser.ast.Expression; +import com.annimon.ownlang.parser.ast.Statement; import java.util.List; /** @@ -12,17 +13,22 @@ import java.util.List; public final class Main { public static void main(String[] args) { - final String input1 = "2 + 2"; + final String input1 = "word = 2 + 2\nword2 = PI + word"; // final String input2 = "(GOLDEN_RATIO + 2) * #f"; final String input2 = "GOLDEN_RATIO"; - final List tokens = new Lexer(input2).tokenize(); + final List tokens = new Lexer(input1).tokenize(); for (Token token : tokens) { System.out.println(token); } - final List expressions = new Parser(tokens).parse(); - for (Expression expr : expressions) { - System.out.println(expr + " = " + expr.eval()); + final List statements = new Parser(tokens).parse(); + for (Statement statement : statements) { + System.out.println(statement); } + for (Statement statement : statements) { + statement.execute(); + } + System.out.printf("%s = %f\n", "word", Variables.get("word")); + System.out.printf("%s = %f\n", "word2", Variables.get("word2")); } } diff --git a/src/com/annimon/ownlang/lib/Constants.java b/src/com/annimon/ownlang/lib/Constants.java deleted file mode 100644 index 9063418..0000000 --- a/src/com/annimon/ownlang/lib/Constants.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.annimon.ownlang.lib; - -import java.util.HashMap; -import java.util.Map; - -/** - * - * @author aNNiMON - */ -public final class Constants { - - private static final Map constants; - - static { - constants = new HashMap<>(); - constants.put("PI", Math.PI); - constants.put("ПИ", Math.PI); - constants.put("E", Math.E); - constants.put("GOLDEN_RATIO", 1.618); - } - - public static boolean isExists(String key) { - return constants.containsKey(key); - } - - public static double get(String key) { - if (!isExists(key)) return 0; - return constants.get(key); - } -} diff --git a/src/com/annimon/ownlang/lib/Variables.java b/src/com/annimon/ownlang/lib/Variables.java new file mode 100644 index 0000000..4913c51 --- /dev/null +++ b/src/com/annimon/ownlang/lib/Variables.java @@ -0,0 +1,34 @@ +package com.annimon.ownlang.lib; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author aNNiMON + */ +public final class Variables { + + private static final Map variables; + + static { + variables = new HashMap<>(); + variables.put("PI", Math.PI); + variables.put("ПИ", Math.PI); + variables.put("E", Math.E); + variables.put("GOLDEN_RATIO", 1.618); + } + + public static boolean isExists(String key) { + return variables.containsKey(key); + } + + public static double get(String key) { + if (!isExists(key)) return 0; + return variables.get(key); + } + + public static void set(String key, double value) { + variables.put(key, value); + } +} diff --git a/src/com/annimon/ownlang/parser/Lexer.java b/src/com/annimon/ownlang/parser/Lexer.java index 446dafd..698c165 100644 --- a/src/com/annimon/ownlang/parser/Lexer.java +++ b/src/com/annimon/ownlang/parser/Lexer.java @@ -9,11 +9,12 @@ import java.util.List; */ public final class Lexer { - private static final String OPERATOR_CHARS = "+-*/()"; + private static final String OPERATOR_CHARS = "+-*/()="; private static final TokenType[] OPERATOR_TOKENS = { TokenType.PLUS, TokenType.MINUS, TokenType.STAR, TokenType.SLASH, TokenType.LPAREN, TokenType.RPAREN, + TokenType.EQ }; private final String input; diff --git a/src/com/annimon/ownlang/parser/Parser.java b/src/com/annimon/ownlang/parser/Parser.java index eb312c6..ab03480 100644 --- a/src/com/annimon/ownlang/parser/Parser.java +++ b/src/com/annimon/ownlang/parser/Parser.java @@ -1,9 +1,11 @@ package com.annimon.ownlang.parser; +import com.annimon.ownlang.parser.ast.AssignmentStatement; import com.annimon.ownlang.parser.ast.BinaryExpression; -import com.annimon.ownlang.parser.ast.ConstantExpression; +import com.annimon.ownlang.parser.ast.VariabletExpression; import com.annimon.ownlang.parser.ast.Expression; import com.annimon.ownlang.parser.ast.NumberExpression; +import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.UnaryExpression; import java.util.ArrayList; import java.util.List; @@ -26,14 +28,31 @@ public final class Parser { size = tokens.size(); } - public List parse() { - final List result = new ArrayList<>(); + public List parse() { + final List result = new ArrayList<>(); while (!match(TokenType.EOF)) { - result.add(expression()); + result.add(statement()); } return result; } + private Statement statement() { + return assignmentStatement(); + } + + private Statement assignmentStatement() { + // WORD EQ + final Token current = get(0); + if (match(TokenType.WORD) && get(0).getType() == TokenType.EQ) { + final String variable = current.getText(); + consume(TokenType.EQ); + return new AssignmentStatement(variable, expression()); + } + throw new RuntimeException("Unknown statement"); + } + + + private Expression expression() { return additive(); } @@ -94,7 +113,7 @@ public final class Parser { return new NumberExpression(Long.parseLong(current.getText(), 16)); } if (match(TokenType.WORD)) { - return new ConstantExpression(current.getText()); + return new VariabletExpression(current.getText()); } if (match(TokenType.LPAREN)) { Expression result = expression(); @@ -104,6 +123,13 @@ public final class Parser { throw new RuntimeException("Unknown expression"); } + private Token consume(TokenType type) { + final Token current = get(0); + if (type != current.getType()) throw new RuntimeException("Token " + current + " doesn't match " + type); + pos++; + return current; + } + private boolean match(TokenType type) { final Token current = get(0); if (type != current.getType()) return false; diff --git a/src/com/annimon/ownlang/parser/TokenType.java b/src/com/annimon/ownlang/parser/TokenType.java index 88c6a70..71f6906 100644 --- a/src/com/annimon/ownlang/parser/TokenType.java +++ b/src/com/annimon/ownlang/parser/TokenType.java @@ -14,6 +14,7 @@ public enum TokenType { MINUS, STAR, SLASH, + EQ, LPAREN, // ( RPAREN, // ) diff --git a/src/com/annimon/ownlang/parser/ast/AssignmentStatement.java b/src/com/annimon/ownlang/parser/ast/AssignmentStatement.java new file mode 100644 index 0000000..b763512 --- /dev/null +++ b/src/com/annimon/ownlang/parser/ast/AssignmentStatement.java @@ -0,0 +1,29 @@ +package com.annimon.ownlang.parser.ast; + +import com.annimon.ownlang.lib.Variables; + +/** + * + * @author aNNiMON + */ +public final class AssignmentStatement implements Statement { + + private final String variable; + private final Expression expression; + + public AssignmentStatement(String variable, Expression expression) { + this.variable = variable; + this.expression = expression; + } + + @Override + public void execute() { + final double result = expression.eval(); + Variables.set(variable, result); + } + + @Override + public String toString() { + return String.format("%s = %s", variable, expression); + } +} diff --git a/src/com/annimon/ownlang/parser/ast/Statement.java b/src/com/annimon/ownlang/parser/ast/Statement.java new file mode 100644 index 0000000..0c69260 --- /dev/null +++ b/src/com/annimon/ownlang/parser/ast/Statement.java @@ -0,0 +1,10 @@ +package com.annimon.ownlang.parser.ast; + +/** + * + * @author aNNiMON + */ +public interface Statement { + + void execute(); +} diff --git a/src/com/annimon/ownlang/parser/ast/ConstantExpression.java b/src/com/annimon/ownlang/parser/ast/VariabletExpression.java similarity index 60% rename from src/com/annimon/ownlang/parser/ast/ConstantExpression.java rename to src/com/annimon/ownlang/parser/ast/VariabletExpression.java index ded0aff..96a64e9 100644 --- a/src/com/annimon/ownlang/parser/ast/ConstantExpression.java +++ b/src/com/annimon/ownlang/parser/ast/VariabletExpression.java @@ -1,23 +1,23 @@ package com.annimon.ownlang.parser.ast; -import com.annimon.ownlang.lib.Constants; +import com.annimon.ownlang.lib.Variables; /** * * @author aNNiMON */ -public final class ConstantExpression implements Expression { +public final class VariabletExpression implements Expression { private final String name; - public ConstantExpression(String name) { + public VariabletExpression(String name) { this.name = name; } @Override public double eval() { - if (!Constants.isExists(name)) throw new RuntimeException("Constant does not exists"); - return Constants.get(name); + if (!Variables.isExists(name)) throw new RuntimeException("Constant does not exists"); + return Variables.get(name); } @Override