aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorjantuomi <jans.tuomi@gmail.com>2016-08-29 14:25:24 +0300
committerjantuomi <jans.tuomi@gmail.com>2016-08-29 14:25:24 +0300
commit5ccfb2931c9ed97798857e97d521ce31ad104c65 (patch)
tree1e5e2d5a8a9fdbb69c28ff96c10d77aa34159ec8 /src/main
parentb4469f872286f8563ec805ef32798bb9608c29e4 (diff)
Implement object definition with 'obj' keyword
Diffstat (limited to 'src/main')
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/Parser.java13
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/AssignmentNode.java2
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/DeclareAssignNode.java4
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/NullaryOperatorNode.java22
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/ObjectDefinitionNode.java42
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java2
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/SymbolNode.java2
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/ast/VariableDeclareNode.java2
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/tokenizer/Tokenizer.java1
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/Token.java1
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/TokenFactory.java2
-rw-r--r--src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/types/ObjectDefinitionToken.java56
-rw-r--r--src/main/com/jantuomi/tunkki/core/runtime/Function.java16
-rw-r--r--src/main/com/jantuomi/tunkki/core/runtime/State.java25
-rw-r--r--src/main/com/jantuomi/tunkki/core/runtime/UserDefinedFunction.java9
-rw-r--r--src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java5
16 files changed, 171 insertions, 33 deletions
diff --git a/src/main/com/jantuomi/tunkki/core/parser/Parser.java b/src/main/com/jantuomi/tunkki/core/parser/Parser.java
index 9cb183f..ebd8eac 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/Parser.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/Parser.java
@@ -17,30 +17,22 @@ import java.util.Stack;
public class Parser {
private static final Parser instance = new Parser();
- private List<Token> tokens;
- private List<ASTNode> statementSequence;
-
public static Parser getInstance() {
return instance;
}
- private Parser() {
-
- }
+ private Parser() {}
private Stack<Token> stack;
public List<Token> parse(List<Token> tokens) throws TunkkiError {
- this.tokens = tokens;
this.stack = new Stack<>();
List<Token> args;
List<Token> output = new ArrayList<>();
for (Token t : tokens) {
+ /* Skip newline tokens */
if (t.getTokenType() == Token.Type.NewlineToken) {
-// if (stack.size() > 0) {
-// output.add(stack.pop());
-// }
continue;
}
@@ -88,6 +80,7 @@ public class Parser {
stack.push(result);
}
+ /* When the token list is empty, pop all remaining tokens from the stack */
while (stack.size() > 0) {
output.add(stack.pop());
}
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/AssignmentNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/AssignmentNode.java
index 38bb269..95ab77c 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/ast/AssignmentNode.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/AssignmentNode.java
@@ -20,7 +20,7 @@ public class AssignmentNode extends BinaryOperatorNode {
public Datatype evaluate() throws TunkkiError {
SymbolNode symbol = (SymbolNode) lhs;
Datatype rValue = rhs.evaluate();
- State.getInstance().setSymbolValueToScope(
+ State.getGlobalState().setSymbolValueToScope(
symbol.getName(),
rValue
);
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/DeclareAssignNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/DeclareAssignNode.java
index 206bbd9..1d2d31a 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/ast/DeclareAssignNode.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/DeclareAssignNode.java
@@ -27,10 +27,10 @@ public class DeclareAssignNode extends BinaryOperatorNode {
throw new ExpectedDifferentTokenTunkkiError(getLine(), getText());
}
- State.getInstance().addSymbolToScope(var.getName());
+ State.getGlobalState().addSymbolToScope(var.getName());
Datatype rValue = rhs.evaluate();
- State.getInstance().setSymbolValueToScope(
+ State.getGlobalState().setSymbolValueToScope(
var.getName(),
rValue
);
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/NullaryOperatorNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/NullaryOperatorNode.java
new file mode 100644
index 0000000..d2d25b9
--- /dev/null
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/NullaryOperatorNode.java
@@ -0,0 +1,22 @@
+package com.jantuomi.tunkki.core.parser.ast;
+
+import com.jantuomi.tunkki.core.parser.datatype.Datatype;
+import com.jantuomi.tunkki.core.parser.tokenizer.token.Token;
+import com.jantuomi.tunkki.exception.types.TunkkiError;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by jan on 8.8.2016.
+ */
+abstract public class NullaryOperatorNode extends ASTNode {
+ public NullaryOperatorNode(Token token) {
+ super(token);
+ }
+
+ @Override
+ List<ASTNode> getChildren() {
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectDefinitionNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectDefinitionNode.java
new file mode 100644
index 0000000..2a9a19d
--- /dev/null
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectDefinitionNode.java
@@ -0,0 +1,42 @@
+package com.jantuomi.tunkki.core.parser.ast;
+
+import com.jantuomi.tunkki.core.parser.datatype.CallableDatatype;
+import com.jantuomi.tunkki.core.parser.datatype.Datatype;
+import com.jantuomi.tunkki.core.parser.datatype.ObjectDatatype;
+import com.jantuomi.tunkki.core.parser.tokenizer.token.Token;
+import com.jantuomi.tunkki.core.runtime.Function;
+import com.jantuomi.tunkki.core.runtime.State;
+import com.jantuomi.tunkki.exception.types.TunkkiError;
+
+import java.util.Collections;
+
+/**
+ * Created by jan on 8.8.2016.
+ */
+public class ObjectDefinitionNode extends NullaryOperatorNode {
+ public ObjectDefinitionNode(Token token, String name, CallableDatatype constructor) {
+ super(token);
+ this.name = name;
+ this.constructor = constructor;
+ }
+
+ private String name;
+ private CallableDatatype constructor;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public Datatype evaluate() throws TunkkiError {
+ ObjectDatatype obj = new ObjectDatatype();
+
+ State state = new State();
+ constructor.call(Collections.emptyList());
+ Function func = constructor.getData();
+ func.setState(state);
+
+ obj.setData(func.getState().getGlobalScope());
+ return obj;
+ }
+}
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java
index c2eb637..c982db2 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java
@@ -21,7 +21,7 @@ public class ObjectMemberNode extends UnaryOperatorNode {
public Datatype evaluate() throws TunkkiError {
Datatype d;
try {
- d = State.getInstance().resolveSymbol(getText());
+ d = State.getGlobalState().resolveSymbol(getText());
} catch (TunkkiError ex) {
ex.setLine(getLine());
throw ex;
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/SymbolNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/SymbolNode.java
index 7fb5e64..21d37f5 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/ast/SymbolNode.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/SymbolNode.java
@@ -44,7 +44,7 @@ public class SymbolNode extends ASTNode {
Datatype returnValue;
try {
- returnValue = State.getInstance().resolveSymbol(name);
+ returnValue = State.getGlobalState().resolveSymbol(name);
}
/* If a TunkkiError is caught, pass it on with line information */
diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/VariableDeclareNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/VariableDeclareNode.java
index b53438a..38590f0 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/ast/VariableDeclareNode.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/ast/VariableDeclareNode.java
@@ -21,7 +21,7 @@ public class VariableDeclareNode extends ASTNode {
@Override
public Datatype evaluate() {
- State.getInstance().addSymbolToScope(variable.getName());
+ State.getGlobalState().addSymbolToScope(variable.getName());
return new StringDatatype(variable.getName());
}
diff --git a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/Tokenizer.java b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/Tokenizer.java
index 2449e0a..9515abf 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/Tokenizer.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/Tokenizer.java
@@ -61,6 +61,7 @@ public class Tokenizer {
tokenRegexes.put(Token.Type.NegationToken, "^(not)\\b");
tokenRegexes.put(Token.Type.DeclarationToken, "^(decl)\\b");
+ tokenRegexes.put(Token.Type.ObjectDefinitionToken, "^(obj)\\b");
tokenRegexes.put(Token.Type.CallToken, "^([a-öA-Ö]+\\w*)\\?[\\s|\\!]");
tokenRegexes.put(Token.Type.ObjectMemberToken, "^([a-öA-Ö]+)\\:");
tokenRegexes.put(Token.Type.SymbolToken, "^([a-öA-Ö]+\\w*)\\b");
diff --git a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/Token.java b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/Token.java
index d53ea68..21ccbaf 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/Token.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/Token.java
@@ -70,6 +70,7 @@ abstract public class Token {
DeclareAssignToken,
ObjectMemberToken,
+ ObjectDefinitionToken,
NotAToken
}
diff --git a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/TokenFactory.java b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/TokenFactory.java
index 588af63..326958d 100644
--- a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/TokenFactory.java
+++ b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/TokenFactory.java
@@ -56,6 +56,8 @@ public class TokenFactory {
return new SymbolToken(text);
case CallToken:
return new CallToken(text, rawText);
+ case ObjectDefinitionToken:
+ return new ObjectDefinitionToken();
case BlockEndToken:
return new BlockEndToken();
case ObjectMemberToken:
diff --git a/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/types/ObjectDefinitionToken.java b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/types/ObjectDefinitionToken.java
new file mode 100644
index 0000000..8215c26
--- /dev/null
+++ b/src/main/com/jantuomi/tunkki/core/parser/tokenizer/token/types/ObjectDefinitionToken.java
@@ -0,0 +1,56 @@
+package com.jantuomi.tunkki.core.parser.tokenizer.token.types;
+
+import com.jantuomi.tunkki.core.parser.ast.ASTNode;
+import com.jantuomi.tunkki.core.parser.ast.FunctionDefineNode;
+import com.jantuomi.tunkki.core.parser.ast.ObjectDefinitionNode;
+import com.jantuomi.tunkki.core.parser.ast.SymbolNode;
+import com.jantuomi.tunkki.core.parser.datatype.CallableDatatype;
+import com.jantuomi.tunkki.core.parser.tokenizer.token.Token;
+import com.jantuomi.tunkki.exception.types.ExpectedDifferentTokenTunkkiError;
+import com.jantuomi.tunkki.exception.types.TunkkiError;
+
+/**
+ * Created by jan on 8.8.2016.
+ */
+public class ObjectDefinitionToken extends VarargOperatorToken {
+ public ObjectDefinitionToken() {
+ super(Type.ObjectDefinitionToken, "obj");
+ }
+
+ @Override
+ public ASTNode generateNode() throws TunkkiError {
+ if (args.size() < 2 || args.size() > 3) {
+ throw new ExpectedDifferentTokenTunkkiError(getLine(), getText());
+ }
+
+ Token arg1 = args.get(0);
+ if (!(arg1 instanceof SymbolToken)) {
+ throw new ExpectedDifferentTokenTunkkiError(getLine(), getText());
+ }
+
+ Token funcArg;
+ if (args.size() == 2) {
+ funcArg = args.get(1);
+ } else {
+ funcArg = args.get(2);
+ }
+
+ if (!(funcArg instanceof FunctionDefineToken)) {
+ throw new ExpectedDifferentTokenTunkkiError(getLine(), getText());
+ }
+
+ SymbolNode symbol = (SymbolNode) arg1.generateNode();
+ String name = symbol.getName();
+
+ FunctionDefineNode constructor = (FunctionDefineNode) funcArg.generateNode();
+ CallableDatatype constructorCallable = (CallableDatatype) constructor.evaluate();
+ ObjectDefinitionNode node = new ObjectDefinitionNode(this, name, constructorCallable);
+ node.setName(name);
+ return node;
+ }
+
+ @Override
+ public Type getTerminatorTokenType() {
+ return Type.FunctionDefineToken;
+ }
+}
diff --git a/src/main/com/jantuomi/tunkki/core/runtime/Function.java b/src/main/com/jantuomi/tunkki/core/runtime/Function.java
index b6eab89..2c60bd0 100644
--- a/src/main/com/jantuomi/tunkki/core/runtime/Function.java
+++ b/src/main/com/jantuomi/tunkki/core/runtime/Function.java
@@ -15,13 +15,27 @@ abstract public class Function {
protected List<String> argumentNames;
protected BlockBodyNode body;
+ private State state = null;
+
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ public State getState() {
+ if (this.state != null) {
+ return this.state;
+ } else {
+ return State.getGlobalState();
+ }
+ }
+
public Function(List<String> argumentNames, BlockBodyNode body) {
this.argumentNames = argumentNames;
this.body = body;
}
public Datatype evaluate(List<Datatype> params) throws TunkkiError {
- State.getInstance().createScope();
+ Scope scope = getState().createScope();
if (!checkArgumentListValidity(params)) {
throw new FunctionArgumentTunkkiError(-1, Datatype.toString(params));
diff --git a/src/main/com/jantuomi/tunkki/core/runtime/State.java b/src/main/com/jantuomi/tunkki/core/runtime/State.java
index 2cbd94a..3bf214c 100644
--- a/src/main/com/jantuomi/tunkki/core/runtime/State.java
+++ b/src/main/com/jantuomi/tunkki/core/runtime/State.java
@@ -6,8 +6,6 @@ import com.jantuomi.tunkki.core.parser.datatype.NadaDatatype;
import com.jantuomi.tunkki.core.runtime.builtins.BuiltinManager;
import com.jantuomi.tunkki.exception.types.TunkkiError;
-import java.util.Arrays;
-import java.util.List;
import java.util.Map;
import java.util.Stack;
@@ -15,15 +13,24 @@ import java.util.Stack;
* Created by jan on 11.6.2016.
*/
public class State {
- private static final State instance = new State();
+ private static final State globalState = new State();
- public static State getInstance() {
- return instance;
+ public static State getGlobalState() {
+ return globalState;
}
private Stack<Scope> scopes = new Stack<>();
- private State() {
+ static {
+ globalState.replaceBaseScopeWithGlobal();
+ }
+
+ public State() {
+ Scope baseScope = new Scope();
+ scopes.push(baseScope);
+ }
+
+ public void replaceBaseScopeWithGlobal() {
/* Push global scope onto the stack */
Scope globalScope = new Scope();
@@ -37,7 +44,7 @@ public class State {
globalScope.addVariable("nada");
globalScope.setVariableValue("nada", new NadaDatatype());
- scopes.push(globalScope);
+ scopes.set(0, globalScope);
}
public Datatype resolveSymbol(String symbol) throws TunkkiError {
@@ -55,6 +62,10 @@ public class State {
return scope;
}
+ public Scope getGlobalScope() {
+ return scopes.get(0);
+ }
+
public void addSymbolToScope(String symbol) {
scopes.peek().addVariable(symbol);
}
diff --git a/src/main/com/jantuomi/tunkki/core/runtime/UserDefinedFunction.java b/src/main/com/jantuomi/tunkki/core/runtime/UserDefinedFunction.java
index 2e994a8..c094d91 100644
--- a/src/main/com/jantuomi/tunkki/core/runtime/UserDefinedFunction.java
+++ b/src/main/com/jantuomi/tunkki/core/runtime/UserDefinedFunction.java
@@ -1,9 +1,7 @@
package com.jantuomi.tunkki.core.runtime;
import com.jantuomi.tunkki.core.parser.ast.BlockBodyNode;
-import com.jantuomi.tunkki.core.parser.datatype.CallableDatatype;
import com.jantuomi.tunkki.core.parser.datatype.Datatype;
-import com.jantuomi.tunkki.exception.types.FunctionArgumentTunkkiError;
import com.jantuomi.tunkki.exception.types.TunkkiError;
import java.util.*;
@@ -13,7 +11,6 @@ import java.util.*;
*/
public class UserDefinedFunction extends Function {
-
public UserDefinedFunction(List<String> argumentNames, BlockBodyNode body) {
super(argumentNames, body);
}
@@ -24,12 +21,12 @@ public class UserDefinedFunction extends Function {
super.evaluate(params);
for (int i = 0; i < argumentNames.size(); i++) {
- State.getInstance().addSymbolToScope(argumentNames.get(i));
- State.getInstance().setSymbolValueToScope(argumentNames.get(i), params.get(i));
+ State.getGlobalState().addSymbolToScope(argumentNames.get(i));
+ State.getGlobalState().setSymbolValueToScope(argumentNames.get(i), params.get(i));
}
Datatype returnValue = body.evaluate();
- State.getInstance().popScope();
+ State.getGlobalState().popScope();
return returnValue;
}
diff --git a/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java b/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java
index b3e1a9a..d2c6f31 100644
--- a/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java
+++ b/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java
@@ -6,7 +6,6 @@ import com.jantuomi.tunkki.core.CommandLineArgumentContainer;
import com.jantuomi.tunkki.core.parser.datatype.*;
import com.jantuomi.tunkki.core.runtime.State;
import com.jantuomi.tunkki.core.runtime.builtins.BuiltinManager;
-import com.jantuomi.tunkki.exception.ExceptionManager;
import com.jantuomi.tunkki.exception.types.*;
import java.util.Arrays;
@@ -39,8 +38,8 @@ public class IncludeBuiltinFunction extends BuiltinFunction {
for (String funcName : funcs.keySet()) {
namespace.getData().addAndSetVariable(funcName, funcs.get(funcName));
}
- State.getInstance().addSymbolToScope(filename);
- State.getInstance().setSymbolValueToScope(filename, namespace);
+ State.getGlobalState().addSymbolToScope(filename);
+ State.getGlobalState().setSymbolValueToScope(filename, namespace);
}
else {