1
0
mirror of https://github.com/DanilaFe/abacus synced 2024-12-23 07:50:09 -08:00

Add more comments.

This commit is contained in:
Danila Fedorin 2017-07-26 10:10:37 -07:00
parent 37d5c04911
commit 7ba6f8a353
8 changed files with 220 additions and 4 deletions

View File

@ -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();
} }

View File

@ -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) {

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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();