mirror of
https://github.com/DanilaFe/abacus
synced 2024-11-10 12:49:52 -08:00
Implement correct plugin loading and registration.
This commit is contained in:
parent
efbd6a4c20
commit
2ca23fd427
|
@ -25,6 +25,7 @@ public class Abacus {
|
||||||
manager.addInstantiated(new StandardPlugin(manager));
|
manager.addInstantiated(new StandardPlugin(manager));
|
||||||
mainUi = new Window(manager);
|
mainUi = new Window(manager);
|
||||||
mainUi.setVisible(true);
|
mainUi.setVisible(true);
|
||||||
|
manager.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
|
|
|
@ -1,25 +1,55 @@
|
||||||
package org.nwapw.abacus.function;
|
package org.nwapw.abacus.function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that represents a single infix operator.
|
||||||
|
*/
|
||||||
public abstract class Operator {
|
public abstract class Operator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The associativity of the operator.
|
||||||
|
*/
|
||||||
private OperatorAssociativity associativity;
|
private OperatorAssociativity associativity;
|
||||||
|
/**
|
||||||
|
* The precedence of the operator.
|
||||||
|
*/
|
||||||
private int precedence;
|
private int precedence;
|
||||||
|
/**
|
||||||
|
* The function that is called by this operator.
|
||||||
|
*/
|
||||||
private Function function;
|
private Function function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new operator with the given parameters.
|
||||||
|
* @param associativity the associativity of the operator.
|
||||||
|
* @param precedence the precedence of the operator.
|
||||||
|
* @param function the function that the operator calls.
|
||||||
|
*/
|
||||||
public Operator(OperatorAssociativity associativity, int precedence, Function function){
|
public Operator(OperatorAssociativity associativity, int precedence, Function function){
|
||||||
this.associativity = associativity;
|
this.associativity = associativity;
|
||||||
this.precedence = precedence;
|
this.precedence = precedence;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operator's associativity.
|
||||||
|
* @return the associativity.
|
||||||
|
*/
|
||||||
public OperatorAssociativity getAssociativity() {
|
public OperatorAssociativity getAssociativity() {
|
||||||
return associativity;
|
return associativity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operator's precedence.
|
||||||
|
* @return the precedence.
|
||||||
|
*/
|
||||||
public int getPrecedence() {
|
public int getPrecedence() {
|
||||||
return precedence;
|
return precedence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the operator's function.
|
||||||
|
* @return the function.
|
||||||
|
*/
|
||||||
public Function getFunction() {
|
public Function getFunction() {
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,25 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public class Lexer<T> {
|
public class Lexer<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entry that represents a pattern that has been registered with the lexer.
|
||||||
|
* @param <T> the type used to identify the pattern.
|
||||||
|
*/
|
||||||
private static class PatternEntry<T>{
|
private static class PatternEntry<T>{
|
||||||
|
/**
|
||||||
|
* The name of the entry.
|
||||||
|
*/
|
||||||
public String name;
|
public String name;
|
||||||
|
/**
|
||||||
|
* The id of the entry.
|
||||||
|
*/
|
||||||
public T id;
|
public T id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new pattern entry with the given name and id.
|
||||||
|
* @param name the name of the pattern entry.
|
||||||
|
* @param id the id of the pattern entry.
|
||||||
|
*/
|
||||||
public PatternEntry(String name, T id){
|
public PatternEntry(String name, T id){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
|
@ -3,14 +3,25 @@ package org.nwapw.abacus.tree;
|
||||||
import org.nwapw.abacus.function.OperatorAssociativity;
|
import org.nwapw.abacus.function.OperatorAssociativity;
|
||||||
import org.nwapw.abacus.lexing.Lexer;
|
import org.nwapw.abacus.lexing.Lexer;
|
||||||
import org.nwapw.abacus.lexing.pattern.Match;
|
import org.nwapw.abacus.lexing.pattern.Match;
|
||||||
import org.nwapw.abacus.plugin.PluginManager;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The builder responsible for turning strings into trees.
|
||||||
|
*/
|
||||||
public class TreeBuilder {
|
public class TreeBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lexer used to get the input tokens.
|
||||||
|
*/
|
||||||
private Lexer<TokenType> lexer;
|
private Lexer<TokenType> lexer;
|
||||||
|
/**
|
||||||
|
* The map of operator precedences.
|
||||||
|
*/
|
||||||
private HashMap<String, Integer> precedenceMap;
|
private HashMap<String, Integer> precedenceMap;
|
||||||
|
/**
|
||||||
|
* The map of operator associativity.
|
||||||
|
*/
|
||||||
private HashMap<String, OperatorAssociativity> associativityMap;
|
private HashMap<String, OperatorAssociativity> associativityMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +29,9 @@ public class TreeBuilder {
|
||||||
*/
|
*/
|
||||||
protected static Comparator<TokenType> tokenSorter = Comparator.comparingInt(e -> e.priority);
|
protected static Comparator<TokenType> tokenSorter = Comparator.comparingInt(e -> e.priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new TreeBuilder.
|
||||||
|
*/
|
||||||
public TreeBuilder(){
|
public TreeBuilder(){
|
||||||
lexer = new Lexer<TokenType>(){{
|
lexer = new Lexer<TokenType>(){{
|
||||||
register(",", TokenType.COMMA);
|
register(",", TokenType.COMMA);
|
||||||
|
@ -29,6 +43,26 @@ public class TreeBuilder {
|
||||||
associativityMap = new HashMap<>();
|
associativityMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a function with the TreeBuilder.
|
||||||
|
* @param function the function to register.
|
||||||
|
*/
|
||||||
|
public void registerFunction(String function){
|
||||||
|
lexer.register(function, TokenType.FUNCTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an operator with the TreeBuilder.
|
||||||
|
* @param operator the operator to register.
|
||||||
|
* @param precedence the precedence of the operator.
|
||||||
|
* @param associativity the associativity of the operator.
|
||||||
|
*/
|
||||||
|
public void registerOperator(String operator, int precedence, OperatorAssociativity associativity){
|
||||||
|
lexer.register(operator, TokenType.OP);
|
||||||
|
precedenceMap.put(operator, precedence);
|
||||||
|
associativityMap.put(operator, associativity);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokenizes a string, converting it into matches
|
* Tokenizes a string, converting it into matches
|
||||||
* @param string the string to tokenize.
|
* @param string the string to tokenize.
|
||||||
|
@ -86,7 +120,9 @@ public class TreeBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(!tokenStack.empty()){
|
while(!tokenStack.empty()){
|
||||||
if(!(tokenStack.peek().getType() == TokenType.OP)) return null;
|
Match<TokenType> match = tokenStack.peek();
|
||||||
|
TokenType matchType = match.getType();
|
||||||
|
if(!(matchType == TokenType.OP || matchType == TokenType.FUNCTION)) return null;
|
||||||
output.add(tokenStack.pop());
|
output.add(tokenStack.pop());
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -11,6 +11,12 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public abstract class TreeNode {
|
public abstract class TreeNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function that reduces a tree to a single vale.
|
||||||
|
* @param reducer the reducer used to reduce the tree.
|
||||||
|
* @param <T> the type the reducer produces.
|
||||||
|
* @return the result of the reduction, or null on error.
|
||||||
|
*/
|
||||||
public abstract <T> T reduce(Reducer<T> reducer);
|
public abstract <T> T reduce(Reducer<T> reducer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package org.nwapw.abacus.window;
|
package org.nwapw.abacus.window;
|
||||||
|
|
||||||
|
import org.nwapw.abacus.function.Operator;
|
||||||
import org.nwapw.abacus.number.NumberInterface;
|
import org.nwapw.abacus.number.NumberInterface;
|
||||||
|
import org.nwapw.abacus.plugin.PluginListener;
|
||||||
import org.nwapw.abacus.plugin.PluginManager;
|
import org.nwapw.abacus.plugin.PluginManager;
|
||||||
import org.nwapw.abacus.tree.NumberReducer;
|
import org.nwapw.abacus.tree.NumberReducer;
|
||||||
import org.nwapw.abacus.tree.TreeBuilder;
|
import org.nwapw.abacus.tree.TreeBuilder;
|
||||||
|
@ -16,7 +18,7 @@ import java.awt.event.MouseEvent;
|
||||||
/**
|
/**
|
||||||
* The main UI window for the calculator.
|
* The main UI window for the calculator.
|
||||||
*/
|
*/
|
||||||
public class Window extends JFrame {
|
public class Window extends JFrame implements PluginListener {
|
||||||
|
|
||||||
private static final String CALC_STRING = "Calculate";
|
private static final String CALC_STRING = "Calculate";
|
||||||
private static final String SYNTAX_ERR_STRING = "Syntax Error";
|
private static final String SYNTAX_ERR_STRING = "Syntax Error";
|
||||||
|
@ -128,7 +130,7 @@ public class Window extends JFrame {
|
||||||
* Action listener that causes the input to be evaluated.
|
* Action listener that causes the input to be evaluated.
|
||||||
*/
|
*/
|
||||||
private ActionListener evaluateListener = (event) -> {
|
private ActionListener evaluateListener = (event) -> {
|
||||||
TreeBuilder builder = new TreeBuilder();
|
if(builder == null) return;
|
||||||
TreeNode parsedExpression = builder.fromString(inputField.getText());
|
TreeNode parsedExpression = builder.fromString(inputField.getText());
|
||||||
if(parsedExpression == null){
|
if(parsedExpression == null){
|
||||||
lastOutputArea.setText(SYNTAX_ERR_STRING);
|
lastOutputArea.setText(SYNTAX_ERR_STRING);
|
||||||
|
@ -162,6 +164,7 @@ public class Window extends JFrame {
|
||||||
public Window(PluginManager manager){
|
public Window(PluginManager manager){
|
||||||
this();
|
this();
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
manager.addListener(this);
|
||||||
reducer = new NumberReducer(manager);
|
reducer = new NumberReducer(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,4 +260,21 @@ public class Window extends JFrame {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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.getPrecedence(), operatorObject.getAssociativity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnload(PluginManager manager) {
|
||||||
|
builder = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user