summaryrefslogtreecommitdiff
path: root/dice-lang/src
diff options
context:
space:
mode:
Diffstat (limited to 'dice-lang/src')
-rw-r--r--dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java25
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Evaluator.java24
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Parser.java12
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Shunter.java200
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Token.java37
5 files changed, 179 insertions, 119 deletions
diff --git a/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java b/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java
index d90ce9d..220fd3f 100644
--- a/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java
+++ b/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java
@@ -100,17 +100,18 @@ public class DiceLangEngine {
litTokens = new FunctionalMap<>();
- litTokens.put("+", ADD);
- litTokens.put("-", SUBTRACT);
- litTokens.put("*", MULTIPLY);
- litTokens.put("/", DIVIDE);
- litTokens.put("//", IDIVIDE);
- litTokens.put("dg", DICEGROUP);
- litTokens.put("dc", DICECONCAT);
- litTokens.put("dl", DICELIST);
- litTokens.put("=>", LET);
- litTokens.put(":=", BIND);
- litTokens.put(",", GROUPSEP);
+ litTokens.put("+", ADD);
+ litTokens.put("-", SUBTRACT);
+ litTokens.put("*", MULTIPLY);
+ litTokens.put("/", DIVIDE);
+ litTokens.put("//", IDIVIDE);
+ litTokens.put("dg", DICEGROUP);
+ litTokens.put("dc", DICECONCAT);
+ litTokens.put("dl", DICELIST);
+ litTokens.put("=>", LET);
+ litTokens.put(":=", BIND);
+ litTokens.put(",", GROUPSEP);
+ litTokens.put("crc", COERCE);
nextLiteral = 1;
@@ -378,6 +379,8 @@ public class DiceLangEngine {
IList<Token> readyTokens = shuntedTokens.flatMap(tk -> {
if(tk.type == Token.Type.TOKGROUP) {
return tk.tokenValues;
+ } else if(tk.type == Token.Type.TAGOP || tk.type == Token.Type.TAGOPR) {
+ return tk.tokenValues;
} else {
return new FunctionalList<>(tk);
}
diff --git a/dice-lang/src/bjc/dicelang/v2/Evaluator.java b/dice-lang/src/bjc/dicelang/v2/Evaluator.java
index 72d7779..969b2d5 100644
--- a/dice-lang/src/bjc/dicelang/v2/Evaluator.java
+++ b/dice-lang/src/bjc/dicelang/v2/Evaluator.java
@@ -158,6 +158,13 @@ public class Evaluator {
private TopDownTransformResult pickEvaluationType(Node nd) {
switch(nd.type) {
+ case UNARYOP:
+ switch(nd.operatorType) {
+ case COERCE:
+ return TopDownTransformResult.PULLUP;
+ default:
+ return TopDownTransformResult.PUSHDOWN;
+ }
default:
return TopDownTransformResult.PUSHDOWN;
}
@@ -166,8 +173,7 @@ public class Evaluator {
private ITree<Node> evaluateNode(ITree<Node> ast, Context ctx) {
switch(ast.getHead().type) {
case UNARYOP:
- System.out.println("\tEVALUATOR ERROR: Unary operator evaluation isn't supported yet");
- return new Tree<>(FAIL(ast));
+ return evaluateUnaryOp(ast, ctx);
case BINOP:
return evaluateBinaryOp(ast, ctx);
case TOKREF:
@@ -180,6 +186,20 @@ public class Evaluator {
}
}
+ private ITree<Node> evaluateUnaryOp(ITree<Node> ast, Context ctx) {
+ switch(ast.getHead().operatorType) {
+ case COERCE:
+ if(ast.getChildrenCount() != 1) {
+ Errors.inst.printError(EK_EVAL_NOTUNARY, ast.getChildrenCount());
+ return new Tree<>(FAIL(AST));
+ }
+ break;
+ default:
+ Errors.inst.printError(EK_EVAL_INVUNARY, ast.getHead().operatorType.toString());
+ return new Tree<>(FAIL(ast));
+ }
+ }
+
private ITree<Node> evaluateBinaryOp(ITree<Node> ast, Context ctx) {
Token.Type binOp = ast.getHead().operatorType;
diff --git a/dice-lang/src/bjc/dicelang/v2/Parser.java b/dice-lang/src/bjc/dicelang/v2/Parser.java
index 9a873f1..7151e0e 100644
--- a/dice-lang/src/bjc/dicelang/v2/Parser.java
+++ b/dice-lang/src/bjc/dicelang/v2/Parser.java
@@ -127,6 +127,18 @@ public class Parser {
working.push(opNode);
}
break;
+ case COERCE:
+ if(working.size() == 0) {
+ Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString());
+ } else {
+ ITree<Node> operand = working.pop();
+ ITree<Node> opNode = new Tree<>(new Node(UNARYOP, tk.type));
+
+ opNode.addChild(operand);
+
+ working.push(opNode);
+ }
+ break;
case INT_LIT:
case FLOAT_LIT:
case STRING_LIT:
diff --git a/dice-lang/src/bjc/dicelang/v2/Shunter.java b/dice-lang/src/bjc/dicelang/v2/Shunter.java
index 014be7d..37da14c 100644
--- a/dice-lang/src/bjc/dicelang/v2/Shunter.java
+++ b/dice-lang/src/bjc/dicelang/v2/Shunter.java
@@ -19,13 +19,17 @@ public class Shunter {
private IMap<Token.Type, Integer> ops;
// Unary operators that can only be
- // applied to non-operator tokens
+ // applied to non-operator tokens and yield operator tokens
private Set<Token.Type> unaryAdjectives;
- // Unary operators that con only be
- // applied to operator tokens
+ // Unary operators that can only be
+ // applied to operator tokens and yield operator tokens
private Set<Token.Type> unaryAdverbs;
+ // Unary operators that can only be
+ // applied to operator tokens and yield data tokens
+ private Set<Token.Type> unaryGerunds;
+
private final int MATH_PREC = 20;
private final int DICE_PREC = 10;
private final int EXPR_PREC = 0;
@@ -35,6 +39,9 @@ public class Shunter {
unaryAdjectives = new HashSet<>();
unaryAdverbs = new HashSet<>();
+ unaryGerunds = new HashSet<>();
+
+ unaryAdjectives.add(COERCE);
ops.put(ADD, 0 + MATH_PREC);
ops.put(SUBTRACT, 0 + MATH_PREC);
@@ -51,6 +58,25 @@ public class Shunter {
ops.put(BIND, 1 + EXPR_PREC);
}
+ private boolean isUnary(Token ty) {
+ switch(ty.type) {
+ default:
+ return false;
+ }
+ }
+
+ private boolean isOp(Token tk) {
+ Token.Type ty = tk.type;
+
+ if(ops.containsKey(ty)) return true;
+ if(unaryAdjectives.contains(ty)) return true;
+ if(unaryAdverbs.contains(ty)) return true;
+ if(unaryGerunds.contains(ty)) return true;
+ if(ty == TAGOPR) return true;
+
+ return false;
+ }
+
public boolean shuntTokens(IList<Token> tks, IList<Token> returned) {
Deque<Token> opStack = new LinkedList<>();
@@ -60,118 +86,103 @@ public class Shunter {
Deque<Token> currReturned = new LinkedList<>();
for(Token tk : tks.toIterable()) {
+ Token.Type tkType = tk.type;
+
if(unaryMode) {
- if(unaryAdjectives.contains(tk.type) || unaryAdverbs.contains(tk.type)) {
- unaryOps.push(tk);
+ if(isUnary(tk)) {
+ unaryOps.add(tk);
continue;
}
- Token currOperator = unaryOps.peek();
-
- if(unaryAdjectives.contains(currOperator.type)) {
- boolean isOp = ops.containsKey(tk.type)
- || unaryAdverbs.contains(tk.type)
- || unaryAdjectives.contains(tk.type);
+ Token unaryOp = unaryOps.pop();
- if(isOp) {
- Errors.inst.printError(EK_SHUNT_NOTADV, currOperator.toString(), tk.toString());
- return false;
- }
+ Token.Type unaryType = unaryOp.type;
- currReturned.addLast(tk);
- currReturned.addLast(unaryOps.pop());
- } else if (unaryAdverbs.contains(currOperator.type)) {
- if(opStack.size() < 1) {
- Errors.inst.printError(EK_SHUNT_NOOP, currOperator.toString());
+ if(unaryAdjectives.contains(unaryType)) {
+ if(isOp(tk)) {
+ Errors.inst.printError(EK_SHUNT_NOTADV, unaryOp.toString(), tk.toString());
return false;
}
- Token currOperand = opStack.peek();
-
- boolean isOp = ops.containsKey(currOperand.type)
- || unaryAdverbs.contains(currOperand.type)
- || unaryAdjectives.contains(currOperand.type);
-
- if(!isOp) {
- Errors.inst.printError(EK_SHUNT_NOTADJ,
- currOperator.toString(),
- tk.toString());
-
- return false;
+ Token newTok = new Token(TAGOPR);
+
+ if(tk.type == TAGOP) {
+ newTok.tokenValues = tk.tokenValues;
+ } else {
+ newTok.tokenValues = new FunctionalList<>();
}
- currReturned.addLast(tk);
- currReturned.addLast(unaryOps.pop());
+ newTok.tokenValues.add(unaryOp);
+ opStack.push(newTok);
+ } else if(unaryAdverbs.contains(unaryType)) {
+ // @TODO finish implementing unary operators
+ // this will require adding a 'backfeed' to the shunter to catch
+ // tokens we missed while parsing unary operators
}
+ }
- if(unaryOps.isEmpty()) unaryMode = false;
- } else {
- if(unaryAdjectives.contains(tk.type) || unaryAdverbs.contains(tk.type)) {
- unaryMode = true;
-
- unaryOps.add(tk);
- continue;
- } else if(ops.containsKey(tk.type)) {
- while(!opStack.isEmpty()
- && isHigherPrec(tk.type, opStack.peek().type)) {
- currReturned.addLast(opStack.pop());
- }
+ if(isUnary(tk)) {
+ unaryMode = true;
- opStack.push(tk);
- } else if(tk.type == OPAREN || tk.type == OBRACE) {
- opStack.push(tk);
-
- if(tk.type == OBRACE)
- currReturned.addLast(tk);
- } else if(tk.type == CPAREN || tk.type == CBRACE) {
- Token matching = null;
-
- switch(tk.type) {
- case CPAREN:
- matching = new Token(OPAREN, tk.intValue);
- break;
- case CBRACE:
- matching = new Token(OBRACE, tk.intValue);
- break;
- default:
- break;
- }
+ unaryOps.add(tk);
+ continue;
+ } else if(isOp(tk)) {
+ while(!opStack.isEmpty() && isHigherPrec(tk, opStack.peek())) {
+ currReturned.addLast(opStack.pop());
+ }
- if(!opStack.contains(matching)) {
- Errors.inst.printError(EK_SHUNT_NOGROUP,
- tk.toString(), matching.toString());
- return false;
- }
+ opStack.push(tk);
+ } else if(tk.type == OPAREN || tk.type == OBRACE) {
+ opStack.push(tk);
+
+ if(tk.type == OBRACE) currReturned.addLast(tk);
+ } else if(tk.type == CPAREN || tk.type == CBRACE) {
+ Token matching = null;
+
+ switch(tk.type) {
+ case CPAREN:
+ matching = new Token(OPAREN, tk.intValue);
+ break;
+ case CBRACE:
+ matching = new Token(OBRACE, tk.intValue);
+ break;
+ default:
+ break;
+ }
- while(!opStack.peek().equals(matching)) {
- currReturned.addLast(opStack.pop());
- }
+ if(!opStack.contains(matching)) {
+ Errors.inst.printError(EK_SHUNT_NOGROUP, tk.toString(), matching.toString());
+ return false;
+ }
- if(tk.type == CBRACE) {
- currReturned.addLast(tk);
- }
+ while(!opStack.peek().equals(matching)) {
+ currReturned.addLast(opStack.pop());
+ }
- opStack.pop();
- } else if(tk.type == GROUPSEP) {
- IList<Token> group = new FunctionalList<>();
+ if(tk.type == CBRACE) {
+ currReturned.addLast(tk);
+ }
- while(currReturned.size() != 0 && !currReturned.peek().isGrouper()) {
- group.add(currReturned.pop());
- }
+ opStack.pop();
+ } else if(tk.type == GROUPSEP) {
+ IList<Token> group = new FunctionalList<>();
- while(opStack.size() != 0 && !opStack.peek().isGrouper()) {
- group.add(opStack.pop());
- }
+ while(currReturned.size() != 0 && !currReturned.peek().isGrouper()) {
+ group.add(currReturned.pop());
+ }
- if(currReturned.size() == 0) {
- Errors.inst.printError(EK_SHUNT_INVSEP);
- return false;
- }
+ while(opStack.size() != 0 && !opStack.peek().isGrouper()) {
+ group.add(opStack.pop());
+ }
- currReturned.addLast(new Token(TOKGROUP, group));
- } else {
- currReturned.addLast(tk);
+ if(currReturned.size() == 0) {
+ Errors.inst.printError(EK_SHUNT_INVSEP);
+ return false;
}
+
+ currReturned.addLast(new Token(TOKGROUP, group));
+ } else {
+ currReturned.addLast(tk);
}
}
@@ -187,7 +198,10 @@ public class Shunter {
return true;
}
- private boolean isHigherPrec(Token.Type left, Token.Type right) {
+ private boolean isHigherPrec(Token lft, Token rght) {
+ Token.Type left = lft.type;
+ Token.Type right = rght.type;
+
boolean exists = ops.containsKey(right);
// If it doesn't, the left is higher precedence.
diff --git a/dice-lang/src/bjc/dicelang/v2/Token.java b/dice-lang/src/bjc/dicelang/v2/Token.java
index e6f22a5..ed5ee8b 100644
--- a/dice-lang/src/bjc/dicelang/v2/Token.java
+++ b/dice-lang/src/bjc/dicelang/v2/Token.java
@@ -20,24 +20,41 @@ public class Token {
INT_LIT, FLOAT_LIT, STRING_LIT,
VREF,
DICE_LIT, DICEGROUP, DICECONCAT, DICELIST,
- LET, BIND,
+ LET, BIND, COERCE,
OPAREN, CPAREN,
OBRACKET, CBRACKET,
OBRACE, CBRACE,
+
// Synthetic tokens
// These are produced when needed
- NIL, PRESHUNT, GROUPSEP,
- TOKGROUP
+ NIL, GROUPSEP, TOKGROUP,
+ TAGOP, TAGOPR,
+
+ // Tag tokens
+ // These are used for the TAG* tokens
+
}
- public final Type type;
+ public final Type type;
- // At most one of these is valid
- // based on the token type
+ // This is used for the following token types
+ // INT_LIT (int value)
+ // STRING_LIT (index into string table)
+ // VREF (index into sym table)
+ // O* and C* (sym-count of current token)
public long intValue;
+
+ // This is used for the following token types
+ // FLOAT_LIT (float value)
public double floatValue;
- public String stringValue;
+
+ // This is used for the following token types
+ // DICE_LIT (dice value)
public DiceBox.DieExpression diceValue;
+
+ // This is used for the following token types
+ // TOKGROUP (the tokens in the group)
+ // TAG* (the tagged construct)
public IList<Token> tokenValues;
public Token(Type typ) {
@@ -56,12 +73,6 @@ public class Token {
floatValue = val;
}
- public Token(Type typ, String val) {
- this(typ);
-
- stringValue = val;
- }
-
public Token(Type typ, DiceBox.DieExpression val) {
this(typ);