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:
parent
07d7343339
commit
9d52d55e68
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_FUNCTION)) break;
|
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());
|
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());
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user