diff --git a/build.gradle b/build.gradle index 7733484..36fd331 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ repositories { } dependencies { + compile 'com.moandjiezana.toml:toml4j:0.7.1' testCompile 'junit:junit:4.12' } diff --git a/src/org/nwapw/abacus/Abacus.java b/src/org/nwapw/abacus/Abacus.java index 3343d71..eacc0d8 100644 --- a/src/org/nwapw/abacus/Abacus.java +++ b/src/org/nwapw/abacus/Abacus.java @@ -1,46 +1,188 @@ package org.nwapw.abacus; -import org.nwapw.abacus.plugin.PluginManager; -//import org.nwapw.abacus.plugin.StandardPlugin; -import org.nwapw.abacus.plugin.StandardPlugin; -import org.nwapw.abacus.window.Window; +import org.nwapw.abacus.config.ConfigurationObject; +import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.number.NaiveNumber; +import org.nwapw.abacus.number.NumberInterface; import org.nwapw.abacus.plugin.ClassFinder; +import org.nwapw.abacus.plugin.PluginListener; +import org.nwapw.abacus.plugin.PluginManager; +import org.nwapw.abacus.plugin.StandardPlugin; +import org.nwapw.abacus.tree.NumberReducer; +import org.nwapw.abacus.tree.TreeBuilder; +import org.nwapw.abacus.tree.TreeNode; +import org.nwapw.abacus.window.Window; import javax.swing.*; +import java.io.File; import java.io.IOException; -import java.util.ArrayList; +import java.lang.reflect.InvocationTargetException; -public class Abacus { +/** + * The main calculator class. This is responsible + * for piecing together all of the components, allowing + * their interaction with each other. + */ +public class Abacus implements PluginListener { + /** + * The default implementation to use for the number representation. + */ + public static final Class DEFAULT_NUMBER = NaiveNumber.class; + /** + * The file used for saving and loading configuration. + */ + public static final File CONFIG_FILE = new File("config.toml"); + + /** + * The main Abacus UI. + */ private Window mainUi; - private PluginManager manager; + /** + * The plugin manager responsible for + * loading and unloading plugins, + * and getting functions from them. + */ + private PluginManager pluginManager; + /** + * Tree builder built from plugin manager, + * used to construct parse trees. + */ + private TreeBuilder treeBuilder; + /** + * The reducer used to evaluate the tree. + */ + private NumberReducer numberReducer; + /** + * The configuration loaded from a file. + */ + private ConfigurationObject configuration; + /** + * Creates a new instance of the Abacus calculator. + */ public Abacus(){ - init(); + pluginManager = new PluginManager(this); + mainUi = new Window(this); + numberReducer = new NumberReducer(this); + configuration = new ConfigurationObject(CONFIG_FILE); + configuration.save(CONFIG_FILE); + + pluginManager.addListener(this); + pluginManager.addInstantiated(new StandardPlugin(pluginManager)); + try { + ClassFinder.loadJars("plugins") + .forEach(plugin -> pluginManager.addClass(plugin)); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + pluginManager.load(); + + mainUi.setVisible(true); } - private void init() { + /** + * Gets the current tree builder. + * @return the main tree builder in this abacus instance. + */ + public TreeBuilder getTreeBuilder() { + return treeBuilder; + } + + /** + * Gets the current plugin manager, + * @return the plugin manager in this abacus instance. + */ + public PluginManager getPluginManager() { + return pluginManager; + } + + /** + * Gets the current UI. + * @return the UI window in this abacus instance. + */ + public Window getMainUi() { + return mainUi; + } + + /** + * Get the reducer that is responsible for transforming + * an expression into a number. + * @return the number reducer in this abacus instance. + */ + public NumberReducer getNumberReducer() { + return numberReducer; + } + + /** + * Gets the configuration object associated with this instance. + * @return the configuration object. + */ + public ConfigurationObject getConfiguration() { + return configuration; + } + + /** + * Parses a string into a tree structure using the main + * tree builder. + * @param input the input string to parse + * @return the resulting tree, null if the tree builder or the produced tree are null. + */ + public TreeNode parseString(String input){ + if(treeBuilder == null) return null; + return treeBuilder.fromString(input); + } + + /** + * Evaluates the given tree using the main + * number reducer. + * @param tree the tree to reduce, must not be null. + * @return the resulting number, or null of the reduction failed. + */ + public NumberInterface evaluateTree(TreeNode tree){ + return tree.reduce(numberReducer); + } + + public NumberInterface numberFromString(String numberString){ + Class toInstantiate = + pluginManager.numberFor(configuration.getNumberImplementation()); + if(toInstantiate == null) toInstantiate = DEFAULT_NUMBER; + + try { + return toInstantiate.getConstructor(String.class).newInstance(numberString); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void onLoad(PluginManager manager) { + treeBuilder = new TreeBuilder(this); + for(String function : manager.getAllFunctions()){ + treeBuilder.registerFunction(function); + } + for(String operator : manager.getAllOperators()){ + Operator operatorObject = manager.operatorFor(operator); + treeBuilder.registerOperator(operator, + operatorObject.getAssociativity(), + operatorObject.getType(), + operatorObject.getPrecedence()); + } + } + + @Override + public void onUnload(PluginManager manager) { + treeBuilder = null; + } + + public static void main(String[] args){ try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | UnsupportedLookAndFeelException | IllegalAccessException e) { e.printStackTrace(); } - manager = new PluginManager(); - manager.addInstantiated(new StandardPlugin(manager)); - try { - ClassFinder.loadJars("plugins") - .forEach(plugin -> manager.addClass(plugin)); - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - mainUi = new Window(manager); - mainUi.setVisible(true); - manager.load(); - } - - public static void main(String[] args){ new Abacus(); } - } diff --git a/src/org/nwapw/abacus/config/Configuration.java b/src/org/nwapw/abacus/config/Configuration.java new file mode 100644 index 0000000..2039d60 --- /dev/null +++ b/src/org/nwapw/abacus/config/Configuration.java @@ -0,0 +1,14 @@ +package org.nwapw.abacus.config; + +/** + * Serializable class that will be used to load TOML + * configurations. + */ +public class Configuration { + + /** + * The type of number this calculator should use. + */ + public String numberType; + +} diff --git a/src/org/nwapw/abacus/config/ConfigurationObject.java b/src/org/nwapw/abacus/config/ConfigurationObject.java new file mode 100644 index 0000000..1f0c066 --- /dev/null +++ b/src/org/nwapw/abacus/config/ConfigurationObject.java @@ -0,0 +1,105 @@ +package org.nwapw.abacus.config; + +import com.moandjiezana.toml.Toml; +import com.moandjiezana.toml.TomlWriter; + +import java.io.File; +import java.io.IOException; + +/** + * A configuration object, which essentially + * manages saving, loading, and getting values + * from the configuration. While Configuration is + * the data model, this is the interface with it. + */ +public class ConfigurationObject { + + /** + * The writer used to store the configuration. + */ + private static final TomlWriter TOML_WRITER = new TomlWriter(); + /** + * The configuration instance being modeled. + */ + private Configuration configuration; + + /** + * Sets up the ConfigurationObject. + * different constructors do different things, + * but they all lead here. + * @param configuration the configuration to set up with. + */ + private void setup(Configuration configuration){ + this.configuration = configuration; + } + + /** + * Creates a default configuration. + * @return the newly created default configuration. + */ + private Configuration getDefaultConfig(){ + configuration = new Configuration(); + configuration.numberType = "naive"; + return configuration; + } + + /** + * Returns the implementation the user has requested to + * represent their numbers. + * @return the implementation name. + */ + public String getNumberImplementation() { + return configuration.numberType; + } + + /** + * Saves the ConfigurationObject to the given file. + * @param toFile the file to save ot. + * @return true if the save succeed, false if otherwise. + */ + public boolean save(File toFile){ + if(toFile.getParentFile() != null) toFile.getParentFile().mkdirs(); + try { + TOML_WRITER.write(configuration, toFile); + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + /** + * Creates a new configuration object with the given config. + * @param config the config to use. + */ + public ConfigurationObject(Configuration config){ + setup(config); + } + + /** + * Create a configuration object by attempting to + * load a config from the given path, using the + * default configuration otherwise. + * @param path the path to attempt to load. + */ + public ConfigurationObject(File path){ + Configuration config; + if(!path.exists()) { + config = getDefaultConfig(); + } else { + Toml parse = new Toml(); + parse.read(path); + config = parse.to(Configuration.class); + } + setup(config); + } + + /** + * Creates a new configuration object with the + * default configuration. + */ + public ConfigurationObject(){ + setup(getDefaultConfig()); + } + +} diff --git a/src/org/nwapw/abacus/number/NaiveNumber.java b/src/org/nwapw/abacus/number/NaiveNumber.java index 1a80cd1..96e42dd 100755 --- a/src/org/nwapw/abacus/number/NaiveNumber.java +++ b/src/org/nwapw/abacus/number/NaiveNumber.java @@ -10,6 +10,13 @@ public class NaiveNumber implements NumberInterface { */ private double value; + /** + * Creates a new NaiveNumber with the given string. + * @param value the value, which will be parsed as a double. + */ + public NaiveNumber(String value) { + this(Double.parseDouble(value)); + } /** * Creates a new NaiveNumber with the given value. * @param value the value to use. @@ -28,7 +35,7 @@ public class NaiveNumber implements NumberInterface { public static final NaiveNumber ONE = new NaiveNumber(1); @Override - public int precision() { + public int getMaxPrecision() { return 18; } diff --git a/src/org/nwapw/abacus/number/NumberInterface.java b/src/org/nwapw/abacus/number/NumberInterface.java index f425a30..1f87d11 100755 --- a/src/org/nwapw/abacus/number/NumberInterface.java +++ b/src/org/nwapw/abacus/number/NumberInterface.java @@ -6,10 +6,10 @@ package org.nwapw.abacus.number; public interface NumberInterface { /** - * The precision to which this number operates. + * The maximum precision to which this number operates. * @return the precision. */ - int precision(); + int getMaxPrecision(); /** * Multiplies this number by another, returning diff --git a/src/org/nwapw/abacus/number/PreciseNumber.java b/src/org/nwapw/abacus/number/PreciseNumber.java index 1641cff..8b01622 100755 --- a/src/org/nwapw/abacus/number/PreciseNumber.java +++ b/src/org/nwapw/abacus/number/PreciseNumber.java @@ -1,8 +1,6 @@ package org.nwapw.abacus.number; import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.MathContext; import java.math.RoundingMode; public class PreciseNumber implements NumberInterface{ @@ -43,7 +41,7 @@ public class PreciseNumber implements NumberInterface{ } @Override - public int precision() { + public int getMaxPrecision() { return 54; } @@ -54,7 +52,7 @@ public class PreciseNumber implements NumberInterface{ @Override public NumberInterface divide(NumberInterface divisor) { - return new PreciseNumber(value.divide(((PreciseNumber) divisor).value, this.precision(), RoundingMode.HALF_UP)); + return new PreciseNumber(value.divide(((PreciseNumber) divisor).value, this.getMaxPrecision(), RoundingMode.HALF_UP)); } @Override @@ -109,7 +107,7 @@ public class PreciseNumber implements NumberInterface{ @Override public String toString() { - BigDecimal rounded = value.setScale(precision() - 4, RoundingMode.HALF_UP); + BigDecimal rounded = value.setScale(getMaxPrecision() - 4, RoundingMode.HALF_UP); return rounded.stripTrailingZeros().toPlainString(); } } diff --git a/src/org/nwapw/abacus/plugin/Plugin.java b/src/org/nwapw/abacus/plugin/Plugin.java index 1f57b1d..2bf4a2d 100644 --- a/src/org/nwapw/abacus/plugin/Plugin.java +++ b/src/org/nwapw/abacus/plugin/Plugin.java @@ -2,6 +2,7 @@ package org.nwapw.abacus.plugin; import org.nwapw.abacus.function.Function; import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.number.NumberInterface; import java.util.HashMap; import java.util.Map; @@ -24,6 +25,10 @@ public abstract class Plugin { * A hash map of operators mapped to their string names. */ private Map operators; + /** + * A hash map of operators mapped to their string names. + */ + private Map> numbers; /** * The plugin manager in which to search for functions * not inside this package, @@ -44,6 +49,7 @@ public abstract class Plugin { this.manager = manager; functions = new HashMap<>(); operators = new HashMap<>(); + numbers = new HashMap<>(); enabled = false; } @@ -63,6 +69,14 @@ public abstract class Plugin { return operators.keySet(); } + /** + * Gets the list of all numbers provided by this plugin. + * @return the list of registered numbers. + */ + public final Set providedNumbers(){ + return numbers.keySet(); + } + /** * Gets a function under the given function name. * @param functionName the name of the function to get @@ -81,6 +95,15 @@ public abstract class Plugin { return operators.get(operatorName); } + /** + * Gets the class under the given name. + * @param numberName the name of the class. + * @return the class, or null if the plugin doesn't provide it. + */ + public final Class getNumber(String numberName){ + return numbers.get(numberName); + } + /** * Enables the function, loading the necessary instances * of functions. @@ -124,6 +147,18 @@ public abstract class Plugin { operators.put(name, operator); } + /** + * To be used in load(). Registers a number class + * with the plugin internally, which makes it possible + * for the user to select it as an "implementation" for the + * number that they would like to use. + * @param name the name to register it under. + * @param toRegister the class to register. + */ + protected final void registerNumber(String name, Class toRegister){ + numbers.put(name, toRegister); + } + /** * Searches the PluginManager for the given function name. * This can be used by the plugins internally in order to call functions diff --git a/src/org/nwapw/abacus/plugin/PluginManager.java b/src/org/nwapw/abacus/plugin/PluginManager.java index 8bb3879..33af14a 100644 --- a/src/org/nwapw/abacus/plugin/PluginManager.java +++ b/src/org/nwapw/abacus/plugin/PluginManager.java @@ -1,7 +1,9 @@ package org.nwapw.abacus.plugin; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.Function; import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.number.NumberInterface; import java.lang.reflect.InvocationTargetException; import java.util.*; @@ -26,10 +28,15 @@ public class PluginManager { */ private Map cachedFunctions; /** - * List of operators tha have been cached, + * List of operators that have been cached, * that is, found in a plugin and returned. */ private Map cachedOperators; + /** + * List of registered number implementations that have + * been cached, that is, found in a plugin and returned. + */ + private Map> cachedNumbers; /** * List of all functions loaded by the plugins. */ @@ -38,21 +45,33 @@ public class PluginManager { * List of all operators loaded by the plugins. */ private Set allOperators; + /** + * List of all numbers loaded by the plugins. + */ + private Set allNumbers; /** * The list of plugin listeners attached to this instance. */ private Set listeners; + /** + * The instance of Abacus that is used to interact with its other + * components. + */ + private Abacus abacus; /** * Creates a new plugin manager. */ - public PluginManager(){ + public PluginManager(Abacus abacus){ + this.abacus = abacus; loadedPluginClasses = new HashSet<>(); plugins = new HashSet<>(); cachedFunctions = new HashMap<>(); cachedOperators = new HashMap<>(); + cachedNumbers = new HashMap<>(); allFunctions = new HashSet<>(); allOperators = new HashSet<>(); + allNumbers = new HashSet<>(); listeners = new HashSet<>(); } @@ -104,6 +123,15 @@ public class PluginManager { return searchCached(plugins, cachedOperators, Plugin::providedOperators, Plugin::getOperator, name); } + /** + * Gets a numer implementation under the given name. + * @param name the name of the implementation. + * @return the implementation class + */ + public Class numberFor(String name){ + return searchCached(plugins, cachedNumbers, Plugin::providedNumbers, Plugin::getNumber, name); + } + /** * Adds an instance of Plugin that already has been instantiated. * @param plugin the plugin to add. @@ -136,6 +164,7 @@ public class PluginManager { for(Plugin plugin : plugins){ allFunctions.addAll(plugin.providedFunctions()); allOperators.addAll(plugin.providedOperators()); + allNumbers.addAll(plugin.providedNumbers()); } listeners.forEach(e -> e.onLoad(this)); } @@ -147,6 +176,7 @@ public class PluginManager { for(Plugin plugin : plugins) plugin.disable(); allFunctions.clear(); allOperators.clear(); + allNumbers.clear(); listeners.forEach(e -> e.onUnload(this)); } @@ -174,6 +204,14 @@ public class PluginManager { return allOperators; } + /** + * Gets all the number implementations loaded by the Plugin Manager + * @return the set of all implementations that were loaded + */ + public Set getAllNumbers() { + return allNumbers; + } + /** * Adds a plugin change listener to this plugin manager. * @param listener the listener to add. diff --git a/src/org/nwapw/abacus/plugin/StandardPlugin.java b/src/org/nwapw/abacus/plugin/StandardPlugin.java index 1ae0969..a0f234c 100755 --- a/src/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/src/org/nwapw/abacus/plugin/StandardPlugin.java @@ -6,6 +6,7 @@ import org.nwapw.abacus.function.OperatorAssociativity; import org.nwapw.abacus.function.OperatorType; import org.nwapw.abacus.number.NaiveNumber; import org.nwapw.abacus.number.NumberInterface; +import org.nwapw.abacus.number.PreciseNumber; import java.util.function.BiFunction; @@ -21,6 +22,9 @@ public class StandardPlugin extends Plugin { @Override public void onEnable() { + registerNumber("naive", NaiveNumber.class); + registerNumber("precise", PreciseNumber.class); + registerOperator("+", new Operator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0, new Function() { @Override protected boolean matchesParams(NumberInterface[] params) { @@ -292,7 +296,7 @@ public class StandardPlugin extends Plugin { * @return the maximum error. */ private NumberInterface getMaxError(NumberInterface number){ - return (new NaiveNumber(10)).promoteTo(number.getClass()).intPow(-number.precision()); + return (new NaiveNumber(10)).promoteTo(number.getClass()).intPow(-number.getMaxPrecision()); } } diff --git a/src/org/nwapw/abacus/tree/NumberReducer.java b/src/org/nwapw/abacus/tree/NumberReducer.java index bb10a5e..6fcff47 100644 --- a/src/org/nwapw/abacus/tree/NumberReducer.java +++ b/src/org/nwapw/abacus/tree/NumberReducer.java @@ -1,8 +1,8 @@ package org.nwapw.abacus.tree; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.Function; import org.nwapw.abacus.number.NumberInterface; -import org.nwapw.abacus.plugin.PluginManager; /** * A reducer implementation that turns a tree into a single number. @@ -13,14 +13,14 @@ public class NumberReducer implements Reducer { /** * The plugin manager from which to draw the functions. */ - private PluginManager manager; + private Abacus abacus; /** - * Creates a new number reducer with the given plugin manager. - * @param manager the plugin manager. + * Creates a new number reducer. + * @param abacus the calculator instance. */ - public NumberReducer(PluginManager manager){ - this.manager = manager; + public NumberReducer(Abacus abacus){ + this.abacus = abacus; } @Override @@ -30,12 +30,12 @@ public class NumberReducer implements Reducer { } else if(node instanceof BinaryInfixNode){ NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; - Function function = manager.operatorFor(((BinaryInfixNode) node).getOperation()).getFunction(); + Function function = abacus.getPluginManager().operatorFor(((BinaryInfixNode) node).getOperation()).getFunction(); if(function == null) return null; return function.apply(left, right); } else if(node instanceof UnaryPrefixNode) { NumberInterface child = (NumberInterface) children[0]; - Function functionn = manager.operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); + Function functionn = abacus.getPluginManager().operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); if(functionn == null) return null; return functionn.apply(child); } else if(node instanceof FunctionNode){ @@ -43,7 +43,7 @@ public class NumberReducer implements Reducer { for(int i = 0; i < convertedChildren.length; i++){ convertedChildren[i] = (NumberInterface) children[i]; } - Function function = manager.functionFor(((FunctionNode) node).getFunction()); + Function function = abacus.getPluginManager().functionFor(((FunctionNode) node).getFunction()); if(function == null) return null; return function.apply(convertedChildren); } diff --git a/src/org/nwapw/abacus/tree/TreeBuilder.java b/src/org/nwapw/abacus/tree/TreeBuilder.java index 83f2ebd..97800e4 100644 --- a/src/org/nwapw/abacus/tree/TreeBuilder.java +++ b/src/org/nwapw/abacus/tree/TreeBuilder.java @@ -1,12 +1,11 @@ package org.nwapw.abacus.tree; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.OperatorAssociativity; import org.nwapw.abacus.function.OperatorType; import org.nwapw.abacus.lexing.Lexer; import org.nwapw.abacus.lexing.pattern.Match; import org.nwapw.abacus.lexing.pattern.Pattern; -import org.nwapw.abacus.number.NaiveNumber; -import org.nwapw.abacus.number.PreciseNumber; import java.util.*; @@ -31,6 +30,11 @@ public class TreeBuilder { * The map of operator types. */ private Map typeMap; + /** + * The abacus instance required to interact with + * other components of the calculator. + */ + private Abacus abacus; /** * Comparator used to sort token types. @@ -40,7 +44,8 @@ public class TreeBuilder { /** * Creates a new TreeBuilder. */ - public TreeBuilder(){ + public TreeBuilder(Abacus abacus){ + this.abacus = abacus; lexer = new Lexer(){{ register(" ", TokenType.WHITESPACE); register(",", TokenType.COMMA); @@ -172,7 +177,7 @@ public class TreeBuilder { else return new UnaryPrefixNode(operator, applyTo); } } else if(matchType == TokenType.NUM){ - return new NumberNode(new NaiveNumber(Double.parseDouble(source.substring(match.getFrom(), match.getTo())))); + return new NumberNode(abacus.numberFromString(source.substring(match.getFrom(), match.getTo()))); } else if(matchType == TokenType.FUNCTION){ String functionName = source.substring(match.getFrom(), match.getTo()); FunctionNode node = new FunctionNode(functionName); diff --git a/src/org/nwapw/abacus/window/Window.java b/src/org/nwapw/abacus/window/Window.java index 0e7a95e..0484cf2 100644 --- a/src/org/nwapw/abacus/window/Window.java +++ b/src/org/nwapw/abacus/window/Window.java @@ -1,11 +1,7 @@ package org.nwapw.abacus.window; -import org.nwapw.abacus.function.Operator; +import org.nwapw.abacus.Abacus; import org.nwapw.abacus.number.NumberInterface; -import org.nwapw.abacus.plugin.PluginListener; -import org.nwapw.abacus.plugin.PluginManager; -import org.nwapw.abacus.tree.NumberReducer; -import org.nwapw.abacus.tree.TreeBuilder; import org.nwapw.abacus.tree.TreeNode; import javax.swing.*; @@ -18,7 +14,7 @@ import java.awt.event.MouseEvent; /** * The main UI window for the calculator. */ -public class Window extends JFrame implements PluginListener { +public class Window extends JFrame { private static final String CALC_STRING = "Calculate"; private static final String SYNTAX_ERR_STRING = "Syntax Error"; @@ -47,18 +43,10 @@ public class Window extends JFrame implements PluginListener { }; /** - * The plugin manager used to retrieve functions. + * The instance of the Abacus class, used + * for interaction with plugins and configuration. */ - private PluginManager manager; - /** - * The builder used to construct the parse trees. - */ - private TreeBuilder builder; - /** - * The reducer used to evaluate the tree. - */ - private NumberReducer reducer; - + private Abacus abacus; /** * The last output by the calculator. */ @@ -130,15 +118,14 @@ public class Window extends JFrame implements PluginListener { * Action listener that causes the input to be evaluated. */ private ActionListener evaluateListener = (event) -> { - if(builder == null) return; - TreeNode parsedExpression = builder.fromString(inputField.getText()); + TreeNode parsedExpression = abacus.parseString(inputField.getText()); if(parsedExpression == null){ lastOutputArea.setText(SYNTAX_ERR_STRING); return; } - NumberInterface numberInterface = parsedExpression.reduce(reducer); - if(numberInterface == null){ - lastOutputArea.setText(EVAL_ERR_STRING);; + NumberInterface numberInterface = abacus.evaluateTree(parsedExpression); + if(numberInterface == null) { + lastOutputArea.setText(EVAL_ERR_STRING); return; } lastOutput = numberInterface.toString(); @@ -159,13 +146,11 @@ public class Window extends JFrame implements PluginListener { /** * Creates a new window with the given manager. - * @param manager the manager to use. + * @param abacus the calculator instance to interact with other components. */ - public Window(PluginManager manager){ + public Window(Abacus abacus){ this(); - this.manager = manager; - manager.addListener(this); - reducer = new NumberReducer(manager); + this.abacus = abacus; } /** @@ -261,23 +246,4 @@ public class Window extends JFrame implements PluginListener { }); } - @Override - public void onLoad(PluginManager manager) { - builder = new TreeBuilder(); - for(String function : manager.getAllFunctions()){ - builder.registerFunction(function); - } - for(String operator : manager.getAllOperators()){ - Operator operatorObject = manager.operatorFor(operator); - builder.registerOperator(operator, - operatorObject.getAssociativity(), - operatorObject.getType(), - operatorObject.getPrecedence()); - } - } - - @Override - public void onUnload(PluginManager manager) { - builder = null; - } }