diff options
| author | bjculkin <bjculkin@mix.wvu.edu> | 2017-03-16 15:33:09 -0400 |
|---|---|---|
| committer | bjculkin <bjculkin@mix.wvu.edu> | 2017-03-16 15:33:09 -0400 |
| commit | 348e10db258ae0cd0ae61dd99f6359ac4c8c0bd1 (patch) | |
| tree | 96e91ff2c65000612667b98aece9f301f70004ac /dice-lang/src/bjc/dicelang/expr/Shunter.java | |
| parent | ca704c30af8b5bf2695c7128e0b21f505457da7b (diff) | |
Added alternate expression parser.
This adds an alternate expression parser designed solely for arithmetic
operations.
Diffstat (limited to 'dice-lang/src/bjc/dicelang/expr/Shunter.java')
| -rw-r--r-- | dice-lang/src/bjc/dicelang/expr/Shunter.java | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/dice-lang/src/bjc/dicelang/expr/Shunter.java b/dice-lang/src/bjc/dicelang/expr/Shunter.java new file mode 100644 index 0000000..5d8cb7c --- /dev/null +++ b/dice-lang/src/bjc/dicelang/expr/Shunter.java @@ -0,0 +1,95 @@ +package bjc.dicelang.expr; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +/** + * Converts a infix series of tokens into a prefix series of tokens. + * + * @author Ben Culkin + */ +public class Shunter { + /** + * Convert a infix series of tokens to a postfix series of tokens. + * + * @param infixTokens + * The tokens in infix order. + * + * @return The tokens in postfix order. + */ + public static Token[] shuntTokens(Token[] infixTokens) { + List<Token> postfixTokens = new ArrayList<>(infixTokens.length); + + Deque<Token> opStack = new LinkedList<>(); + + /* + * Shunt each token. + */ + for(Token tok : infixTokens) { + /* + * Handle operators. + */ + if(tok.type.isOperator) { + Token curOp = opStack.peek(); + + /* + * Check if an operator is higher priority, + * respecting their left associativity. + */ + int leftPriority = tok.type.operatorPriority; + int rightPriority = curOp == null ? 0 : curOp.type.operatorPriority; + + boolean isHigherPrec = leftPriority >= rightPriority; + + /* + * Pop all operators that are lower precedence + * than us. + */ + while(!opStack.isEmpty() && isHigherPrec) { + postfixTokens.add(opStack.pop()); + + curOp = opStack.peek(); + + leftPriority = tok.type.operatorPriority; + rightPriority = curOp == null ? 0 : curOp.type.operatorPriority; + + isHigherPrec = leftPriority >= rightPriority; + } + + opStack.push(tok); + } else if(tok.type == TokenType.OPAREN) { + opStack.push(tok); + } else if(tok.type == TokenType.CPAREN) { + Token curOp = opStack.peek(); + + /* + * Pop things until we find the matching paren. + */ + while(curOp.type != TokenType.OPAREN) { + Token tk = opStack.pop(); + + postfixTokens.add(tk); + + curOp = opStack.peek(); + } + + if(!opStack.isEmpty()) { + opStack.pop(); + } + } else { + postfixTokens.add(tok); + } + } + + /* + * Flush remaining operators. + */ + while(!opStack.isEmpty()) { + postfixTokens.add(opStack.pop()); + } + + return postfixTokens.toArray(new Token[0]); + } +} |
