diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2016-06-16 20:21:25 +0300 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2016-07-26 19:47:02 +0300 |
| commit | d35a37a449d31e6f4b43b937abf7b0e1fc497828 (patch) | |
| tree | 8d65ac1068dbf09de480e7cae0fb39ec21d330ec | |
| parent | f441022881945db08846e09a8f3bfee2f8cfa95d (diff) | |
Grammar now uses reverse polish notation
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 |
