summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-25 22:11:28 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-25 22:11:28 -0400
commitfb7d03388e298258563c22abda1bd46cdaf991b7 (patch)
treeff2caeda751acd733ea00c089800ff380211f0b3 /BJC-Utils2/src/main/java/bjc/utils
parent42f7d379a430aaf2fad169f0170de04072b08b10 (diff)
General code cleanup, and some more GUI controls
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java11
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java105
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java5
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/FormattedInputPanel.java66
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java60
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/SliderInputPanel.java196
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java46
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java55
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java21
10 files changed, 454 insertions, 113 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
index 09d3da7..e1a57c2 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java
@@ -67,10 +67,10 @@ public class CLICommander {
normalOutput.print(currentMode.getName() + ">> ");
}
- String ln = inputSource.nextLine();
+ String currentLine = inputSource.nextLine();
- if (currentMode.canHandleCommand(ln)) {
- String[] commandTokens = ln.split(" ");
+ if (currentMode.canHandleCommand(currentLine)) {
+ String[] commandTokens = currentLine.split(" ");
String[] commandArgs;
@@ -84,7 +84,8 @@ public class CLICommander {
currentMode = currentMode.processCommand(commandTokens[0],
commandArgs);
} else {
- errorOutput.print("Error: Unrecognized command " + ln);
+ errorOutput.print(
+ "Error: Unrecognized command " + currentLine);
}
}
@@ -105,4 +106,4 @@ public class CLICommander {
this.initialMode = initialMode;
}
-}
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
index fad1199..529635d 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
@@ -50,4 +50,4 @@ public class GenericCommand implements ICommand {
public boolean isAlias() {
return false;
}
-}
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
index 84b4d39..a9c9054 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
@@ -70,16 +70,26 @@ public class GenericCommandMode implements ICommandMode {
"Command name must not be null");
} else if (aliasName == null) {
throw new NullPointerException("Alias name must not be null");
- } else if (!commandHandlers.containsKey(commandName)) {
+ } else if (!commandHandlers.containsKey(commandName)
+ && !defaultHandlers.containsKey(commandName)) {
throw new IllegalArgumentException(
"Cannot alias non-existant command '" + commandName
+ "'");
- } else if (commandHandlers.containsKey(aliasName)) {
+ } else if (commandHandlers.containsKey(aliasName)
+ || defaultHandlers.containsKey(aliasName)) {
throw new IllegalArgumentException("Cannot bind alias '"
+ aliasName + "' to a command with a bound handler");
} else {
- commandHandlers.put(aliasName,
- commandHandlers.get(commandName).createAlias());
+ ICommand aliasedCommand;
+ if (defaultHandlers.containsKey(commandName)) {
+ aliasedCommand =
+ defaultHandlers.get(commandName).createAlias();
+ } else {
+ aliasedCommand =
+ commandHandlers.get(commandName).createAlias();
+ }
+
+ commandHandlers.put(aliasName, aliasedCommand);
}
}
@@ -120,29 +130,9 @@ public class GenericCommandMode implements ICommandMode {
helpTopics.put(topicName, help);
}
- private void aliasCommands(String[] args) {
- if (args.length != 2) {
- errorOutput.accept("ERROR: Alias requires two arguments. "
- + "The command name, and the alias for that command");
- } else {
- String commandName = args[0];
- String aliasName = args[1];
-
- if (!canHandleCommand(commandName)) {
- errorOutput.accept("ERROR: '" + commandName
- + "' is not a valid command.");
- } else if (canHandleCommand(aliasName)) {
- errorOutput.accept("ERROR: Cannot overwrite command '"
- + aliasName + "'");
- } else {
- addCommandAlias(commandName, aliasName);
- }
- }
- }
-
private GenericCommand buildAliasCommand() {
return new GenericCommand((args) -> {
- aliasCommands(args);
+ doAliasCommands(args);
return this;
}, "alias\tAlias one command to another",
@@ -177,10 +167,10 @@ public class GenericCommandMode implements ICommandMode {
return new GenericCommand((args) -> {
if (args == null || args.length == 0) {
// Invoke general help
- helpSummary();
+ doHelpSummary();
} else {
// Invoke help for a command
- helpCommand(args[0]);
+ doHelpCommand(args[0]);
}
return this;
@@ -194,7 +184,7 @@ public class GenericCommandMode implements ICommandMode {
private GenericCommand buildListCommand() {
return new GenericCommand((args) -> {
- listCommands();
+ doListCommands();
return this;
}, "list\tList available command",
@@ -208,25 +198,27 @@ public class GenericCommandMode implements ICommandMode {
|| defaultHandlers.containsKey(command);
}
- @Override
- public String getCustomPrompt() {
- if (customPrompt != null) {
- return customPrompt;
- }
-
- return ICommandMode.super.getCustomPrompt();
- }
+ private void doAliasCommands(String[] args) {
+ if (args.length != 2) {
+ errorOutput.accept("ERROR: Alias requires two arguments. "
+ + "The command name, and the alias for that command");
+ } else {
+ String commandName = args[0];
+ String aliasName = args[1];
- @Override
- public String getName() {
- if (modeName != null) {
- return modeName;
+ if (!canHandleCommand(commandName)) {
+ errorOutput.accept("ERROR: '" + commandName
+ + "' is not a valid command.");
+ } else if (canHandleCommand(aliasName)) {
+ errorOutput.accept("ERROR: Cannot overwrite command '"
+ + aliasName + "'");
+ } else {
+ addCommandAlias(commandName, aliasName);
+ }
}
-
- return ICommandMode.super.getName();
}
- private void helpCommand(String commandName) {
+ private void doHelpCommand(String commandName) {
if (commandHandlers.containsKey(commandName)) {
normalOutput.accept("\n" + commandHandlers.get(commandName)
.getHelp().getDescription());
@@ -243,7 +235,7 @@ public class GenericCommandMode implements ICommandMode {
}
}
- private void helpSummary() {
+ private void doHelpSummary() {
normalOutput.accept(
"Help topics for this command mode are as follows:\n");
if (commandHandlers.getSize() > 0) {
@@ -281,7 +273,7 @@ public class GenericCommandMode implements ICommandMode {
}
}
- private void listCommands() {
+ private void doListCommands() {
normalOutput.accept(
"The available commands for this mode are as follows:\n");
@@ -300,6 +292,24 @@ public class GenericCommandMode implements ICommandMode {
}
@Override
+ public String getCustomPrompt() {
+ if (customPrompt != null) {
+ return customPrompt;
+ }
+
+ return ICommandMode.super.getCustomPrompt();
+ }
+
+ @Override
+ public String getName() {
+ if (modeName != null) {
+ return modeName;
+ }
+
+ return ICommandMode.super.getName();
+ }
+
+ @Override
public ICommandMode processCommand(String command, String[] args) {
normalOutput.accept("\n");
@@ -373,7 +383,10 @@ public class GenericCommandMode implements ICommandMode {
addCommandAlias("help", "man");
- // Add commands handled in a upper layer
+ // Add commands handled in a upper layer.
+
+ // TODO figure out a place to put commands that apply across all
+ // modes, but only apply to a specific application
defaultHandlers.put("clear", buildClearCommands());
defaultHandlers.put("exit", buildExitCommand());
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java
index f6313af..48a741c 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandMode.java
@@ -36,10 +36,11 @@ public interface ICommandMode {
/**
* Get the name of this command mode
*
- * @return The name of this command mode, which is "crawler" by default
+ * @return The name of this command mode, which is the empty string by
+ * default
*/
public default String getName() {
- return "crawler";
+ return "";
}
/**
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/FormattedInputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/FormattedInputPanel.java
new file mode 100644
index 0000000..f11c3a8
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/FormattedInputPanel.java
@@ -0,0 +1,66 @@
+package bjc.utils.gui;
+
+import java.util.function.Consumer;
+
+import javax.swing.JFormattedTextField;
+import javax.swing.JFormattedTextField.AbstractFormatter;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import bjc.utils.gui.layout.HLayout;
+
+/**
+ * A simple panel allowing for input of a single formatted value
+ *
+ * @author ben
+ *
+ * @param <InputVal>
+ * The type of value being formatted
+ */
+public class FormattedInputPanel<InputVal> extends JPanel {
+ private static final long serialVersionUID = 5232016563558588031L;
+ private JFormattedTextField field;
+
+ /**
+ * Create a new formatted input panel
+ *
+ * @param label
+ * The label for this panel
+ * @param length
+ * The length of this panel
+ * @param formatter
+ * The formatter to use for input
+ * @param valueReciever
+ * The action to call whenever the value changes
+ */
+ @SuppressWarnings("unchecked")
+ public FormattedInputPanel(String label, int length,
+ AbstractFormatter formatter,
+ Consumer<InputVal> valueReciever) {
+ setLayout(new HLayout(2));
+
+ JLabel lab = new JLabel(label);
+ field = new JFormattedTextField(formatter);
+
+ field.setColumns(length);
+ field.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
+ field.addPropertyChangeListener("value", (event) -> {
+ // This is safe, because InputVal should be the type of
+ // whatever object the formatter is returning
+ valueReciever.accept((InputVal) field.getValue());
+ });
+
+ add(lab);
+ add(field);
+ }
+
+ /**
+ * Reset the value in this panel to a specified value
+ *
+ * @param value
+ * The value to set the panel to
+ */
+ public void resetValues(InputVal value) {
+ field.setValue(value);
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java
new file mode 100644
index 0000000..4cbfb61
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java
@@ -0,0 +1,60 @@
+package bjc.utils.gui;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+
+import bjc.utils.data.IHolder;
+import bjc.utils.gui.layout.HLayout;
+
+/**
+ * A panel that outputs a value bound to a {@link IHolder}
+ *
+ * @author ben
+ *
+ */
+public class HolderOutputPanel extends JPanel {
+ private static final long serialVersionUID = 166573313903782080L;
+ private Timer updateTimer;
+ private JLabel value;
+
+ /**
+ * Create a new display panel, backed by a holder
+ *
+ * @param lab
+ * The label to attach to this field
+ * @param val
+ * The holder to get the value from
+ * @param nDelay
+ * The delay in ms between value updates
+ */
+ public HolderOutputPanel(String lab, IHolder<String> val, int nDelay) {
+ setLayout(new HLayout(2));
+
+ JLabel label = new JLabel(lab);
+ value = new JLabel(val.getValue() + " (stopped)");
+
+ updateTimer = new Timer(nDelay, (event) -> {
+ value.setText(val.getValue());
+ });
+
+ add(label);
+ add(value);
+ }
+
+ /**
+ * Start updating the contents of the field from the holder
+ */
+ public void startUpdating() {
+ updateTimer.start();
+ }
+
+ /**
+ * Stop updating the contents of the field from the holder
+ */
+ public void stopUpdating() {
+ updateTimer.stop();
+
+ value.setText(value.getText() + " (stopped)");
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SliderInputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SliderInputPanel.java
new file mode 100644
index 0000000..0988f0c
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/SliderInputPanel.java
@@ -0,0 +1,196 @@
+package bjc.utils.gui;
+
+import java.text.ParseException;
+import java.util.function.Consumer;
+
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+
+import bjc.utils.gui.layout.HLayout;
+
+/**
+ * A simple input panel for a slider-controlled value and a manual-input
+ * field for setting the slider
+ *
+ * @author ben
+ *
+ */
+public class SliderInputPanel extends JPanel {
+ private final class NumberFormatter
+ extends JFormattedTextField.AbstractFormatter {
+ private static final long serialVersionUID = -4448291795913908270L;
+
+ private int minValue;
+ private int maxValue;
+
+ private int initValue;
+
+ public NumberFormatter(SliderSettings settings) {
+ minValue = settings.minValue;
+ maxValue = settings.maxValue;
+
+ initValue = settings.initValue;
+ }
+
+ @Override
+ public Object stringToValue(String text) throws ParseException {
+ try {
+ int val = Integer.parseInt(text);
+
+ if (val < minValue) {
+ throw new ParseException(
+ "Value must be greater than " + minValue, 0);
+ } else if (val > maxValue) {
+ throw new ParseException(
+ "Value must be smaller than " + maxValue, 0);
+ } else {
+ return val;
+ }
+ } catch (NumberFormatException nfex) {
+ ParseException pex = new ParseException(
+ "Value must be a valid integer", 0);
+
+ pex.initCause(nfex);
+
+ throw pex;
+ }
+ }
+
+ @Override
+ public String valueToString(Object value) throws ParseException {
+ if (value == null) {
+ return Integer.toString(initValue);
+ }
+
+ return Integer.toString((Integer) value);
+ }
+ }
+
+ /**
+ * Represents the settings for a slider
+ *
+ * @author ben
+ *
+ */
+ public static class SliderSettings {
+ /**
+ * The minimum value of the slider
+ */
+ public final int minValue;
+ /**
+ * The maximum value of the slider
+ */
+ public final int maxValue;
+
+ /**
+ * The initial value of the slider
+ */
+ public final int initValue;
+
+ /**
+ * Create a new slider settings, with the initial value in the
+ * middle
+ *
+ * @param min
+ * The minimum value of the slider
+ * @param max
+ * The maximum value of the slider
+ */
+ public SliderSettings(int min, int max) {
+ this(min, max, (min + max) / 2);
+ }
+
+ /**
+ * Create a new set of slider sttings
+ *
+ * @param min
+ * The minimum slider value
+ * @param max
+ * The maximum slider value
+ * @param init
+ * Th initial slider value
+ */
+ public SliderSettings(int min, int max, int init) {
+ minValue = min;
+ maxValue = max;
+
+ initValue = init;
+ }
+ }
+
+ private static final long serialVersionUID = 2956394160569961404L;
+ private JSlider slider;
+ private JFormattedTextField field;
+
+ /**
+ * Create a new slider input panel
+ *
+ * @param lab
+ * The label for the field
+ * @param settings
+ * The settings for slider values
+ * @param majorTick
+ * The setting for where to place big ticks
+ * @param minorTick
+ * The setting for where to place small ticks
+ * @param action
+ * The action to execute for a given value
+ */
+ public SliderInputPanel(String lab, SliderSettings settings,
+ int majorTick, int minorTick, Consumer<Integer> action) {
+ setLayout(new HLayout(3));
+
+ JLabel label = new JLabel(lab);
+
+ slider = new JSlider(settings.minValue, settings.maxValue,
+ settings.initValue);
+ field = new JFormattedTextField(new NumberFormatter(settings));
+
+ slider.setMajorTickSpacing(majorTick);
+ slider.setMinorTickSpacing(minorTick);
+ slider.setPaintTicks(true);
+ slider.setPaintLabels(true);
+
+ slider.addChangeListener((event) -> {
+ if (slider.getValueIsAdjusting()) {
+ // Do nothing
+ } else {
+ int sliderVal = slider.getValue();
+
+ field.setValue(sliderVal);
+
+ action.accept(sliderVal);
+ }
+ });
+
+ field.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
+ field.setColumns(15);
+ field.addPropertyChangeListener("value", (event) -> {
+ Object value = field.getValue();
+
+ if (value == null) {
+ // Do nothing
+ } else {
+ slider.setValue((Integer) value);
+ }
+ });
+
+ add(label);
+ add(slider);
+ add(field);
+ }
+
+ /**
+ * Reset the values in this panel to a specified value
+ *
+ * @param value
+ * The value to reset the fields to
+ */
+ public void resetValues(int value) {
+ slider.setValue(value);
+
+ field.setValue(value);
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
index 636bf31..2ea23c6 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
@@ -16,10 +16,10 @@ import bjc.utils.funcutils.StringUtils;
*
* @author ben
*
- * @param <E>
+ * @param <TokenType>
* The type of tokens being shunted
*/
-public class ShuntingYard<E> {
+public class ShuntingYard<TokenType> {
/**
* A enum representing the fundamental operator types
*
@@ -32,17 +32,18 @@ public class ShuntingYard<E> {
*/
ADD(1),
/**
- * Represents division
+ * Represents subtraction
*/
- DIVIDE(4),
+ SUBTRACT(2),
+
/**
* Represents multiplication
*/
MULTIPLY(3),
/**
- * Represents subtraction
+ * Represents division
*/
- SUBTRACT(2);
+ DIVIDE(4);
private final int precedence;
@@ -62,12 +63,13 @@ public class ShuntingYard<E> {
}
private final class TokenShunter implements Consumer<String> {
- private IFunctionalList<E> output;
- private Deque<String> stack;
- private Function<String, E> transform;
+ private IFunctionalList<TokenType> output;
+ private Deque<String> stack;
+ private Function<String, TokenType> transform;
- public TokenShunter(IFunctionalList<E> outpt, Deque<String> stack,
- Function<String, E> transform) {
+ public TokenShunter(IFunctionalList<TokenType> outpt,
+ Deque<String> stack,
+ Function<String, TokenType> transform) {
this.output = outpt;
this.stack = stack;
this.transform = transform;
@@ -159,11 +161,10 @@ public class ShuntingYard<E> {
return false;
}
- boolean hasHigherPrecedence = operators.get(rightOperator)
- .getPrecedence() >= operators.get(leftOperator)
- .getPrecedence();
+ int rightPrecedence = operators.get(rightOperator).getPrecedence();
+ int leftPrecedence = operators.get(leftOperator).getPrecedence();
- return hasHigherPrecedence;
+ return rightPrecedence >= leftPrecedence;
}
/**
@@ -175,15 +176,16 @@ public class ShuntingYard<E> {
* The function to use to transform strings to tokens
* @return A list of tokens in postfix notation
*/
- public IFunctionalList<E> postfix(IFunctionalList<String> input,
- Function<String, E> tokenTransformer) {
+ public IFunctionalList<TokenType> postfix(
+ IFunctionalList<String> input,
+ Function<String, TokenType> tokenTransformer) {
if (input == null) {
throw new NullPointerException("Input must not be null");
} else if (tokenTransformer == null) {
throw new NullPointerException("Transformer must not be null");
}
- IFunctionalList<E> output = new FunctionalList<>();
+ IFunctionalList<TokenType> output = new FunctionalList<>();
Deque<String> stack = new LinkedList<>();
@@ -199,14 +201,14 @@ public class ShuntingYard<E> {
/**
* Remove an operator from the list of shuntable operators
*
- * @param tok
+ * @param token
* The token representing the operator
*/
- public void removeOp(String tok) {
- if (tok == null) {
+ public void removeOp(String token) {
+ if (token == null) {
throw new NullPointerException("Token must not be null");
}
- operators.remove(tok);
+ operators.remove(token);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
index 4727124..9fb64cf 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
@@ -12,26 +12,26 @@ import bjc.utils.data.Pair;
import bjc.utils.funcdata.ITree;
import bjc.utils.funcdata.Tree;
-final class TokenTransformer<T> implements Consumer<T> {
- private final class OperatorHandler
- implements UnaryOperator<IPair<Deque<ITree<T>>, ITree<T>>> {
- private T element;
+final class TokenTransformer<TokenType> implements Consumer<TokenType> {
+ private final class OperatorHandler implements
+ UnaryOperator<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> {
+ private TokenType element;
- public OperatorHandler(T element) {
+ public OperatorHandler(TokenType element) {
this.element = element;
}
@Override
- public IPair<Deque<ITree<T>>, ITree<T>> apply(
- IPair<Deque<ITree<T>>, ITree<T>> pair) {
- return pair.bind((queuedASTs, currentAST) -> {
+ public IPair<Deque<ITree<TokenType>>, ITree<TokenType>> apply(
+ IPair<Deque<ITree<TokenType>>, ITree<TokenType>> pair) {
+ return pair.bindLeft((queuedASTs) -> {
return handleOperator(queuedASTs);
});
}
- private IPair<Deque<ITree<T>>, ITree<T>> handleOperator(
- Deque<ITree<T>> queuedASTs) {
- ITree<T> newAST;
+ private IPair<Deque<ITree<TokenType>>, ITree<TokenType>>
+ handleOperator(Deque<ITree<TokenType>> queuedASTs) {
+ ITree<TokenType> newAST;
if (isSpecialOperator.test(element)) {
newAST = handleSpecialOperator.apply(element)
@@ -45,8 +45,8 @@ final class TokenTransformer<T> implements Consumer<T> {
+ queuedASTs.peek());
}
- ITree<T> rightAST = queuedASTs.pop();
- ITree<T> leftAST = queuedASTs.pop();
+ ITree<TokenType> rightAST = queuedASTs.pop();
+ ITree<TokenType> leftAST = queuedASTs.pop();
newAST = new Tree<>(element, leftAST, rightAST);
}
@@ -57,15 +57,18 @@ final class TokenTransformer<T> implements Consumer<T> {
}
}
- private IHolder<IPair<Deque<ITree<T>>, ITree<T>>> initialState;
- private Predicate<T> operatorPredicate;
- private Predicate<T> isSpecialOperator;
- private Function<T, Function<Deque<ITree<T>>, ITree<T>>> handleSpecialOperator;
+ private IHolder<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> initialState;
+
+ private Predicate<TokenType> operatorPredicate;
+
+ private Predicate<TokenType> isSpecialOperator;
+ private Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator;
public TokenTransformer(
- IHolder<IPair<Deque<ITree<T>>, ITree<T>>> initialState,
- Predicate<T> operatorPredicate, Predicate<T> isSpecialOperator,
- Function<T, Function<Deque<ITree<T>>, ITree<T>>> handleSpecialOperator) {
+ IHolder<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> initialState,
+ Predicate<TokenType> operatorPredicate,
+ Predicate<TokenType> isSpecialOperator,
+ Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator) {
this.initialState = initialState;
this.operatorPredicate = operatorPredicate;
this.isSpecialOperator = isSpecialOperator;
@@ -73,20 +76,16 @@ final class TokenTransformer<T> implements Consumer<T> {
}
@Override
- public void accept(T element) {
+ public void accept(TokenType element) {
if (operatorPredicate.test(element)) {
initialState.transform(new OperatorHandler(element));
} else {
- ITree<T> newAST = new Tree<>(element);
+ ITree<TokenType> newAST = new Tree<>(element);
- initialState.doWith((pair) -> {
- pair.doWith((queue, currentAST) -> {
+ initialState.transform((pair) -> {
+ return pair.bindLeft((queue) -> {
queue.push(newAST);
- });
- });
- initialState.transform((pair) -> {
- return pair.bind((queue, currentAST) -> {
return new Pair<>(queue, newAST);
});
});
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
index 2d2a69e..283d16e 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
@@ -24,7 +24,7 @@ public class TreeConstructor {
*
* Only binary operators are accepted.
*
- * @param <T>
+ * @param <TokenType>
* The elements of the parse tree
* @param tokens
* The list of tokens to build a tree from
@@ -33,8 +33,9 @@ public class TreeConstructor {
* operator
* @return A AST from the expression
*/
- public static <T> ITree<T> constructTree(IFunctionalList<T> tokens,
- Predicate<T> operatorPredicate) {
+ public static <TokenType> ITree<TokenType> constructTree(
+ IFunctionalList<TokenType> tokens,
+ Predicate<TokenType> operatorPredicate) {
return constructTree(tokens, operatorPredicate, (op) -> false,
null);
}
@@ -45,7 +46,7 @@ public class TreeConstructor {
* Only binary operators are accepted by default. Use the last two
* parameters to handle non-binary operators
*
- * @param <T>
+ * @param <TokenType>
* The elements of the parse tree
* @param tokens
* The list of tokens to build a tree from
@@ -63,9 +64,11 @@ public class TreeConstructor {
* interface. Maybe there's a better way to express how that
* works
*/
- public static <T> ITree<T> constructTree(IFunctionalList<T> tokens,
- Predicate<T> operatorPredicate, Predicate<T> isSpecialOperator,
- Function<T, Function<Deque<ITree<T>>, ITree<T>>> handleSpecialOperator) {
+ public static <TokenType> ITree<TokenType> constructTree(
+ IFunctionalList<TokenType> tokens,
+ Predicate<TokenType> operatorPredicate,
+ Predicate<TokenType> isSpecialOperator,
+ Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator) {
if (tokens == null) {
throw new NullPointerException("Tokens must not be null");
} else if (operatorPredicate == null) {
@@ -76,8 +79,8 @@ public class TreeConstructor {
"Special operator determiner must not be null");
}
- IHolder<IPair<Deque<ITree<T>>, ITree<T>>> initialState = new Identity<>(
- new Pair<>(new LinkedList<>(), null));
+ IHolder<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> initialState =
+ new Identity<>(new Pair<>(new LinkedList<>(), null));
tokens.forEach(
new TokenTransformer<>(initialState, operatorPredicate,