mirror of
https://github.com/DanilaFe/abacus
synced 2024-12-22 23:40:08 -08:00
Add more comments.
This commit is contained in:
parent
1b9dc5514e
commit
08999350f4
|
@ -4,26 +4,61 @@ import org.nwapw.abacus.function.Function;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A plugin class that can be externally implemented and loaded via the
|
||||||
|
* plugin manager. Plugins provide functionality to the calculator
|
||||||
|
* with the "hasFunction" and "getFunction" functions,
|
||||||
|
* and can use "registerFunction" and "functionFor" for
|
||||||
|
* loading internally.
|
||||||
|
*/
|
||||||
public abstract class Plugin {
|
public abstract class Plugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hash map of functions mapped to their string names.
|
||||||
|
*/
|
||||||
private HashMap<String, Function> functions;
|
private HashMap<String, Function> functions;
|
||||||
|
/**
|
||||||
|
* The plugin manager in which to search for functions
|
||||||
|
* not inside this package,
|
||||||
|
*/
|
||||||
private PluginManager manager;
|
private PluginManager manager;
|
||||||
|
|
||||||
private Plugin(){ }
|
private Plugin(){ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new plugin with the given PluginManager.
|
||||||
|
* @param manager the manager controlling this plugin.
|
||||||
|
*/
|
||||||
public Plugin(PluginManager manager) {
|
public Plugin(PluginManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
functions = new HashMap<>();
|
functions = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the current plugin provides the given function name.
|
||||||
|
* @param functionName the name of the function provided.
|
||||||
|
* @return true of the function exists, false if it doesn't.
|
||||||
|
*/
|
||||||
public final boolean hasFunction(String functionName) {
|
public final boolean hasFunction(String functionName) {
|
||||||
return functions.containsKey(functionName);
|
return functions.containsKey(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a function under the given function name.
|
||||||
|
* @param functionName the name of the function to get
|
||||||
|
* @return the function, or null if this plugin doesn't provide it.
|
||||||
|
*/
|
||||||
public final Function getFunction(String functionName) {
|
public final Function getFunction(String functionName) {
|
||||||
return functions.get(functionName);
|
return functions.get(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used in load(). Registers a function abstract class with the
|
||||||
|
* plugin internally, which makes it accessible to the plugin manager.
|
||||||
|
* @param name the name to register by.
|
||||||
|
* @param toRegister the function implementation.
|
||||||
|
* @return true if the function was registered successfully, false if not.
|
||||||
|
*/
|
||||||
protected final boolean registerFunction(String name, Function toRegister) {
|
protected final boolean registerFunction(String name, Function toRegister) {
|
||||||
if(functionFor(name) == null){
|
if(functionFor(name) == null){
|
||||||
functions.put(name, toRegister);
|
functions.put(name, toRegister);
|
||||||
|
@ -32,12 +67,22 @@ public abstract class Plugin {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the PluginManager for the given function name.
|
||||||
|
* This can be used by the plugins internally in order to call functions
|
||||||
|
* they do not provide.
|
||||||
|
* @param name then name for which to search
|
||||||
|
* @return the resulting function, or null if none was found for that name.
|
||||||
|
*/
|
||||||
protected final Function functionFor(String name) {
|
protected final Function functionFor(String name) {
|
||||||
Plugin ownerPlugin = manager.pluginForFunction(name);
|
return manager.functionFor(name);
|
||||||
if(ownerPlugin == null) return null;
|
|
||||||
return ownerPlugin.getFunction(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract method to be overridden by plugin implementation, in which the plugins
|
||||||
|
* are supposed to register the functions they provide and do any other
|
||||||
|
* necessary setup.
|
||||||
|
*/
|
||||||
public abstract void load();
|
public abstract void load();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@ import org.nwapw.abacus.function.Function;
|
||||||
import org.nwapw.abacus.number.NaiveNumber;
|
import org.nwapw.abacus.number.NaiveNumber;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The plugin providing standard functions such as addition and subtraction to
|
||||||
|
* the calculator.
|
||||||
|
*/
|
||||||
public class StandardPlugin extends Plugin {
|
public class StandardPlugin extends Plugin {
|
||||||
|
|
||||||
public StandardPlugin(PluginManager manager) {
|
public StandardPlugin(PluginManager manager) {
|
||||||
|
|
|
@ -3,22 +3,44 @@ package org.nwapw.abacus.tree;
|
||||||
import org.nwapw.abacus.number.NaiveNumber;
|
import org.nwapw.abacus.number.NaiveNumber;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node implementation that represents a single number.
|
||||||
|
*/
|
||||||
public class NumberNode extends TreeNode {
|
public class NumberNode extends TreeNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number that is represented by this number node.
|
||||||
|
*/
|
||||||
private NumberInterface number;
|
private NumberInterface number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a number node with no number.
|
||||||
|
*/
|
||||||
public NumberNode(){
|
public NumberNode(){
|
||||||
number = null;
|
number = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new number node with the given double value.
|
||||||
|
* @param value the value to use.
|
||||||
|
*/
|
||||||
public NumberNode(double value){
|
public NumberNode(double value){
|
||||||
number = new NaiveNumber(value);
|
number = new NaiveNumber(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new number node with the given string value, converted
|
||||||
|
* to a double.
|
||||||
|
* @param value the value.
|
||||||
|
*/
|
||||||
public NumberNode(String value){
|
public NumberNode(String value){
|
||||||
this(Double.parseDouble(value));
|
this(Double.parseDouble(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number value of this node.
|
||||||
|
* @return the number value of this node.
|
||||||
|
*/
|
||||||
public NumberInterface getNumber() {
|
public NumberInterface getNumber() {
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,81 @@
|
||||||
package org.nwapw.abacus.tree;
|
package org.nwapw.abacus.tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree node that represents an operation being applied to two operands.
|
||||||
|
*/
|
||||||
public class OpNode extends TreeNode {
|
public class OpNode extends TreeNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation being applied.
|
||||||
|
*/
|
||||||
private String operation;
|
private String operation;
|
||||||
|
/**
|
||||||
|
* The left node of the operation.
|
||||||
|
*/
|
||||||
private TreeNode left;
|
private TreeNode left;
|
||||||
|
/**
|
||||||
|
* The right node of the operation.
|
||||||
|
*/
|
||||||
private TreeNode right;
|
private TreeNode right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new operation node with the given operation
|
||||||
|
* and no child nodes.
|
||||||
|
* @param operation the operation.
|
||||||
|
*/
|
||||||
public OpNode(String operation){
|
public OpNode(String operation){
|
||||||
this(operation, null, null);
|
this(operation, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new operation node with the given operation
|
||||||
|
* and child nodes.
|
||||||
|
* @param operation the operation.
|
||||||
|
* @param left the left node of the expression.
|
||||||
|
* @param right the right node of the expression.
|
||||||
|
*/
|
||||||
public OpNode(String operation, TreeNode left, TreeNode right){
|
public OpNode(String operation, TreeNode left, TreeNode right){
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operation in this node.
|
||||||
|
* @return the operation in this node.
|
||||||
|
*/
|
||||||
public String getOperation() {
|
public String getOperation() {
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the left sub-expression of this node.
|
||||||
|
* @return the left node.
|
||||||
|
*/
|
||||||
public TreeNode getLeft() {
|
public TreeNode getLeft() {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the left sub-expression of this node.
|
||||||
|
* @param left the sub-expression to apply.
|
||||||
|
*/
|
||||||
public void setLeft(TreeNode left) {
|
public void setLeft(TreeNode left) {
|
||||||
this.left = left;
|
this.left = left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the right sub-expression of this node.
|
||||||
|
* @return the right node.
|
||||||
|
*/
|
||||||
public TreeNode getRight() {
|
public TreeNode getRight() {
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the right sub-expression of this node.
|
||||||
|
* @param right the sub-expression to apply.
|
||||||
|
*/
|
||||||
public void setRight(TreeNode right) {
|
public void setRight(TreeNode right) {
|
||||||
this.right = right;
|
this.right = right;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package org.nwapw.abacus.tree;
|
package org.nwapw.abacus.tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to represent the associativity of an operator.
|
||||||
|
*/
|
||||||
public enum OperatorAssociativity {
|
public enum OperatorAssociativity {
|
||||||
LEFT, RIGHT
|
LEFT, RIGHT
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package org.nwapw.abacus.tree;
|
package org.nwapw.abacus.tree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to represent the type of the token that has been matched
|
||||||
|
* by the lexer.
|
||||||
|
*/
|
||||||
public enum TokenType {
|
public enum TokenType {
|
||||||
|
|
||||||
ANY(0), OP(1), NUM(2), WORD(3), OPEN_PARENTH(4), CLOSE_PARENTH(5);
|
ANY(0), OP(1), NUM(2), WORD(3), OPEN_PARENTH(4), CLOSE_PARENTH(5);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The priority by which this token gets sorted.
|
||||||
|
*/
|
||||||
public final int priority;
|
public final int priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new token type with the given priority.
|
||||||
|
* @param priority the priority of this token type.
|
||||||
|
*/
|
||||||
TokenType(int priority){
|
TokenType(int priority){
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,14 @@ import org.nwapw.abacus.lexing.pattern.Match;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class that represents an expression tree node.
|
||||||
|
*/
|
||||||
public abstract class TreeNode {
|
public abstract class TreeNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lexer used to lex tokens.
|
||||||
|
*/
|
||||||
private static Lexer<TokenType> lexer = new Lexer<TokenType>(){{
|
private static Lexer<TokenType> lexer = new Lexer<TokenType>(){{
|
||||||
register(".", TokenType.ANY);
|
register(".", TokenType.ANY);
|
||||||
register("\\+|-|\\*|/|^", TokenType.OP);
|
register("\\+|-|\\*|/|^", TokenType.OP);
|
||||||
|
@ -15,6 +21,9 @@ public abstract class TreeNode {
|
||||||
register("\\(", TokenType.OPEN_PARENTH);
|
register("\\(", TokenType.OPEN_PARENTH);
|
||||||
register("\\)", TokenType.CLOSE_PARENTH);
|
register("\\)", TokenType.CLOSE_PARENTH);
|
||||||
}};
|
}};
|
||||||
|
/**
|
||||||
|
* A map that maps operations to their precedence.
|
||||||
|
*/
|
||||||
private static HashMap<String, Integer> precedenceMap = new HashMap<String, Integer>(){{
|
private static HashMap<String, Integer> precedenceMap = new HashMap<String, Integer>(){{
|
||||||
put("+", 0);
|
put("+", 0);
|
||||||
put("-", 0);
|
put("-", 0);
|
||||||
|
@ -22,6 +31,9 @@ public abstract class TreeNode {
|
||||||
put("/", 1);
|
put("/", 1);
|
||||||
put("^", 2);
|
put("^", 2);
|
||||||
}};
|
}};
|
||||||
|
/**
|
||||||
|
* A map that maps operations to their associativity.
|
||||||
|
*/
|
||||||
private static HashMap<String, OperatorAssociativity> associativityMap =
|
private static HashMap<String, OperatorAssociativity> associativityMap =
|
||||||
new HashMap<String, OperatorAssociativity>() {{
|
new HashMap<String, OperatorAssociativity>() {{
|
||||||
put("+", OperatorAssociativity.LEFT);
|
put("+", OperatorAssociativity.LEFT);
|
||||||
|
@ -31,12 +43,26 @@ public abstract class TreeNode {
|
||||||
put("^", OperatorAssociativity.RIGHT);
|
put("^", OperatorAssociativity.RIGHT);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator used to sort token types.
|
||||||
|
*/
|
||||||
private static Comparator<TokenType> tokenSorter = Comparator.comparingInt(e -> e.priority);
|
private static Comparator<TokenType> tokenSorter = Comparator.comparingInt(e -> e.priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizes a string, converting it into matches
|
||||||
|
* @param string the string to tokenize.
|
||||||
|
* @return the list of tokens produced.
|
||||||
|
*/
|
||||||
public static ArrayList<Match<TokenType>> tokenize(String string){
|
public static ArrayList<Match<TokenType>> tokenize(String string){
|
||||||
return lexer.lexAll(string, 0, tokenSorter);
|
return lexer.lexAll(string, 0, tokenSorter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rearranges tokens into a postfix list, using Shunting Yard.
|
||||||
|
* @param source the source string.
|
||||||
|
* @param from the tokens to be rearranged.
|
||||||
|
* @return the resulting list of rearranged tokens.
|
||||||
|
*/
|
||||||
public static ArrayList<Match<TokenType>> intoPostfix(String source, ArrayList<Match<TokenType>> from){
|
public static ArrayList<Match<TokenType>> intoPostfix(String source, ArrayList<Match<TokenType>> from){
|
||||||
ArrayList<Match<TokenType>> output = new ArrayList<>();
|
ArrayList<Match<TokenType>> output = new ArrayList<>();
|
||||||
Stack<Match<TokenType>> tokenStack = new Stack<>();
|
Stack<Match<TokenType>> tokenStack = new Stack<>();
|
||||||
|
@ -78,6 +104,12 @@ public abstract class TreeNode {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a tree recursively from a list of tokens.
|
||||||
|
* @param source the source string.
|
||||||
|
* @param matches the list of tokens from the source string.
|
||||||
|
* @return the construct tree expression.
|
||||||
|
*/
|
||||||
public static TreeNode fromStringRecursive(String source, ArrayList<Match<TokenType>> matches){
|
public static TreeNode fromStringRecursive(String source, ArrayList<Match<TokenType>> matches){
|
||||||
if(matches.size() == 0) return null;
|
if(matches.size() == 0) return null;
|
||||||
Match<TokenType> match = matches.remove(0);
|
Match<TokenType> match = matches.remove(0);
|
||||||
|
@ -92,6 +124,11 @@ public abstract class TreeNode {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tree node from a string.
|
||||||
|
* @param string the string to create a node from.
|
||||||
|
* @return the resulting tree.
|
||||||
|
*/
|
||||||
public static TreeNode fromString(String string){
|
public static TreeNode fromString(String string){
|
||||||
ArrayList<Match<TokenType>> matches = intoPostfix(string, tokenize(string));
|
ArrayList<Match<TokenType>> matches = intoPostfix(string, tokenize(string));
|
||||||
if(matches == null) return null;
|
if(matches == null) return null;
|
||||||
|
|
|
@ -3,26 +3,76 @@ package org.nwapw.abacus.window;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main UI window for the calculator.
|
||||||
|
*/
|
||||||
public class Window extends JFrame {
|
public class Window extends JFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of outputs from the calculator.
|
||||||
|
*/
|
||||||
private String history;
|
private String history;
|
||||||
|
/**
|
||||||
|
* The last output by the calculator.
|
||||||
|
*/
|
||||||
private String lastOutput;
|
private String lastOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The panel where the output occurs.
|
||||||
|
*/
|
||||||
private JPanel outputPanel;
|
private JPanel outputPanel;
|
||||||
|
/**
|
||||||
|
* The text area reserved for the last output.
|
||||||
|
*/
|
||||||
private JTextArea lastOutputArea;
|
private JTextArea lastOutputArea;
|
||||||
|
/**
|
||||||
|
* The text area used for all history output.
|
||||||
|
*/
|
||||||
private JTextArea historyArea;
|
private JTextArea historyArea;
|
||||||
|
/**
|
||||||
|
* The scroll pane for the history area.
|
||||||
|
*/
|
||||||
private JScrollPane historyAreaScroll;
|
private JScrollPane historyAreaScroll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The panel where the input occurs.
|
||||||
|
*/
|
||||||
private JPanel inputPanel;
|
private JPanel inputPanel;
|
||||||
|
/**
|
||||||
|
* The input text field.
|
||||||
|
*/
|
||||||
private JTextField inputField;
|
private JTextField inputField;
|
||||||
|
/**
|
||||||
|
* The "submit" button.
|
||||||
|
*/
|
||||||
private JButton inputEnterButton;
|
private JButton inputEnterButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The side panel for separate configuration.
|
||||||
|
*/
|
||||||
private JPanel sidePanel;
|
private JPanel sidePanel;
|
||||||
|
/**
|
||||||
|
* Panel for elements relating to number
|
||||||
|
* system selection.
|
||||||
|
*/
|
||||||
private JPanel numberSystemPanel;
|
private JPanel numberSystemPanel;
|
||||||
|
/**
|
||||||
|
* The possible list of number systems.
|
||||||
|
*/
|
||||||
private JComboBox<String> numberSystemList;
|
private JComboBox<String> numberSystemList;
|
||||||
private JButton functionSelectButton;
|
/**
|
||||||
|
* The panel for elements relating to
|
||||||
|
* function selection.
|
||||||
|
*/
|
||||||
private JPanel functionSelectPanel;
|
private JPanel functionSelectPanel;
|
||||||
|
/**
|
||||||
|
* The list of functions available to the user.
|
||||||
|
*/
|
||||||
private JComboBox<String> functionList;
|
private JComboBox<String> functionList;
|
||||||
|
/**
|
||||||
|
* The button used to select a function.
|
||||||
|
*/
|
||||||
|
private JButton functionSelectButton;
|
||||||
|
|
||||||
public Window() {
|
public Window() {
|
||||||
super();
|
super();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user