Implement correct plugin loading and registration.

This commit is contained in:
Danila Fedorin 2017-07-27 14:06:57 -07:00
parent efbd6a4c20
commit 2ca23fd427
6 changed files with 112 additions and 4 deletions

View File

@ -25,6 +25,7 @@ public class Abacus {
manager.addInstantiated(new StandardPlugin(manager));
mainUi = new Window(manager);
mainUi.setVisible(true);
manager.load();
}
public static void main(String[] args){

View File

@ -1,25 +1,55 @@
package org.nwapw.abacus.function;
/**
* A class that represents a single infix operator.
*/
public abstract class Operator {
/**
* The associativity of the operator.
*/
private OperatorAssociativity associativity;
/**
* The precedence of the operator.
*/
private int precedence;
/**
* The function that is called by this operator.
*/
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){
this.associativity = associativity;
this.precedence = precedence;
this.function = function;
}
/**
* Gets the operator's associativity.
* @return the associativity.
*/
public OperatorAssociativity getAssociativity() {
return associativity;
}
/**
* Gets the operator's precedence.
* @return the precedence.
*/
public int getPrecedence() {
return precedence;
}
/**
* Gets the operator's function.
* @return the function.
*/
public Function getFunction() {
return function;
}

View File

@ -14,10 +14,25 @@ import java.util.*;
*/
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>{
/**
* The name of the entry.
*/
public String name;
/**
* The id of the entry.
*/
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){
this.name = name;
this.id = id;

View File

@ -3,14 +3,25 @@ package org.nwapw.abacus.tree;
import org.nwapw.abacus.function.OperatorAssociativity;
import org.nwapw.abacus.lexing.Lexer;
import org.nwapw.abacus.lexing.pattern.Match;
import org.nwapw.abacus.plugin.PluginManager;
import java.util.*;
/**
* The builder responsible for turning strings into trees.
*/
public class TreeBuilder {
/**
* The lexer used to get the input tokens.
*/
private Lexer<TokenType> lexer;
/**
* The map of operator precedences.
*/
private HashMap<String, Integer> precedenceMap;
/**
* The map of operator associativity.
*/
private HashMap<String, OperatorAssociativity> associativityMap;
/**
@ -18,6 +29,9 @@ public class TreeBuilder {
*/
protected static Comparator<TokenType> tokenSorter = Comparator.comparingInt(e -> e.priority);
/**
* Creates a new TreeBuilder.
*/
public TreeBuilder(){
lexer = new Lexer<TokenType>(){{
register(",", TokenType.COMMA);
@ -29,6 +43,26 @@ public class TreeBuilder {
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
* @param string the string to tokenize.
@ -86,7 +120,9 @@ public class TreeBuilder {
}
}
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());
}
return output;

View File

@ -11,6 +11,12 @@ import java.util.*;
*/
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);
}

View File

@ -1,6 +1,8 @@
package org.nwapw.abacus.window;
import org.nwapw.abacus.function.Operator;
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;
@ -16,7 +18,7 @@ import java.awt.event.MouseEvent;
/**
* 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 SYNTAX_ERR_STRING = "Syntax Error";
@ -128,7 +130,7 @@ public class Window extends JFrame {
* Action listener that causes the input to be evaluated.
*/
private ActionListener evaluateListener = (event) -> {
TreeBuilder builder = new TreeBuilder();
if(builder == null) return;
TreeNode parsedExpression = builder.fromString(inputField.getText());
if(parsedExpression == null){
lastOutputArea.setText(SYNTAX_ERR_STRING);
@ -162,6 +164,7 @@ public class Window extends JFrame {
public Window(PluginManager manager){
this();
this.manager = manager;
manager.addListener(this);
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;
}
}