diff --git a/src/org/nwapw/abacus/plugin/Plugin.java b/src/org/nwapw/abacus/plugin/Plugin.java index 11e10e1..4f662de 100644 --- a/src/org/nwapw/abacus/plugin/Plugin.java +++ b/src/org/nwapw/abacus/plugin/Plugin.java @@ -4,26 +4,61 @@ import org.nwapw.abacus.function.Function; 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 { + /** + * A hash map of functions mapped to their string names. + */ private HashMap functions; + /** + * The plugin manager in which to search for functions + * not inside this package, + */ private PluginManager manager; private Plugin(){ } + /** + * Creates a new plugin with the given PluginManager. + * @param manager the manager controlling this plugin. + */ public Plugin(PluginManager manager) { this.manager = manager; 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) { 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) { 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) { if(functionFor(name) == null){ functions.put(name, toRegister); @@ -32,12 +67,22 @@ public abstract class Plugin { 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) { - Plugin ownerPlugin = manager.pluginForFunction(name); - if(ownerPlugin == null) return null; - return ownerPlugin.getFunction(name); + return manager.functionFor(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(); } diff --git a/src/org/nwapw/abacus/plugin/StandardPlugin.java b/src/org/nwapw/abacus/plugin/StandardPlugin.java index 4c6ccee..0d718c3 100644 --- a/src/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/src/org/nwapw/abacus/plugin/StandardPlugin.java @@ -4,6 +4,10 @@ import org.nwapw.abacus.function.Function; import org.nwapw.abacus.number.NaiveNumber; 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 StandardPlugin(PluginManager manager) { diff --git a/src/org/nwapw/abacus/tree/NumberNode.java b/src/org/nwapw/abacus/tree/NumberNode.java index 1ad6da5..1ac4ea9 100644 --- a/src/org/nwapw/abacus/tree/NumberNode.java +++ b/src/org/nwapw/abacus/tree/NumberNode.java @@ -3,22 +3,44 @@ package org.nwapw.abacus.tree; import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NumberInterface; +/** + * A node implementation that represents a single number. + */ public class NumberNode extends TreeNode { + /** + * The number that is represented by this number node. + */ private NumberInterface number; + /** + * Creates a number node with no number. + */ public NumberNode(){ number = null; } + /** + * Creates a new number node with the given double value. + * @param value the value to use. + */ public NumberNode(double 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){ this(Double.parseDouble(value)); } + /** + * Gets the number value of this node. + * @return the number value of this node. + */ public NumberInterface getNumber() { return number; } diff --git a/src/org/nwapw/abacus/tree/OpNode.java b/src/org/nwapw/abacus/tree/OpNode.java index 0fcdaed..b338064 100644 --- a/src/org/nwapw/abacus/tree/OpNode.java +++ b/src/org/nwapw/abacus/tree/OpNode.java @@ -1,37 +1,81 @@ package org.nwapw.abacus.tree; +/** + * A tree node that represents an operation being applied to two operands. + */ public class OpNode extends TreeNode { + /** + * The operation being applied. + */ private String operation; + /** + * The left node of the operation. + */ private TreeNode left; + /** + * The right node of the operation. + */ private TreeNode right; + /** + * Creates a new operation node with the given operation + * and no child nodes. + * @param operation the operation. + */ public OpNode(String operation){ 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){ this.operation = operation; this.left = left; this.right = right; } + /** + * Gets the operation in this node. + * @return the operation in this node. + */ public String getOperation() { return operation; } + /** + * Gets the left sub-expression of this node. + * @return the left node. + */ public TreeNode getLeft() { return left; } + /** + * Sets the left sub-expression of this node. + * @param left the sub-expression to apply. + */ public void setLeft(TreeNode left) { this.left = left; } + /** + * Gets the right sub-expression of this node. + * @return the right node. + */ public TreeNode getRight() { return right; } + /** + * Sets the right sub-expression of this node. + * @param right the sub-expression to apply. + */ public void setRight(TreeNode right) { this.right = right; } diff --git a/src/org/nwapw/abacus/tree/OperatorAssociativity.java b/src/org/nwapw/abacus/tree/OperatorAssociativity.java index 78b633b..1d7f6df 100644 --- a/src/org/nwapw/abacus/tree/OperatorAssociativity.java +++ b/src/org/nwapw/abacus/tree/OperatorAssociativity.java @@ -1,5 +1,8 @@ package org.nwapw.abacus.tree; +/** + * Enum to represent the associativity of an operator. + */ public enum OperatorAssociativity { LEFT, RIGHT } diff --git a/src/org/nwapw/abacus/tree/TokenType.java b/src/org/nwapw/abacus/tree/TokenType.java index e0d7d97..ce92eb3 100644 --- a/src/org/nwapw/abacus/tree/TokenType.java +++ b/src/org/nwapw/abacus/tree/TokenType.java @@ -1,11 +1,22 @@ package org.nwapw.abacus.tree; +/** + * Enum to represent the type of the token that has been matched + * by the lexer. + */ public enum TokenType { 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; + /** + * Creates a new token type with the given priority. + * @param priority the priority of this token type. + */ TokenType(int priority){ this.priority = priority; } diff --git a/src/org/nwapw/abacus/tree/TreeNode.java b/src/org/nwapw/abacus/tree/TreeNode.java index 6581826..d549621 100644 --- a/src/org/nwapw/abacus/tree/TreeNode.java +++ b/src/org/nwapw/abacus/tree/TreeNode.java @@ -5,8 +5,14 @@ import org.nwapw.abacus.lexing.pattern.Match; import java.util.*; +/** + * An abstract class that represents an expression tree node. + */ public abstract class TreeNode { + /** + * The lexer used to lex tokens. + */ private static Lexer lexer = new Lexer(){{ register(".", TokenType.ANY); register("\\+|-|\\*|/|^", TokenType.OP); @@ -15,6 +21,9 @@ public abstract class TreeNode { register("\\(", TokenType.OPEN_PARENTH); register("\\)", TokenType.CLOSE_PARENTH); }}; + /** + * A map that maps operations to their precedence. + */ private static HashMap precedenceMap = new HashMap(){{ put("+", 0); put("-", 0); @@ -22,6 +31,9 @@ public abstract class TreeNode { put("/", 1); put("^", 2); }}; + /** + * A map that maps operations to their associativity. + */ private static HashMap associativityMap = new HashMap() {{ put("+", OperatorAssociativity.LEFT); @@ -31,12 +43,26 @@ public abstract class TreeNode { put("^", OperatorAssociativity.RIGHT); }}; + /** + * Comparator used to sort token types. + */ private static Comparator 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> tokenize(String string){ 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> intoPostfix(String source, ArrayList> from){ ArrayList> output = new ArrayList<>(); Stack> tokenStack = new Stack<>(); @@ -78,6 +104,12 @@ public abstract class TreeNode { 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> matches){ if(matches.size() == 0) return null; Match match = matches.remove(0); @@ -92,6 +124,11 @@ public abstract class TreeNode { 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){ ArrayList> matches = intoPostfix(string, tokenize(string)); if(matches == null) return null; diff --git a/src/org/nwapw/abacus/window/Window.java b/src/org/nwapw/abacus/window/Window.java index 61575b7..e8e32ff 100644 --- a/src/org/nwapw/abacus/window/Window.java +++ b/src/org/nwapw/abacus/window/Window.java @@ -3,26 +3,76 @@ package org.nwapw.abacus.window; import javax.swing.*; import java.awt.*; +/** + * The main UI window for the calculator. + */ public class Window extends JFrame { + /** + * A collection of outputs from the calculator. + */ private String history; + /** + * The last output by the calculator. + */ private String lastOutput; + /** + * The panel where the output occurs. + */ private JPanel outputPanel; + /** + * The text area reserved for the last output. + */ private JTextArea lastOutputArea; + /** + * The text area used for all history output. + */ private JTextArea historyArea; + /** + * The scroll pane for the history area. + */ private JScrollPane historyAreaScroll; + /** + * The panel where the input occurs. + */ private JPanel inputPanel; + /** + * The input text field. + */ private JTextField inputField; + /** + * The "submit" button. + */ private JButton inputEnterButton; + /** + * The side panel for separate configuration. + */ private JPanel sidePanel; + /** + * Panel for elements relating to number + * system selection. + */ private JPanel numberSystemPanel; + /** + * The possible list of number systems. + */ private JComboBox numberSystemList; - private JButton functionSelectButton; + /** + * The panel for elements relating to + * function selection. + */ private JPanel functionSelectPanel; + /** + * The list of functions available to the user. + */ private JComboBox functionList; + /** + * The button used to select a function. + */ + private JButton functionSelectButton; public Window() { super();