From 9d52d55e68ffacb97636c7451367fde85db2b36f Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 25 Aug 2017 18:42:41 -0700 Subject: [PATCH] Add TreeValue operator nodes, and parsing for them. --- .../nwapw/abacus/parsing/LexerTokenizer.java | 6 ++++ .../abacus/parsing/ShuntingYardParser.java | 30 +++++++++++++------ .../java/org/nwapw/abacus/tree/TokenType.java | 3 +- .../nwapw/abacus/tree/TreeValueBinaryNode.kt | 21 +++++++++++++ .../nwapw/abacus/tree/TreeValueUnaryNode.kt | 19 ++++++++++++ 5 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueBinaryNode.kt create mode 100644 core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueUnaryNode.kt diff --git a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java index 14ecf95..2d7b16b 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java @@ -50,6 +50,9 @@ public class LexerTokenizer implements Tokenizer>, PluginListen for (String operator : manager.getAllOperators()) { lexer.register(Pattern.sanitize(operator), TokenType.OP); } + for (String operator : manager.getAllTreeValueOperators()){ + lexer.register(Pattern.sanitize(operator), TokenType.TREE_VALUE_OP); + } for (String function : manager.getAllFunctions()) { lexer.register(Pattern.sanitize(function), TokenType.FUNCTION); } @@ -63,6 +66,9 @@ public class LexerTokenizer implements Tokenizer>, PluginListen for (String operator : manager.getAllOperators()) { lexer.unregister(Pattern.sanitize(operator), TokenType.OP); } + for (String operator : manager.getAllTreeValueOperators()){ + lexer.unregister(Pattern.sanitize(operator), TokenType.TREE_VALUE_OP); + } for (String function : manager.getAllFunctions()) { lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION); } diff --git a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index b7bac6d..fd74bc0 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -58,7 +58,7 @@ public class ShuntingYardParser implements Parser>, PluginListe } else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) { output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END)); tokenStack.push(match); - } else if (matchType == TokenType.OP) { + } else if (matchType == TokenType.OP || matchType == TokenType.TREE_VALUE_OP) { String tokenString = match.getContent(); OperatorType type = typeMap.get(tokenString); int precedence = precedenceMap.get(tokenString); @@ -70,7 +70,7 @@ public class ShuntingYardParser implements Parser>, PluginListe } if (tokenString.equals("-") && (previousType == null || previousType == TokenType.OP || - previousType == TokenType.OPEN_PARENTH)) { + previousType == TokenType.TREE_VALUE_OP || previousType == TokenType.OPEN_PARENTH)) { from.add(0, new Match<>("`", TokenType.OP)); continue; } @@ -78,10 +78,12 @@ public class ShuntingYardParser implements Parser>, PluginListe while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) { Match otherMatch = tokenStack.peek(); TokenType otherMatchType = otherMatch.getType(); - if (!(otherMatchType == TokenType.OP || otherMatchType == TokenType.FUNCTION || - otherMatchType == TokenType.TREE_VALUE_FUNCTION)) break; + if (!(otherMatchType == TokenType.OP || + otherMatchType == TokenType.TREE_VALUE_OP || + otherMatchType == TokenType.FUNCTION || + otherMatchType == TokenType.TREE_VALUE_FUNCTION)) break; - if (otherMatchType == TokenType.OP) { + if (otherMatchType == TokenType.OP || otherMatchType == TokenType.TREE_VALUE_OP) { int otherPrecedence = precedenceMap.get(otherMatch.getContent()); if (otherPrecedence < precedence || (associativity == OperatorAssociativity.RIGHT && otherPrecedence == precedence)) { @@ -106,7 +108,9 @@ public class ShuntingYardParser implements Parser>, PluginListe while (!tokenStack.empty()) { Match match = tokenStack.peek(); TokenType newMatchType = match.getType(); - if (!(newMatchType == TokenType.OP || newMatchType == TokenType.FUNCTION || + if (!(newMatchType == TokenType.OP || + newMatchType == TokenType.TREE_VALUE_OP || + newMatchType == TokenType.FUNCTION || newMatchType == TokenType.TREE_VALUE_FUNCTION)) return null; output.add(tokenStack.pop()); } @@ -123,18 +127,26 @@ public class ShuntingYardParser implements Parser>, PluginListe if (matches.size() == 0) return null; Match match = matches.remove(0); TokenType matchType = match.getType(); - if (matchType == TokenType.OP) { + if (matchType == TokenType.OP || matchType == TokenType.TREE_VALUE_OP) { String operator = match.getContent(); OperatorType type = typeMap.get(operator); if (type == OperatorType.BINARY_INFIX) { TreeNode right = constructRecursive(matches); TreeNode left = constructRecursive(matches); if (left == null || right == null) return null; - else return new NumberBinaryNode(operator, left, right); + if(matchType == TokenType.OP) { + return new NumberBinaryNode(operator, left, right); + } else { + return new TreeValueBinaryNode(operator, left, right); + } } else { TreeNode applyTo = constructRecursive(matches); if (applyTo == null) return null; - else return new NumberUnaryNode(operator, applyTo); + if(matchType == TokenType.OP){ + return new NumberUnaryNode(operator, applyTo); + } else { + return new TreeValueUnaryNode(operator, applyTo); + } } } else if (matchType == TokenType.NUM) { return new NumberNode(match.getContent()); diff --git a/core/src/main/java/org/nwapw/abacus/tree/TokenType.java b/core/src/main/java/org/nwapw/abacus/tree/TokenType.java index 857e9b4..ff1ca5e 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/TokenType.java +++ b/core/src/main/java/org/nwapw/abacus/tree/TokenType.java @@ -7,7 +7,8 @@ package org.nwapw.abacus.tree; public enum TokenType { INTERNAL_FUNCTION_END(-1), - ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), TREE_VALUE_FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8); + ANY(0), WHITESPACE(1), COMMA(2), OP(3), TREE_VALUE_OP(3), + NUM(4), VARIABLE(5), FUNCTION(6), TREE_VALUE_FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8); /** * The priority by which this token gets sorted. diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueBinaryNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueBinaryNode.kt new file mode 100644 index 0000000..4edfef3 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueBinaryNode.kt @@ -0,0 +1,21 @@ +package org.nwapw.abacus.tree + +/** + * A tree node that represents a binary tree value operator. + * + * + * The tree value operators operate on trees, and so this + * node does not reduce its children. It is up to the implementation to handle + * reduction. + * @param operation the operation this node performs. + * @param left the left child of this node. + * @param right the right child of this node. + */ +class TreeValueBinaryNode(operation: String, left: TreeNode?, right: TreeNode?) + : BinaryNode(operation, left, right) { + + override fun reduce(reducer: Reducer): T? { + return reducer.reduceNode(this) + } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueUnaryNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueUnaryNode.kt new file mode 100644 index 0000000..fdc0db5 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/TreeValueUnaryNode.kt @@ -0,0 +1,19 @@ +package org.nwapw.abacus.tree + +/** + * A tree node that represents a unary tree value operator. + * + * The tree value operators operate on trees, and so this + * node does not reduce its children. It is up to the implementation to handle + * reduction. + * @param operation the operation this node performs. + * @param child the node the operation should be applied to. + */ +class TreeValueUnaryNode(operation: String, child: TreeNode?) + : UnaryNode(operation, child) { + + override fun reduce(reducer: Reducer): T? { + return reducer.reduceNode(this); + } + +} \ No newline at end of file