mirror of
				https://github.com/DanilaFe/abacus
				synced 2025-11-03 18:33:41 -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;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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<String, Function> 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();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,8 @@
 | 
			
		||||
package org.nwapw.abacus.tree;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enum to represent the associativity of an operator.
 | 
			
		||||
 */
 | 
			
		||||
public enum OperatorAssociativity {
 | 
			
		||||
    LEFT, RIGHT
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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<TokenType> lexer = new Lexer<TokenType>(){{
 | 
			
		||||
        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<String, Integer> precedenceMap = new HashMap<String, Integer>(){{
 | 
			
		||||
        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<String, OperatorAssociativity> associativityMap =
 | 
			
		||||
            new HashMap<String, OperatorAssociativity>() {{
 | 
			
		||||
                put("+", OperatorAssociativity.LEFT);
 | 
			
		||||
@ -31,12 +43,26 @@ public abstract class TreeNode {
 | 
			
		||||
                put("^", OperatorAssociativity.RIGHT);
 | 
			
		||||
            }};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Comparator used to sort token types.
 | 
			
		||||
     */
 | 
			
		||||
    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){
 | 
			
		||||
        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){
 | 
			
		||||
        ArrayList<Match<TokenType>> output = new ArrayList<>();
 | 
			
		||||
        Stack<Match<TokenType>> 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<Match<TokenType>> matches){
 | 
			
		||||
        if(matches.size() == 0) return null;
 | 
			
		||||
        Match<TokenType> 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<Match<TokenType>> matches = intoPostfix(string, tokenize(string));
 | 
			
		||||
        if(matches == null) return null;
 | 
			
		||||
 | 
			
		||||
@ -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<String> 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<String> functionList;
 | 
			
		||||
    /**
 | 
			
		||||
     * The button used to select a function.
 | 
			
		||||
     */
 | 
			
		||||
    private JButton functionSelectButton;
 | 
			
		||||
 | 
			
		||||
    public Window() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user