diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-10-27 21:56:18 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-10-27 22:12:47 -0400 |
| commit | e7413128ff4e376997de6e94e4bea5eca14811ef (patch) | |
| tree | 0749e270fdb754d04dc223abd95d47436508047f /dice-lang/src/bjc/dicelang/ast/DiceASTParser.java | |
| parent | e13a6981bd278c2cfc3b5ecb2517367b117f7a52 (diff) | |
Moved examples
Diffstat (limited to 'dice-lang/src/bjc/dicelang/ast/DiceASTParser.java')
| -rw-r--r-- | dice-lang/src/bjc/dicelang/ast/DiceASTParser.java | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/dice-lang/src/bjc/dicelang/ast/DiceASTParser.java b/dice-lang/src/bjc/dicelang/ast/DiceASTParser.java new file mode 100644 index 0000000..9a36951 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/ast/DiceASTParser.java @@ -0,0 +1,160 @@ +package bjc.dicelang.ast; + +import java.util.Deque; +import java.util.InputMismatchException; +import java.util.function.Function; +import java.util.function.Predicate; + +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.FunctionalMap; +import bjc.utils.funcdata.IList; +import bjc.utils.funcdata.IMap; +import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.Tree; +import bjc.utils.funcutils.StringUtils; +import bjc.utils.parserutils.TreeConstructor; + +import bjc.dicelang.IDiceExpression; +import bjc.dicelang.ast.nodes.DiceLiteralNode; +import bjc.dicelang.ast.nodes.DiceLiteralType; +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.ILiteralDiceNode; +import bjc.dicelang.ast.nodes.IntegerLiteralNode; +import bjc.dicelang.ast.nodes.OperatorDiceNode; +import bjc.dicelang.ast.nodes.VariableDiceNode; + +/** + * Parse a string expression into AST form. Doesn't do anything else + * + * @author ben + * + */ +public class DiceASTParser { + private static IDiceASTNode convertLeafNode(String leafNode) { + DiceLiteralType literalType = ILiteralDiceNode + .getLiteralType(leafNode); + + if (literalType != null) { + switch (literalType) { + case DICE: + return new DiceLiteralNode( + IDiceExpression.toExpression(leafNode)); + case INTEGER: + return new IntegerLiteralNode( + Integer.parseInt(leafNode)); + default: + throw new InputMismatchException( + "Cannot convert string '" + leafNode + + "' into a literal."); + } + } + + if (leafNode.matches("[+-]?\\d*\\.\\d+")) { + throw new InputMismatchException( + "Floating point literals are not supported"); + } + + return new VariableDiceNode(leafNode); + } + + private static IDiceASTNode convertOperatorNode(String operatorNode) { + try { + return OperatorDiceNode.fromString(operatorNode); + } catch (IllegalArgumentException iaex) { + InputMismatchException imex = new InputMismatchException( + "Attempted to parse invalid operator " + operatorNode); + + imex.initCause(iaex); + + throw imex; + } + } + + /** + * Create an AST from a list of tokens + * + * @param tokens + * The list of tokens to convert + * @return An AST built from the tokens + */ + public static ITree<IDiceASTNode> createFromString( + IList<String> tokens) { + Predicate<String> specialPicker = (operator) -> { + if (StringUtils.containsOnly(operator, "\\[")) { + return true; + } else if (StringUtils.containsOnly(operator, "\\]")) { + return true; + } + + return false; + }; + + IMap<String, Function<Deque<ITree<String>>, ITree<String>>> operators = new FunctionalMap<>(); + + operators.put("[", (queuedTrees) -> { + Tree<String> openArray = new Tree<>("["); + + return openArray; + }); + + operators.put("]", (queuedTrees) -> { + return parseCloseArray(queuedTrees); + }); + + ITree<String> rawTokens = TreeConstructor.constructTree(tokens, + (token) -> { + return isOperatorNode(token); + }, specialPicker, operators::get); + + ITree<IDiceASTNode> tokenizedTree = rawTokens.rebuildTree( + DiceASTParser::convertLeafNode, + DiceASTParser::convertOperatorNode); + + return tokenizedTree; + } + + private static boolean isOperatorNode(String token) { + if (StringUtils.containsOnly(token, "\\[")) { + return true; + } else if (StringUtils.containsOnly(token, "\\]")) { + return true; + } + + if (token.equals("[]")) { + // This is a synthetic operator, constructed by [ and ] + return true; + } + + try { + OperatorDiceNode.fromString(token); + return true; + } catch (@SuppressWarnings("unused") IllegalArgumentException iaex) { + // We don't care about details + return false; + } + } + + private static ITree<String> parseCloseArray( + Deque<ITree<String>> queuedTrees) { + IList<ITree<String>> children = new FunctionalList<>(); + + while (shouldContinuePopping(queuedTrees)) { + children.add(queuedTrees.pop()); + } + + queuedTrees.pop(); + + children.reverse(); + + ITree<String> arrayTree = new Tree<>("[]", children); + + return arrayTree; + } + + private static boolean shouldContinuePopping( + Deque<ITree<String>> queuedTrees) { + String peekToken = queuedTrees.peek().getHead(); + + return !peekToken.equals("["); + } +} |
