From 870d769cfc152171d27b2331a7c590d0b307ad48 Mon Sep 17 00:00:00 2001 From: EVE Date: Mon, 13 Mar 2017 16:41:15 -0400 Subject: More tweaker work. --- dice-lang/src/bjc/dicelang/Shunter.java | 186 +++++++++++++++++++------------- 1 file changed, 111 insertions(+), 75 deletions(-) (limited to 'dice-lang/src/bjc/dicelang/Shunter.java') 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 ops; + IMap ops; + /* + * Operators that are right-associative + */ + Set rightAssoc; + + /* + * Operators that aren't associative + */ + Set notAssoc; + // Unary operators that can only be // applied to non-operator tokens and yield operator tokens - private Set unaryAdjectives; + Set unaryAdjectives; // Unary operators that can only be // applied to operator tokens and yield operator tokens - private Set unaryAdverbs; + Set unaryAdverbs; // Unary operators that can only be // applied to operator tokens and yield data tokens - private Set unaryGerunds; + Set 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 tks, IList returned) { + Deque opStack = new LinkedList<>(); + Deque unaryOps = new LinkedList<>(); - if(unaryAdjectives.contains(ty)) return true; - if(unaryAdverbs.contains(ty)) return true; - if(unaryGerunds.contains(ty)) return true; + Deque currReturned = new LinkedList<>(); - return false; - } + Deque 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 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 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 tks, IList returned) { - Deque opStack = new LinkedList<>(); - Deque unaryOps = new LinkedList<>(); - - Deque currReturned = new LinkedList<>(); - - Deque 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; } } -- cgit v1.2.3