summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/v2/Shunter.java
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2017-02-24 04:15:20 -0500
committerbculkin2442 <bjculkin@mix.wvu.edu>2017-02-24 04:15:20 -0500
commit5e246adccf986af9dd032d6e8645ddd5d2a577d4 (patch)
tree96cc49b43b32f1b38e4d848419d2b23a4c74b217 /dice-lang/src/bjc/dicelang/v2/Shunter.java
parenta942114b89013732a2be3092cdb65cafc4566fe0 (diff)
Work on unary operators
Specifically, the coercive operator for allowing mixing floats and ints
Diffstat (limited to 'dice-lang/src/bjc/dicelang/v2/Shunter.java')
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Shunter.java200
1 files changed, 107 insertions, 93 deletions
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.