aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2016-06-16 20:21:25 +0300
committerJan Tuomi <jans.tuomi@gmail.com>2016-07-26 19:47:02 +0300
commitd35a37a449d31e6f4b43b937abf7b0e1fc497828 (patch)
tree8d65ac1068dbf09de480e7cae0fb39ec21d330ec
parentf441022881945db08846e09a8f3bfee2f8cfa95d (diff)
Grammar now uses reverse polish notation
-rw-r--r--main/Main.java20
-rw-r--r--main/core/parser/ASTGenerator.java30
-rw-r--r--main/core/parser/Parser.java245
-rw-r--r--main/core/parser/ast/ASTNode.java4
-rw-r--r--main/core/parser/ast/AdditionNode.java30
-rw-r--r--main/core/parser/ast/AssignmentNode.java36
-rw-r--r--main/core/parser/ast/ExpressionNode.java12
-rw-r--r--main/core/parser/ast/IntegerLiteralNode.java17
-rw-r--r--main/core/parser/ast/SymbolNode.java35
-rw-r--r--main/core/parser/datatype/DataContainer.java14
-rw-r--r--main/core/parser/datatype/IntegerDataContainer.java33
-rw-r--r--main/core/tokenizer/Tokenizer.java4
-rw-r--r--main/core/tokenizer/token/ArgumentInfo.java28
-rw-r--r--main/core/tokenizer/token/Token.java57
-rw-r--r--main/core/tokenizer/token/types/AdditionToken.java22
-rw-r--r--main/core/tokenizer/token/types/BinaryOperatorToken.java31
-rw-r--r--main/core/tokenizer/token/types/IntegerLiteralToken.java32
-rw-r--r--main/exception/ExceptionManager.java10
-rw-r--r--main/exception/InterpreterException.java33
-rw-r--r--test/MainTest.java3
-rw-r--r--test/core/parser/ParserTest.java21
-rw-r--r--test/core/tokenizer/TokenizerTest.java63
22 files changed, 334 insertions, 446 deletions
diff --git a/main/Main.java b/main/Main.java
index b2d29e9..31bbd7b 100644
--- a/main/Main.java
+++ b/main/Main.java
@@ -1,13 +1,17 @@
package com.jantuomi.interpreter.main;
import com.jantuomi.interpreter.main.core.CommandLineArgumentContainer;
+import com.jantuomi.interpreter.main.core.parser.ASTGenerator;
import com.jantuomi.interpreter.main.core.parser.Parser;
import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
import com.jantuomi.interpreter.main.core.runtime.Interpreter;
import com.jantuomi.interpreter.main.core.tokenizer.Tokenizer;
+import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+import com.jantuomi.interpreter.main.exception.InterpreterException;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
+import java.util.Collections;
import java.util.List;
import java.util.Scanner;
@@ -34,14 +38,22 @@ public class Main {
System.out.print(">> ");
input = scanner.nextLine();
- run(input);
+ try {
+ run(input);
+ } catch (InterpreterException e) {
+ e.printStackTrace();
+ }
}
}
- public static void run(String input) {
+ public static void run(String input) throws InterpreterException {
Tokenizer tokenizer = Tokenizer.getInstance();
- tokenizer.tokenize(input);
- List<ASTNode> nodes = Parser.getInstance().parse(tokenizer.getTokens());
+ List<Token> sequence = tokenizer.tokenize(input);
+
+ Collections.reverse(sequence);
+
+ List<Token> trees = Parser.getInstance().parse(sequence);
+ List<ASTNode> nodes = ASTGenerator.getInstance().generate(trees);
String output = Interpreter.execute(nodes);
System.out.println(output);
}
diff --git a/main/core/parser/ASTGenerator.java b/main/core/parser/ASTGenerator.java
new file mode 100644
index 0000000..e0a3146
--- /dev/null
+++ b/main/core/parser/ASTGenerator.java
@@ -0,0 +1,30 @@
+package com.jantuomi.interpreter.main.core.parser;
+
+import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
+import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by jan on 16.6.2016.
+ */
+public class ASTGenerator {
+ private static final ASTGenerator instance = new ASTGenerator();
+
+ private ASTGenerator() {}
+
+ public static ASTGenerator getInstance() {
+ return instance;
+ }
+
+ public List<ASTNode> generate(List<Token> trees) {
+ List<ASTNode> list = new ArrayList<>();
+
+ for (Token root : trees) {
+ list.add(root.generateNode());
+ }
+
+ return list;
+ }
+}
diff --git a/main/core/parser/Parser.java b/main/core/parser/Parser.java
index 416c3f0..e8b8813 100644
--- a/main/core/parser/Parser.java
+++ b/main/core/parser/Parser.java
@@ -1,14 +1,13 @@
package com.jantuomi.interpreter.main.core.parser;
-import com.jantuomi.interpreter.main.core.parser.ast.*;
+import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
+import com.jantuomi.interpreter.main.core.tokenizer.token.ArgumentInfo;
import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
-import com.jantuomi.interpreter.main.exception.ExceptionManager;
-import com.jantuomi.interpreter.main.exception.InterpreterException;
-import com.jantuomi.interpreter.main.utils.Counter;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Stack;
/**
* Created by jan on 11.6.2016.
@@ -27,226 +26,42 @@ public class Parser {
}
- private Token getTokenAt(Counter c) {
- if (c.getValue() >= tokens.size()) {
- return new Token(Token.Type.NotAToken);
- }
-
- return tokens.get(c.getValue());
- }
-
- private boolean isTooDeep(Counter c) {
- return c.getRecursionDepth() > tokens.size();
- }
+ private Stack<Token> stack;
- public List<ASTNode> parse(List<Token> tokens) {
+ public List<Token> parse(List<Token> tokens) {
this.tokens = tokens;
- this.statementSequence = new ArrayList<>();
+ this.stack = new Stack<>();
- Counter c = new Counter();
- while (c.getValue() < tokens.size()) {
- AssignmentNode asn = expectAssignmentRoutine(c);
- if (asn != null) {
- statementSequence.add(asn);
- continue;
- }
- AdditionNode adn = expectAdditionRoutine(c);
- if (adn != null) {
- statementSequence.add(adn);
+ List<Token> args = new ArrayList<>();
+ List<Token> output = new ArrayList<>();
+ for (Token t : tokens) {
+ if (t.getTokenType() == Token.Type.NewlineToken) {
+// if (stack.size() > 0) {
+// output.add(stack.pop());
+// }
continue;
}
- Token failed = tokens.get(c.getValue());
- ExceptionManager.raise(InterpreterException.Exception.SyntaxError, failed.getLine(),
- Arrays.asList(failed.toString()));
- break;
- }
-
- return statementSequence;
- }
-
- public AssignmentNode expectAssignmentRoutine(Counter c) {
- Counter d = c.clone();
- d.deeper();
-
- if (isTooDeep(d)) {
- return null;
- }
-
- SymbolNode lhs = expectAssignmentLHS(d);
- if (lhs == null) {
- return null;
- }
- boolean isAssign = expectAssignmentAndAdvance(d);
- if (!isAssign) {
- return null;
- }
- ExpressionNode rhs = expectAssignmentRHS(d);
- if (rhs == null) {
- return null;
- }
-
- AssignmentNode an = new AssignmentNode(lhs, rhs);
- d.shallower();
- c.assign(d);
- return an;
- }
-
- private AdditionNode expectAdditionRoutine(Counter c) {
- Counter d = c.clone();
- d.deeper();
-
- if (isTooDeep(d)) {
- return null;
- }
-
- ExpressionNode lhs = expectExpression(d);
- if (lhs == null) {
- return null;
- }
- boolean isAddition = expectAdditionAndAdvance(d);
- if (!isAddition) {
- return null;
- }
- ExpressionNode rhs = expectExpression(d);
- if (rhs == null) {
- return null;
- }
-
- AdditionNode an = new AdditionNode(lhs, rhs);
- d.shallower();
- c.assign(d);
- return an;
- }
-
-// private ExpressionNode expectAdditionLHS(Counter c) {
-// Counter d = c.clone();
-// d.deeper();
-//
-// if (isTooDeep(d)) {
-// return null;
-// }
-//
-// IntegerLiteralNode in = parseIntegerLiteralAndAdvance(d);
-// if (in != null) {
-// d.shallower();
-// c.assign(d);
-// return in;
-// }
-// SymbolNode sn = parseSymbolAndAdvance(d);
-// if (sn != null) {
-// d.shallower();
-// c.assign(d);
-// return sn;
-// }
-//
-// return null;
-// }
-
-
- public SymbolNode expectAssignmentLHS(Counter c) {
- Counter d = c.clone();
- d.deeper();
-
- if (isTooDeep(d)) {
- return null;
- }
-
- SymbolNode sn = parseSymbolAndAdvance(d);
- if (sn != null) {
- d.shallower();
- c.assign(d);
- return sn;
- }
- return null;
- }
-
- public ExpressionNode expectAssignmentRHS(Counter c) {
- Counter d = c.clone();
- d.deeper();
-
- if (isTooDeep(d)) {
- return null;
- }
-
- ExpressionNode en = expectExpression(c);
- if (en != null) {
- d.shallower();
- c.assign(d);
- return en;
- }
- return null;
- }
-
- private ExpressionNode expectExpression(Counter c) {
- Counter d = c.clone();
- d.deeper();
-
- if (isTooDeep(d)) {
- return null;
- }
-
- AdditionNode an = expectAdditionRoutine(d);
- if (an != null) {
- d.shallower();
- c.assign(d);
- return an;
- }
- IntegerLiteralNode in = parseIntegerLiteralAndAdvance(d);
- if (in != null) {
- d.shallower();
- c.assign(d);
- return in;
- }
- SymbolNode sn = parseSymbolAndAdvance(d);
- if (sn != null) {
- d.shallower();
- c.assign(d);
- return sn;
- }
-
- return null;
- }
-
- private boolean expectAdditionAndAdvance(Counter c) {
- if (getTokenAt(c).is(Token.Type.AdditionToken)) {
- c.advance();
- return true;
- } else {
- return false;
- }
- }
-
- private IntegerLiteralNode parseIntegerLiteralAndAdvance(Counter c) {
- if (getTokenAt(c).is(Token.Type.IntegerLiteralToken)) {
- IntegerLiteralNode in = new IntegerLiteralNode(getTokenAt(c));
- c.advance();
- return in;
- } else {
- return null;
- }
- }
-
- public boolean expectAssignmentAndAdvance(Counter c) {
- if (getTokenAt(c).is(Token.Type.AssignmentToken)) {
- c.advance();
- return true;
- } else {
- return false;
+ args.clear();
+ ArgumentInfo argumentInfo = t.getArgumentInfo();
+ if (!argumentInfo.getVarargs()) {
+ for (int i = 0; i < argumentInfo.getCount(); i++) {
+ args.add(stack.pop());
+ }
+ } else {
+ System.err.println("no vararg support yet");
+ }
+ Collections.reverse(args);
+ Token result = t.setArguments(args);
+ stack.push(result);
}
- }
-
- public SymbolNode parseSymbolAndAdvance(Counter c) {
- if (getTokenAt(c).is(Token.Type.SymbolToken)) {
- SymbolNode sn = new SymbolNode(getTokenAt(c));
- c.advance();
- return sn;
- } else {
- return null;
+ while (stack.size() > 0) {
+ output.add(stack.pop());
}
+ return output;
}
- public void printTree(ASTNode e) {
+ public void printTree(Token e) {
System.out.println("### Tree begin ###");
e.print(0);
System.out.println("### Tree end ###");
diff --git a/main/core/parser/ast/ASTNode.java b/main/core/parser/ast/ASTNode.java
index 106ff75..4f840e3 100644
--- a/main/core/parser/ast/ASTNode.java
+++ b/main/core/parser/ast/ASTNode.java
@@ -18,6 +18,10 @@ abstract public class ASTNode {
this.source = token;
}
+ public Token.Type tokenType() {
+ return source.getTokenType();
+ }
+
abstract List<ASTNode> getChildren();
public void print(int indent) {
diff --git a/main/core/parser/ast/AdditionNode.java b/main/core/parser/ast/AdditionNode.java
index f6ebc84..46f67a4 100644
--- a/main/core/parser/ast/AdditionNode.java
+++ b/main/core/parser/ast/AdditionNode.java
@@ -6,31 +6,31 @@ import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
import java.util.Arrays;
import java.util.List;
-
/**
- * Created by jan on 13.6.2016.
+ * Created by jan on 16.6.2016.
*/
-public class AdditionNode extends ExpressionNode {
-
- private ExpressionNode lhs;
- private ExpressionNode rhs;
+public class AdditionNode extends ASTNode {
- public AdditionNode(ExpressionNode lhs, ExpressionNode rhs) {
- super(new Token(Token.Type.AdditionToken));
+ private ASTNode lhs;
+ private ASTNode rhs;
+ public AdditionNode(Token token, ASTNode lhs, ASTNode rhs) {
+ super(token);
this.lhs = lhs;
this.rhs = rhs;
}
@Override
- public List<ASTNode> getChildren() {
- return Arrays.asList(lhs, rhs);
- }
+ public DataContainer evaluate() {
+ DataContainer operand1 = lhs.evaluate();
+ DataContainer operand2 = rhs.evaluate();
+ DataContainer result = operand1.add(operand2);
+ return result;
+
+ }
@Override
- public DataContainer evaluate() {
- DataContainer lhs = this.lhs.evaluate();
- DataContainer rhs = this.rhs.evaluate();
- return lhs.add(rhs);
+ List<ASTNode> getChildren() {
+ return Arrays.asList(lhs, rhs);
}
}
diff --git a/main/core/parser/ast/AssignmentNode.java b/main/core/parser/ast/AssignmentNode.java
deleted file mode 100644
index 8d8f8bc..0000000
--- a/main/core/parser/ast/AssignmentNode.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.jantuomi.interpreter.main.core.parser.ast;
-
-import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer;
-import com.jantuomi.interpreter.main.core.runtime.State;
-import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Created by jan on 11.6.2016.
- */
-public class AssignmentNode extends ASTNode {
-
- private SymbolNode lhs;
- private ExpressionNode rhs;
-
- public AssignmentNode(SymbolNode lhs, ExpressionNode rhs) {
- super(new Token(Token.Type.AssignmentToken));
-
- this.lhs = lhs;
- this.rhs = rhs;
- }
-
- @Override
- public DataContainer evaluate() {
- DataContainer value = rhs.evaluate();
- State.getInstance().setSymbolValue(lhs.getSymbol(), value);
- return value;
- }
-
- @Override
- List<ASTNode> getChildren() {
- return Arrays.asList(lhs, rhs);
- }
-}
diff --git a/main/core/parser/ast/ExpressionNode.java b/main/core/parser/ast/ExpressionNode.java
deleted file mode 100644
index ac1a190..0000000
--- a/main/core/parser/ast/ExpressionNode.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.jantuomi.interpreter.main.core.parser.ast;
-
-import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
-
-/**
- * Created by jan on 11.6.2016.
- */
-abstract public class ExpressionNode extends ASTNode {
- public ExpressionNode(Token token) {
- super(token);
- }
-}
diff --git a/main/core/parser/ast/IntegerLiteralNode.java b/main/core/parser/ast/IntegerLiteralNode.java
index d2fceb1..68b57d7 100644
--- a/main/core/parser/ast/IntegerLiteralNode.java
+++ b/main/core/parser/ast/IntegerLiteralNode.java
@@ -8,24 +8,23 @@ import java.util.Arrays;
import java.util.List;
/**
- * Created by jan on 13.6.2016.
+ * Created by jan on 16.6.2016.
*/
-public class IntegerLiteralNode extends ExpressionNode {
-
- private int data;
+public class IntegerLiteralNode extends ASTNode {
+ private IntegerDataContainer value;
public IntegerLiteralNode(Token token) {
super(token);
- this.data = Integer.parseInt(token.getText());
+ value = new IntegerDataContainer(Integer.parseInt(token.getText()));
}
@Override
- List<ASTNode> getChildren() {
- return Arrays.asList();
+ public DataContainer evaluate() {
+ return value;
}
@Override
- public DataContainer evaluate() {
- return new IntegerDataContainer(data);
+ List<ASTNode> getChildren() {
+ return Arrays.asList();
}
}
diff --git a/main/core/parser/ast/SymbolNode.java b/main/core/parser/ast/SymbolNode.java
deleted file mode 100644
index 1457851..0000000
--- a/main/core/parser/ast/SymbolNode.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.jantuomi.interpreter.main.core.parser.ast;
-
-import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer;
-import com.jantuomi.interpreter.main.core.runtime.State;
-import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Created by jan on 11.6.2016.
- */
-public class SymbolNode extends ExpressionNode {
- private String symbol;
-
- public SymbolNode(Token token) {
- super(token);
-
- this.symbol = token.getText();
- }
-
- @Override
- List<ASTNode> getChildren() {
- return Arrays.asList();
- }
-
- public String getSymbol() {
- return symbol;
- }
-
- @Override
- public DataContainer evaluate() {
- return State.getInstance().getSymbolValue(symbol);
- }
-}
diff --git a/main/core/parser/datatype/DataContainer.java b/main/core/parser/datatype/DataContainer.java
index 45199e2..593855b 100644
--- a/main/core/parser/datatype/DataContainer.java
+++ b/main/core/parser/datatype/DataContainer.java
@@ -1,10 +1,18 @@
package com.jantuomi.interpreter.main.core.parser.datatype;
-
/**
* Created by jan on 11.6.2016.
*/
abstract public class DataContainer<T> {
+
+ public enum Type {
+ Integer
+ }
+
+ private Type type;
+
+ private T data;
+
public T getData() {
return data;
}
@@ -13,10 +21,8 @@ abstract public class DataContainer<T> {
this.data = data;
}
- private T data;
-
@Override
abstract public String toString();
- public abstract DataContainer add(DataContainer rhs);
+ abstract public DataContainer<T> add(DataContainer<T> other);
}
diff --git a/main/core/parser/datatype/IntegerDataContainer.java b/main/core/parser/datatype/IntegerDataContainer.java
index 8566a1c..b5fdac3 100644
--- a/main/core/parser/datatype/IntegerDataContainer.java
+++ b/main/core/parser/datatype/IntegerDataContainer.java
@@ -1,36 +1,25 @@
package com.jantuomi.interpreter.main.core.parser.datatype;
-
-import com.jantuomi.interpreter.main.exception.ExceptionManager;
-import com.jantuomi.interpreter.main.exception.InterpreterException;
-
-import java.util.Arrays;
-
/**
- * Created by jan on 11.6.2016.
+ * Created by jan on 16.6.2016.
*/
public class IntegerDataContainer extends DataContainer<Integer> {
- public IntegerDataContainer(Integer data) {
- this.setData(data);
+
+ private int value;
+
+ public IntegerDataContainer(int value) {
+ this.value = value;
}
@Override
public String toString() {
- return getData().toString();
+ return Integer.toString(value);
}
@Override
- public DataContainer add(DataContainer rhs) {
- if (rhs instanceof IntegerDataContainer) {
- return new IntegerDataContainer(
- getData() + ((IntegerDataContainer) rhs).getData()
- );
- }
- else {
- ExceptionManager.raise(InterpreterException.Exception.TypeError, -1,
- Arrays.asList(this.getClass().toString(), rhs.getClass().toString()));
-
- return null;
- }
+ public DataContainer<Integer> add(DataContainer<Integer> other) {
+ return new IntegerDataContainer(
+ this.value + ((IntegerDataContainer) other).value
+ );
}
}
diff --git a/main/core/tokenizer/Tokenizer.java b/main/core/tokenizer/Tokenizer.java
index c04db22..7e88a43 100644
--- a/main/core/tokenizer/Tokenizer.java
+++ b/main/core/tokenizer/Tokenizer.java
@@ -57,7 +57,7 @@ public class Tokenizer {
erroneousTokenTypes.add(Token.Type.NotAToken);
}
- public List<Token> tokenize(String string) {
+ public List<Token> tokenize(String string) throws InterpreterException {
sourceString = string;
tokens.clear();
int line = 1;
@@ -79,7 +79,7 @@ public class Tokenizer {
}
if (erroneousTokenTypes.contains(token.getTokenType())) {
- ExceptionManager.raise(InterpreterException.Exception.IllegalTokenError, line, Arrays.asList(token.getText()));
+ ExceptionManager.raise(InterpreterException.ExceptionType.IllegalTokenError, line, Arrays.asList(token.getText()));
}
String tokenRawText = token.getRawText();
diff --git a/main/core/tokenizer/token/ArgumentInfo.java b/main/core/tokenizer/token/ArgumentInfo.java
new file mode 100644
index 0000000..a9c3d90
--- /dev/null
+++ b/main/core/tokenizer/token/ArgumentInfo.java
@@ -0,0 +1,28 @@
+package com.jantuomi.interpreter.main.core.tokenizer.token;
+
+/**
+ * Created by jan on 15.6.2016.
+ */
+public class ArgumentInfo {
+ private int count = 0;
+ private boolean isVarargs = false;
+ public ArgumentInfo(int count) {
+ this.count = count;
+ }
+
+ public ArgumentInfo() {
+
+ }
+
+ public void setVariable(boolean value) {
+ this.isVarargs = value;
+ }
+
+ public boolean getVarargs() {
+ return isVarargs;
+ }
+
+ public int getCount() {
+ return count;
+ }
+}
diff --git a/main/core/tokenizer/token/Token.java b/main/core/tokenizer/token/Token.java
index 99ae913..0d4395e 100644
--- a/main/core/tokenizer/token/Token.java
+++ b/main/core/tokenizer/token/Token.java
@@ -1,8 +1,12 @@
package com.jantuomi.interpreter.main.core.tokenizer.token;
+import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
+import com.jantuomi.interpreter.main.core.tokenizer.token.types.AdditionToken;
+import com.jantuomi.interpreter.main.core.tokenizer.token.types.IntegerLiteralToken;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -10,7 +14,19 @@ import java.util.regex.Pattern;
/**
* Created by jan on 10.6.2016.
*/
-public class Token {
+abstract public class Token {
+
+ public void print(int indent) {
+ for (int i = 0; i < indent; i++) {
+ System.out.print("\t");
+ }
+ System.out.println(toString());
+ for (Token child : getChildren()) {
+ child.print(indent + 1);
+ }
+ }
+
+ abstract public ASTNode generateNode();
/* Token types, ordered by precedence */
public enum Type {
@@ -40,6 +56,10 @@ public class Token {
NotAToken
}
+ abstract public Token setArguments(List<Token> args);
+
+ abstract public List<Token> getChildren();
+
public boolean is(Type type) {
return getTokenType() == type;
}
@@ -120,12 +140,45 @@ public class Token {
String text = matcher.group(1);
String rawText = matcher.group(0);
- return new Token(type, text, rawText);
+ switch (type) {
+ case IntegerLiteralToken:
+ return new IntegerLiteralToken(text);
+ case AdditionToken:
+ return new AdditionToken();
+ default:
+ return null;
+ }
}
return null;
}
+ public ArgumentInfo getArgumentInfo() {
+ switch (getTokenType()) {
+
+ case FunctionDefineToken:
+ ArgumentInfo ai = new ArgumentInfo();
+ ai.setVariable(true);
+ return ai;
+ case AdditionToken:
+ case SubtractionToken:
+ case DivisionToken:
+ case MultiplicationToken:
+ case AssignmentToken:
+ case LessThanToken:
+ case GreaterThanToken:
+ case LessOrEqualThanToken:
+ case GreaterOrEqualThanToken:
+ case EqualsToken:
+ case NotEqualsToken:
+ return new ArgumentInfo(2);
+ case DeclarationToken:
+ return new ArgumentInfo(1);
+ default:
+ return new ArgumentInfo(0);
+ }
+ }
+
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
diff --git a/main/core/tokenizer/token/types/AdditionToken.java b/main/core/tokenizer/token/types/AdditionToken.java
new file mode 100644
index 0000000..2d77b46
--- /dev/null
+++ b/main/core/tokenizer/token/types/AdditionToken.java
@@ -0,0 +1,22 @@
+package com.jantuomi.interpreter.main.core.tokenizer.token.types;
+
+import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
+import com.jantuomi.interpreter.main.core.parser.ast.AdditionNode;
+
+/**
+ * Created by jan on 15.6.2016.
+ */
+public class AdditionToken extends BinaryOperatorToken {
+ public AdditionToken() {
+ super(Type.AdditionToken);
+ }
+
+ @Override
+ public ASTNode generateNode() {
+ return new AdditionNode(this,
+ lhs.generateNode(),
+ rhs.generateNode()
+ );
+
+ }
+}
diff --git a/main/core/tokenizer/token/types/BinaryOperatorToken.java b/main/core/tokenizer/token/types/BinaryOperatorToken.java
new file mode 100644
index 0000000..3998bb9
--- /dev/null
+++ b/main/core/tokenizer/token/types/BinaryOperatorToken.java
@@ -0,0 +1,31 @@
+package com.jantuomi.interpreter.main.core.tokenizer.token.types;
+
+import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by jan on 15.6.2016.
+ */
+abstract public class BinaryOperatorToken extends Token {
+ protected Token lhs;
+ protected Token rhs;
+
+ public BinaryOperatorToken(Type type) {
+ super(type);
+ }
+
+ @Override
+ public Token setArguments(List<Token> args) {
+ lhs = args.get(0);
+ rhs = args.get(1);
+ return this;
+ }
+
+ @Override
+ public List<Token> getChildren() {
+ return Arrays.asList(lhs, rhs);
+
+ }
+}
diff --git a/main/core/tokenizer/token/types/IntegerLiteralToken.java b/main/core/tokenizer/token/types/IntegerLiteralToken.java
new file mode 100644
index 0000000..cdb4fde
--- /dev/null
+++ b/main/core/tokenizer/token/types/IntegerLiteralToken.java
@@ -0,0 +1,32 @@
+package com.jantuomi.interpreter.main.core.tokenizer.token.types;
+
+import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
+import com.jantuomi.interpreter.main.core.parser.ast.IntegerLiteralNode;
+import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by jan on 15.6.2016.
+ */
+public class IntegerLiteralToken extends Token{
+ public IntegerLiteralToken(String text) {
+ super(Type.IntegerLiteralToken, text);
+ }
+
+ @Override
+ public ASTNode generateNode() {
+ return new IntegerLiteralNode(this);
+ }
+
+ @Override
+ public Token setArguments(List<Token> args) {
+ return this;
+ }
+
+ @Override
+ public List<Token> getChildren() {
+ return Arrays.asList();
+ }
+}
diff --git a/main/exception/ExceptionManager.java b/main/exception/ExceptionManager.java
index 0ceb25b..dbb59d3 100644
--- a/main/exception/ExceptionManager.java
+++ b/main/exception/ExceptionManager.java
@@ -16,13 +16,9 @@ public class ExceptionManager {
return instance;
}
- public static void raise(InterpreterException.Exception ex, int line, List<String> args) {
- InterpreterException e = new InterpreterException(ex);
- String output = e.what();
- for (String arg : args) {
- output = String.format(output, arg);
- }
- System.err.println(String.format("[%s] line: %d %s", ex.toString(), line, output));
+ public static void raise(InterpreterException.ExceptionType ex, int line, List<String> args) throws InterpreterException {
+ InterpreterException e = new InterpreterException(ex, line, args);
+ throw e;
}
diff --git a/main/exception/InterpreterException.java b/main/exception/InterpreterException.java
index 6ba5a7b..26e39fd 100644
--- a/main/exception/InterpreterException.java
+++ b/main/exception/InterpreterException.java
@@ -2,36 +2,45 @@ package com.jantuomi.interpreter.main.exception;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
* Created by jan on 12.6.2016.
*/
-public class InterpreterException {
+public class InterpreterException extends Exception {
- public enum Exception {
+ public enum ExceptionType {
IllegalTokenError,
UnknownOperatorError,
SyntaxError,
TypeError
}
- public static Map<Exception, String> errorTexts = new HashMap<>();
+ public static Map<ExceptionType, String> errorTexts = new HashMap<>();
static {
- errorTexts.put(Exception.IllegalTokenError, "Illegal token %s found.");
- errorTexts.put(Exception.UnknownOperatorError, "Unexpected operator %s found.");
- errorTexts.put(Exception.SyntaxError, "Unexpected %s.");
- errorTexts.put(Exception.TypeError, "Incompatible types %s and %s.");
+ errorTexts.put(ExceptionType.IllegalTokenError, "Illegal token %s found.");
+ errorTexts.put(ExceptionType.UnknownOperatorError, "Unexpected operator %s found.");
+ errorTexts.put(ExceptionType.SyntaxError, "Unexpected %s.");
+ errorTexts.put(ExceptionType.TypeError, "Incompatible types %s and %s.");
}
- private Exception exception;
+ private ExceptionType exceptionType;
- public InterpreterException(Exception e) {
- exception = e;
+ public InterpreterException(ExceptionType exceptionType, int line, List<String> args) {
+ super(formatMessage(exceptionType.toString() + what(exceptionType), line, args));
+ this.exceptionType = exceptionType;
}
- public String what() {
- return errorTexts.get(exception);
+ private static String formatMessage(String message, int line, List<String> args) {
+ for (String arg : args) {
+ message = String.format(message, arg);
+ }
+ return String.format("line %d: ", line) + message;
+ }
+
+ public static String what(ExceptionType type) {
+ return errorTexts.get(type);
}
}
diff --git a/test/MainTest.java b/test/MainTest.java
index 256998d..d6171a5 100644
--- a/test/MainTest.java
+++ b/test/MainTest.java
@@ -1,6 +1,7 @@
package com.jantuomi.interpreter.test;
import com.jantuomi.interpreter.main.Main;
+import com.jantuomi.interpreter.main.exception.InterpreterException;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@@ -23,7 +24,7 @@ public class MainTest {
}
@Test
- public void testWholeProcedure() {
+ public void testWholeProcedure() throws InterpreterException {
String input = "x <- 1 + 2";
Main.run(input);
}
diff --git a/test/core/parser/ParserTest.java b/test/core/parser/ParserTest.java
index 913896e..9dc51e3 100644
--- a/test/core/parser/ParserTest.java
+++ b/test/core/parser/ParserTest.java
@@ -1,8 +1,9 @@
package com.jantuomi.interpreter.test.core.parser;
import com.jantuomi.interpreter.main.core.parser.Parser;
-import com.jantuomi.interpreter.main.core.parser.ast.ASTNode;
import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+import com.jantuomi.interpreter.main.core.tokenizer.token.types.AdditionToken;
+import com.jantuomi.interpreter.main.core.tokenizer.token.types.IntegerLiteralToken;
import org.junit.Test;
import java.util.Arrays;
@@ -14,21 +15,17 @@ import java.util.List;
public class ParserTest {
@Test
- public void parseAssignment() throws Exception {
+ public void testParseAddition() throws Exception {
List<Token> tokens = Arrays.asList(
- new Token(Token.Type.SymbolToken, "x"),
- new Token(Token.Type.AssignmentToken),
- new Token(Token.Type.SymbolToken, "y"),
- new Token(Token.Type.AdditionToken),
- new Token(Token.Type.SymbolToken, "x"),
- new Token(Token.Type.AdditionToken),
- new Token(Token.Type.IntegerLiteralToken, "1")
+ new IntegerLiteralToken("1"),
+ new IntegerLiteralToken("2"),
+ new AdditionToken()
);
Parser parser = Parser.getInstance();
- List<ASTNode> sequence = parser.parse(tokens);
- for (ASTNode e : sequence) {
- parser.printTree(e);
+ List<Token> sequence = parser.parse(tokens);
+ for (Token t : sequence) {
+ parser.printTree(t);
}
}
} \ No newline at end of file
diff --git a/test/core/tokenizer/TokenizerTest.java b/test/core/tokenizer/TokenizerTest.java
index 7b29020..4274a93 100644
--- a/test/core/tokenizer/TokenizerTest.java
+++ b/test/core/tokenizer/TokenizerTest.java
@@ -2,6 +2,8 @@ package com.jantuomi.interpreter.test.core.tokenizer;
import com.jantuomi.interpreter.main.core.tokenizer.Tokenizer;
import com.jantuomi.interpreter.main.core.tokenizer.token.Token;
+import com.jantuomi.interpreter.main.core.tokenizer.token.types.IntegerLiteralToken;
+import com.jantuomi.interpreter.main.exception.InterpreterException;
import org.junit.Test;
import java.util.List;
@@ -14,67 +16,12 @@ import static org.junit.Assert.assertTrue;
public class TokenizerTest {
@Test
- public void testTokenizeCommentAndSymbol() {
- String testString = "\"string literal\"\n/*comment*/\n1 2\nsymbol_Test3";
+ public void testAddition() throws InterpreterException {
+ String testString = "1 2 +";
List<Token> list = Tokenizer.getInstance().tokenize(testString);
System.out.println(String.format("test string:\n%s", testString));
Tokenizer.printTokens(list);
- assertTrue(list.contains(new Token(Token.Type.CommentToken, "comment")));
- }
-
- @Test
- public void testTokenizeMultilineString() {
- String testString = "\"this is a\nmultiline\nstring\"";
- List<Token> list = Tokenizer.getInstance().tokenize(testString);
-
- System.out.println(String.format("test string:\n%s", testString));
- Tokenizer.printTokens(list);
- assertTrue(list.contains(new Token(Token.Type.StringLiteralToken, "this is a\nmultiline\nstring")));
- }
-
- @Test
- public void testTokenizeMath() {
- String testString = "x <- (1 + 2) / 3 * 4";
- List<Token> list = Tokenizer.getInstance().tokenize(testString);
-
- System.out.println(String.format("test string:\n%s", testString));
- Tokenizer.printTokens(list);
- for (Token t : list) {
- if (t.isSameType(new Token(Token.Type.AssignmentToken))) {
- return;
- }
- }
- assertTrue("No assignment token found!" == null);
- }
-
- @Test
- public void testTokenizeDeclAndAssign() {
- String testString = "decl x\nx <- 1 + 2";
- List<Token> list = Tokenizer.getInstance().tokenize(testString);
-
- System.out.println(String.format("test string:\n%s", testString));
- Tokenizer.printTokens(list);
- for (Token t : list) {
- if (t.isSameType(new Token(Token.Type.DeclarationToken))) {
- return;
- }
- }
- assertTrue("No declaration token found!" == null);
- }
-
- @Test
- public void testTokenizeFunction() {
- String testString = "func name(arg)\nx <- 1\nend";
- List<Token> list = Tokenizer.getInstance().tokenize(testString);
-
- System.out.println(String.format("test string:\n%s", testString));
- Tokenizer.printTokens(list);
- for (Token t : list) {
- if (t.isSameType(new Token(Token.Type.FunctionDefineToken))) {
- return;
- }
- }
- assertTrue("No function declaration token found!" == null);
+ assertTrue(list.contains(new IntegerLiteralToken("2")));
}
} \ No newline at end of file