1
0
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:
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)); 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){

View File

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

View File

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

View File

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

View File

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

View File

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