diff options
| author | EVE <EVE@EVE-PC> | 2017-03-13 16:41:15 -0400 |
|---|---|---|
| committer | EVE <EVE@EVE-PC> | 2017-03-13 16:41:15 -0400 |
| commit | 870d769cfc152171d27b2331a7c590d0b307ad48 (patch) | |
| tree | 3fee9a6bbbf03792cbe9c0a7927b92e4783e07a0 /dice-lang/src/bjc/dicelang/Shunter.java | |
| parent | 620ad3db1cbebe52ebd8df03fcda9d965ecb3282 (diff) | |
More tweaker work.
Diffstat (limited to 'dice-lang/src/bjc/dicelang/Shunter.java')
| -rw-r--r-- | dice-lang/src/bjc/dicelang/Shunter.java | 186 |
1 files changed, 111 insertions, 75 deletions
diff --git a/dice-lang/src/bjc/dicelang/Shunter.java b/dice-lang/src/bjc/dicelang/Shunter.java index 28ae117..900f72c 100644 --- a/dice-lang/src/bjc/dicelang/Shunter.java +++ b/dice-lang/src/bjc/dicelang/Shunter.java @@ -16,27 +16,40 @@ import java.util.Set; public class Shunter { // The binary operators and their // priorities - private IMap<Token.Type, Integer> ops; + IMap<Token.Type, Integer> ops; + /* + * Operators that are right-associative + */ + Set<Token.Type> rightAssoc; + + /* + * Operators that aren't associative + */ + Set<Token.Type> notAssoc; + // Unary operators that can only be // applied to non-operator tokens and yield operator tokens - private Set<Token.Type> unaryAdjectives; + Set<Token.Type> unaryAdjectives; // Unary operators that can only be // applied to operator tokens and yield operator tokens - private Set<Token.Type> unaryAdverbs; + Set<Token.Type> unaryAdverbs; // Unary operators that can only be // applied to operator tokens and yield data tokens - private Set<Token.Type> unaryGerunds; + Set<Token.Type> unaryGerunds; - private final int MATH_PREC = 30; - private final int DICE_PREC = 20; - private final int STR_PREC = 10; - private final int EXPR_PREC = 0; + public final int MATH_PREC = 30; + public final int DICE_PREC = 20; + public final int STR_PREC = 10; + public final int EXPR_PREC = 0; public Shunter() { ops = new FunctionalMap<>(); + + rightAssoc = new HashSet<>(); + notAssoc = new HashSet<>(); unaryAdjectives = new HashSet<>(); unaryAdverbs = new HashSet<>(); @@ -60,30 +73,47 @@ public class Shunter { ops.put(STRCAT, 0 + STR_PREC); ops.put(STRREP, 1 + STR_PREC); + ops.put(LET, 0 + EXPR_PREC); ops.put(BIND, 1 + EXPR_PREC); } - private boolean isUnary(Token tk) { - Token.Type ty = tk.type; + public boolean shuntTokens(IList<Token> tks, IList<Token> returned) { + Deque<Token> opStack = new LinkedList<>(); + Deque<Token> unaryOps = new LinkedList<>(); - if(unaryAdjectives.contains(ty)) return true; - if(unaryAdverbs.contains(ty)) return true; - if(unaryGerunds.contains(ty)) return true; + Deque<Token> currReturned = new LinkedList<>(); - return false; - } + Deque<Token> feed = new LinkedList<>(); - private boolean isOp(Token tk) { - Token.Type ty = tk.type; + for(Token tk : tks.toIterable()) { + boolean succ; + + while(feed.size() != 0) { + succ = shuntToken(feed.poll(), opStack, unaryOps, currReturned, feed); + + if(!succ) { + return false; + } + } + + succ = shuntToken(tk, opStack, unaryOps, currReturned, feed); + + if(!succ) { + return false; + } + } - 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; + // Flush leftover operators + while(!opStack.isEmpty()) { + currReturned.addLast(opStack.pop()); + } - return false; + for(Token tk : currReturned) { + returned.add(tk); + } + + return true; } private boolean shuntToken(Token tk, Deque<Token> opStack, @@ -94,66 +124,72 @@ public class Shunter { unaryStack.add(tk); return true; } - + Token unaryOp = unaryStack.pop(); - + Token.Type unaryType = unaryOp.type; - + if(unaryAdjectives.contains(unaryType)) { if(isOp(tk)) { Errors.inst.printError(EK_SHUNT_NOTADV, unaryOp.toString(), tk.toString()); return false; } - + Token newTok = new Token(TAGOPR); - + if(tk.type == TAGOP) { newTok.tokenValues = tk.tokenValues; } else { newTok.tokenValues = new FunctionalList<>(tk); } - + newTok.tokenValues.add(unaryOp); opStack.push(newTok); - + return true; } else if(unaryAdverbs.contains(unaryType)) { if(!isOp(tk)) { Errors.inst.printError(EK_SHUNT_NOTADJ, unaryOp.toString(), tk.toString()); return false; } - + Token newTok = new Token(TAGOPR); - + if(tk.type == TAGOP) { newTok.tokenValues = tk.tokenValues; } else { newTok.tokenValues = new FunctionalList<>(tk); } - + newTok.tokenValues.add(unaryOp); opStack.push(newTok); - + return true; } } - + if(isUnary(tk)) { unaryStack.add(tk); return true; } else if(isOp(tk)) { while(!opStack.isEmpty() && isHigherPrec(tk, opStack.peek())) { - currReturned.addLast(opStack.pop()); + Token newOp = opStack.pop(); + + if(tk.type == newOp.type && notAssoc.contains(tk.type)) { + Errors.inst.printError(EK_SHUNT_NOTASSOC, tk.type.toString()); + } + + currReturned.addLast(newOp); } - + 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); @@ -164,68 +200,42 @@ public class Shunter { default: break; } - + if(!opStack.contains(matching)) { Errors.inst.printError(EK_SHUNT_NOGROUP, tk.toString(), matching.toString()); return false; } - + while(!opStack.peek().equals(matching)) { currReturned.addLast(opStack.pop()); } - + if(tk.type == CBRACE) { currReturned.addLast(tk); } - + opStack.pop(); } else if(tk.type == GROUPSEP) { IList<Token> group = new FunctionalList<>(); - + while(currReturned.size() != 0 && !currReturned.peek().isGrouper()) { group.add(currReturned.pop()); } - + while(opStack.size() != 0 && !opStack.peek().isGrouper()) { group.add(opStack.pop()); } - + if(currReturned.size() == 0) { Errors.inst.printError(EK_SHUNT_INVSEP); return false; } - + currReturned.addLast(new Token(TOKGROUP, group)); } else { currReturned.addLast(tk); } - - return true; - } - - public boolean shuntTokens(IList<Token> tks, IList<Token> returned) { - Deque<Token> opStack = new LinkedList<>(); - Deque<Token> unaryOps = new LinkedList<>(); - - Deque<Token> currReturned = new LinkedList<>(); - - Deque<Token> feed = new LinkedList<>(); - - for(Token tk : tks.toIterable()) { - while(feed.size() != 0) - shuntToken(feed.poll(), opStack, unaryOps, currReturned, feed); - shuntToken(tk, opStack, unaryOps, currReturned, feed); - } - - // Flush leftover operators - while(!opStack.isEmpty()) { - currReturned.addLast(opStack.pop()); - } - - for(Token tk : currReturned) { - returned.add(tk); - } - + return true; } @@ -256,7 +266,33 @@ public class Shunter { } else { leftPrecedence = ops.get(left); } + + if(rightAssoc.contains(left)) { + return rightPrecedence > leftPrecedence; + } else { + return rightPrecedence >= leftPrecedence; + } + } + + 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; + } - return rightPrecedence >= leftPrecedence; + private boolean isUnary(Token tk) { + Token.Type ty = tk.type; + + if(unaryAdjectives.contains(ty)) return true; + if(unaryAdverbs.contains(ty)) return true; + if(unaryGerunds.contains(ty)) return true; + + return false; } } |
