1
0
mirror of https://github.com/DanilaFe/abacus synced 2024-12-22 15:30:09 -08:00

Add TreeValue operator nodes, and parsing for them.

This commit is contained in:
Danila Fedorin 2017-08-25 18:42:41 -07:00
parent 07d7343339
commit 9d52d55e68
5 changed files with 69 additions and 10 deletions

View File

@ -50,6 +50,9 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
for (String operator : manager.getAllOperators()) { for (String operator : manager.getAllOperators()) {
lexer.register(Pattern.sanitize(operator), TokenType.OP); 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()) { for (String function : manager.getAllFunctions()) {
lexer.register(Pattern.sanitize(function), TokenType.FUNCTION); lexer.register(Pattern.sanitize(function), TokenType.FUNCTION);
} }
@ -63,6 +66,9 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
for (String operator : manager.getAllOperators()) { for (String operator : manager.getAllOperators()) {
lexer.unregister(Pattern.sanitize(operator), TokenType.OP); 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()) { for (String function : manager.getAllFunctions()) {
lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION); lexer.unregister(Pattern.sanitize(function), TokenType.FUNCTION);
} }

View File

@ -58,7 +58,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
} else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) { } else if (matchType == TokenType.FUNCTION || matchType == TokenType.TREE_VALUE_FUNCTION) {
output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END)); output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END));
tokenStack.push(match); tokenStack.push(match);
} else if (matchType == TokenType.OP) { } else if (matchType == TokenType.OP || matchType == TokenType.TREE_VALUE_OP) {
String tokenString = match.getContent(); String tokenString = match.getContent();
OperatorType type = typeMap.get(tokenString); OperatorType type = typeMap.get(tokenString);
int precedence = precedenceMap.get(tokenString); int precedence = precedenceMap.get(tokenString);
@ -70,7 +70,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
} }
if (tokenString.equals("-") && (previousType == null || previousType == TokenType.OP || 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)); from.add(0, new Match<>("`", TokenType.OP));
continue; continue;
} }
@ -78,10 +78,12 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) { while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) {
Match<TokenType> otherMatch = tokenStack.peek(); Match<TokenType> otherMatch = tokenStack.peek();
TokenType otherMatchType = otherMatch.getType(); TokenType otherMatchType = otherMatch.getType();
if (!(otherMatchType == TokenType.OP || otherMatchType == TokenType.FUNCTION || if (!(otherMatchType == TokenType.OP ||
otherMatchType == TokenType.TREE_VALUE_OP ||
otherMatchType == TokenType.FUNCTION ||
otherMatchType == TokenType.TREE_VALUE_FUNCTION)) break; 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()); int otherPrecedence = precedenceMap.get(otherMatch.getContent());
if (otherPrecedence < precedence || if (otherPrecedence < precedence ||
(associativity == OperatorAssociativity.RIGHT && otherPrecedence == precedence)) { (associativity == OperatorAssociativity.RIGHT && otherPrecedence == precedence)) {
@ -106,7 +108,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
while (!tokenStack.empty()) { while (!tokenStack.empty()) {
Match<TokenType> match = tokenStack.peek(); Match<TokenType> match = tokenStack.peek();
TokenType newMatchType = match.getType(); 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; newMatchType == TokenType.TREE_VALUE_FUNCTION)) return null;
output.add(tokenStack.pop()); output.add(tokenStack.pop());
} }
@ -123,18 +127,26 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
if (matches.size() == 0) return null; if (matches.size() == 0) return null;
Match<TokenType> match = matches.remove(0); Match<TokenType> match = matches.remove(0);
TokenType matchType = match.getType(); TokenType matchType = match.getType();
if (matchType == TokenType.OP) { if (matchType == TokenType.OP || matchType == TokenType.TREE_VALUE_OP) {
String operator = match.getContent(); String operator = match.getContent();
OperatorType type = typeMap.get(operator); OperatorType type = typeMap.get(operator);
if (type == OperatorType.BINARY_INFIX) { if (type == OperatorType.BINARY_INFIX) {
TreeNode right = constructRecursive(matches); TreeNode right = constructRecursive(matches);
TreeNode left = constructRecursive(matches); TreeNode left = constructRecursive(matches);
if (left == null || right == null) return null; 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 { } else {
TreeNode applyTo = constructRecursive(matches); TreeNode applyTo = constructRecursive(matches);
if (applyTo == null) return null; 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) { } else if (matchType == TokenType.NUM) {
return new NumberNode(match.getContent()); return new NumberNode(match.getContent());

View File

@ -7,7 +7,8 @@ package org.nwapw.abacus.tree;
public enum TokenType { public enum TokenType {
INTERNAL_FUNCTION_END(-1), 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. * The priority by which this token gets sorted.

View File

@ -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 <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this)
}
}

View File

@ -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 <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this);
}
}