add stop on node

This commit is contained in:
rileyJones 2017-08-02 11:04:35 -07:00
parent f464bcff6f
commit 051be8d49e
8 changed files with 115 additions and 70 deletions

View File

@ -53,7 +53,10 @@ public class Abacus {
* from a string.
*/
private TreeBuilder treeBuilder;
private Window window;
public boolean getStop(){
return window.getStop();
}
/**
* Creates a new instance of the Abacus calculator.
*/
@ -133,7 +136,7 @@ public class Abacus {
* @return the resulting tree, null if the tree builder or the produced tree are null.
*/
public TreeNode parseString(String input) {
return treeBuilder.fromString(input);
return treeBuilder.fromString(input,this);
}
/**
@ -165,4 +168,8 @@ public class Abacus {
}
return null;
}
public void setWindow(Window window) {
this.window = window;
}
}

View File

@ -1,5 +1,6 @@
package org.nwapw.abacus.parsing;
import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.tree.TreeNode;
import java.util.List;
@ -18,5 +19,5 @@ public interface Parser<T> {
* @param tokens the tokens to construct a tree from.
* @return the constructed tree, or null on error.
*/
public TreeNode constructTree(List<T> tokens);
public TreeNode constructTree(List<T> tokens,Abacus trace);
}

View File

@ -34,6 +34,8 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
*/
private Map<String, OperatorType> typeMap;
//private Abacus trace;
/**
* Creates a new Shunting Yard parser with the given Abacus instance.
*
@ -116,7 +118,8 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
* @param matches the list of tokens from the source string.
* @return the construct tree expression.
*/
public TreeNode constructRecursive(List<Match<TokenType>> matches) {
public TreeNode constructRecursive(List<Match<TokenType>> matches,Abacus trace) {
//this.trace = trace;
if (matches.size() == 0) return null;
Match<TokenType> match = matches.remove(0);
TokenType matchType = match.getType();
@ -124,22 +127,22 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
String operator = match.getContent();
OperatorType type = typeMap.get(operator);
if (type == OperatorType.BINARY_INFIX) {
TreeNode right = constructRecursive(matches);
TreeNode left = constructRecursive(matches);
TreeNode right = constructRecursive(matches,trace);
TreeNode left = constructRecursive(matches,trace);
if (left == null || right == null) return null;
else return new BinaryInfixNode(operator, left, right);
else return new BinaryInfixNode(operator, left, right,trace);
} else {
TreeNode applyTo = constructRecursive(matches);
TreeNode applyTo = constructRecursive(matches,trace);
if (applyTo == null) return null;
else return new UnaryPrefixNode(operator, applyTo);
else return new UnaryPrefixNode(operator, applyTo,trace);
}
} else if (matchType == TokenType.NUM) {
return new NumberNode(abacus.numberFromString(match.getContent()));
} else if (matchType == TokenType.FUNCTION) {
String functionName = match.getContent();
FunctionNode node = new FunctionNode(functionName);
FunctionNode node = new FunctionNode(functionName,trace);
while (!matches.isEmpty() && matches.get(0).getType() != TokenType.INTERNAL_FUNCTION_END) {
TreeNode argument = constructRecursive(matches);
TreeNode argument = constructRecursive(matches,trace);
if (argument == null) return null;
node.prependChild(argument);
}
@ -151,10 +154,10 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
}
@Override
public TreeNode constructTree(List<Match<TokenType>> tokens) {
public TreeNode constructTree(List<Match<TokenType>> tokens,Abacus trace) {
tokens = intoPostfix(new ArrayList<>(tokens));
Collections.reverse(tokens);
return constructRecursive(tokens);
return constructRecursive(tokens,trace);
}
@Override

View File

@ -1,5 +1,6 @@
package org.nwapw.abacus.parsing;
import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.tree.TreeNode;
import java.util.List;
@ -41,10 +42,10 @@ public class TreeBuilder<T> {
* @param input the string to parse into a tree.
* @return the resulting tree.
*/
public TreeNode fromString(String input) {
public TreeNode fromString(String input,Abacus trace) {
List<T> tokens = tokenizer.tokenizeString(input);
if (tokens == null) return null;
return parser.constructTree(tokens);
return parser.constructTree(tokens,trace);
}
}

View File

@ -1,5 +1,7 @@
package org.nwapw.abacus.tree;
import org.nwapw.abacus.Abacus;
/**
* A tree node that represents an operation being applied to two operands.
*/
@ -17,6 +19,7 @@ public class BinaryInfixNode extends TreeNode {
* The right node of the operation.
*/
private TreeNode right;
private Abacus trace;
private BinaryInfixNode() {
}
@ -27,8 +30,8 @@ public class BinaryInfixNode extends TreeNode {
*
* @param operation the operation.
*/
public BinaryInfixNode(String operation) {
this(operation, null, null);
public BinaryInfixNode(String operation,Abacus trace) {
this(operation, null, null,trace);
}
/**
@ -39,10 +42,11 @@ public class BinaryInfixNode extends TreeNode {
* @param left the left node of the expression.
* @param right the right node of the expression.
*/
public BinaryInfixNode(String operation, TreeNode left, TreeNode right) {
public BinaryInfixNode(String operation, TreeNode left, TreeNode right,Abacus trace) {
this.operation = operation;
this.left = left;
this.right = right;
this.trace = trace;
}
/**
@ -92,10 +96,15 @@ public class BinaryInfixNode extends TreeNode {
@Override
public <T> T reduce(Reducer<T> reducer) {
T leftReduce = left.reduce(reducer);
T rightReduce = right.reduce(reducer);
if (leftReduce == null || rightReduce == null) return null;
return reducer.reduceNode(this, leftReduce, rightReduce);
if(!trace.getStop()) {
T leftReduce = left.reduce(reducer);
T rightReduce = right.reduce(reducer);
if (leftReduce == null || rightReduce == null) return null;
return reducer.reduceNode(this, leftReduce, rightReduce);
}
return null;
}
@Override

View File

@ -1,5 +1,7 @@
package org.nwapw.abacus.tree;
import org.nwapw.abacus.Abacus;
import java.util.ArrayList;
import java.util.List;
@ -16,6 +18,7 @@ public class FunctionNode extends TreeNode {
* The list of arguments to the function.
*/
private List<TreeNode> children;
private Abacus trace;
/**
* Creates a function node with no function.
@ -28,9 +31,10 @@ public class FunctionNode extends TreeNode {
*
* @param function the function name.
*/
public FunctionNode(String function) {
public FunctionNode(String function,Abacus trace) {
this.function = function;
children = new ArrayList<>();
this.trace = trace;
}
/**

View File

@ -1,5 +1,7 @@
package org.nwapw.abacus.tree;
import org.nwapw.abacus.Abacus;
public class UnaryPrefixNode extends TreeNode {
/**
@ -10,14 +12,15 @@ public class UnaryPrefixNode extends TreeNode {
* The tree node to apply the operation to.
*/
private TreeNode applyTo;
private Abacus trace;
/**
* Creates a new node with the given operation and no child.
*
* @param operation the operation for this node.
*/
public UnaryPrefixNode(String operation) {
this(operation, null);
public UnaryPrefixNode(String operation,Abacus trace) {
this(operation, null,trace);
}
/**
@ -26,16 +29,20 @@ public class UnaryPrefixNode extends TreeNode {
* @param operation the operation for this node.
* @param applyTo the node to apply the function to.
*/
public UnaryPrefixNode(String operation, TreeNode applyTo) {
public UnaryPrefixNode(String operation, TreeNode applyTo,Abacus trace) {
this.operation = operation;
this.applyTo = applyTo;
this.trace = trace;
}
@Override
public <T> T reduce(Reducer<T> reducer) {
Object reducedChild = applyTo.reduce(reducer);
if (reducedChild == null) return null;
return reducer.reduceNode(this, reducedChild);
if(!trace.getStop()) {
Object reducedChild = applyTo.reduce(reducer);
if (reducedChild == null) return null;
return reducer.reduceNode(this, reducedChild);
}
return null;
}
/**

View File

@ -16,15 +16,13 @@ import java.awt.event.MouseEvent;
*/
public class Window extends JFrame {
private boolean contComputation;
private static final String CALC_STRING = "Calculate";
private static final String SYNTAX_ERR_STRING = "Syntax Error";
private static final String EVAL_ERR_STRING = "Evaluation Error";
private static final String NUMBER_SYSTEM_LABEL = "Number Type:";
private static final String FUNCTION_LABEL = "Functions:";
private static final String STOP_STRING = "Stop";
private static final String STOPPED_TEXT = "Stopped";
/**
* Array of Strings to which the "calculate" button's text
* changes. For instance, in the graph tab, the name will
@ -124,62 +122,56 @@ public class Window extends JFrame {
*/
private Thread calculateThread;
/**
* Check if currently calculating
* Check if currently calculating.
*/
private boolean calculating;
private int count;
//private Object monitor;
/**
* Action listener that causes the input to be evaluated.
* Checks if thread should stop calculating.
*/
private boolean stopCalculating;
/**
* Test variable to check number of threads running in the calculator.
*/
private int count;
/**
* ActionListener that stops calculations.
*/
//*
private ActionListener stopListener = (event) -> {
//contComputation=false;
//Long pause = Long.MAX_VALUE;
//System.out.println(Thread.currentThread().getName());
//System.out.println(calculateThread.getName());
//calculateThread.suspend();
System.out.println(count++);
calculating = false;
/*
synchronized(calculateThread) {
try {
calculateThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//*/
};//*/
//System.out.println(count++); //Shows about how many calculation threads are running with the calculating=false command
//calculating = false; //Ignores result of calculation and allows for the start of a new calculation
stopCalculating = true; //Stops calculation at the next node check
//calculateThread.stop(); //Stops thread no matter what, Unsafe
};
/**
* Node check to get whether nodes should continue calculating.
* @return boolean stop calculations if true.
*/
public boolean getStop(){
return stopCalculating;
}
/**
* ActionListener that runs all calculations.
*/
private ActionListener evaluateListener = (event) -> {
//contComputation = true;
Runnable calculate = new Runnable() {
public void run() {
boolean skip = false;
calculating = true;
TreeNode parsedExpression = null;
parsedExpression = abacus.parseString(inputField.getText());
if (parsedExpression == null) {
lastOutputArea.setText(SYNTAX_ERR_STRING);
skip = true;
}
/*
try {
Thread.currentThread().sleep(9999);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IllegalMonitorStateException e){
e.printStackTrace();
}
//*/
//NumberInterface numberInterface = null;
if(!skip){
NumberInterface numberInterface = abacus.evaluateTree(parsedExpression);
if (numberInterface == null) {
lastOutputArea.setText(EVAL_ERR_STRING);
calculating = false;
stopCalculating = false;
return;
}
if(calculateThread.equals(Thread.currentThread())) {
@ -189,6 +181,7 @@ public class Window extends JFrame {
lastOutputArea.setText(lastOutput);
inputField.setText("");
calculating = false;
stopCalculating = false;
}
}
}
@ -208,6 +201,14 @@ public class Window extends JFrame {
evaluateListener,
null
};
/**
* Array of listeners that tell the stop button how to behave
* at a given input tab.
*/
private ActionListener[] stopListeners = {
stopListener,
null
};
/**
* Creates a new window with the given manager.
@ -217,6 +218,7 @@ public class Window extends JFrame {
public Window(Abacus abacus) {
this();
this.abacus = abacus;
abacus.setWindow(this);
}
/**
@ -225,29 +227,36 @@ public class Window extends JFrame {
private Window() {
super();
contComputation = true;
//variables related to when calculations occur
stopCalculating = false;
calculating = true;
lastOutput = "";
//default window properties
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(320, 480);
//initiates input objects
inputField = new JTextField();
inputEnterButton = new JButton(CALC_STRING);
inputStopButton = new JButton(STOP_STRING);
//adds input objects into Panel
inputPanel = new JPanel();
inputPanel.setLayout(new BorderLayout());
inputPanel.add(inputStopButton, BorderLayout.SOUTH);
inputPanel.add(inputField, BorderLayout.NORTH);
inputPanel.add(inputEnterButton, BorderLayout.CENTER);
//initiates output objects in calculator tab
historyModel = new HistoryTableModel();
historyTable = new JTable(historyModel);
historyScroll = new JScrollPane(historyTable);
lastOutputArea = new JTextArea(lastOutput);
lastOutputArea.setEditable(false);
//adds output objects into Panel
calculationPanel = new JPanel();
calculationPanel.setLayout(new BorderLayout());
calculationPanel.add(historyScroll, BorderLayout.CENTER);
@ -286,19 +295,23 @@ public class Window extends JFrame {
int selectionIndex = pane.getSelectedIndex();
boolean enabled = INPUT_ENABLED[selectionIndex];
ActionListener listener = listeners[selectionIndex];
ActionListener stopUsed = stopListeners[selectionIndex];
inputEnterButton.setText(BUTTON_NAMES[selectionIndex]);
inputField.setEnabled(enabled);
inputEnterButton.setEnabled(enabled);
inputStopButton.setEnabled(enabled);
for (ActionListener removingListener : inputEnterButton.getActionListeners()) {
inputEnterButton.removeActionListener(removingListener);
inputField.removeActionListener(removingListener);
}
for(ActionListener removingListener : inputStopButton.getActionListeners()){
inputStopButton.removeActionListener(removingListener);
}
if (listener != null) {
inputEnterButton.addActionListener(listener);
inputField.addActionListener(listener);
inputStopButton.addActionListener(listener);
inputStopButton.addActionListener(stopUsed);
}
});
add(pane, BorderLayout.CENTER);