summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/parserutils
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/parserutils')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java6
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java66
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java21
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java60
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java31
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java29
6 files changed, 96 insertions, 117 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java
index a9efe9b..bb6ebac 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java
@@ -2,7 +2,7 @@ package bjc.utils.parserutils;
/**
* Represents something that has a set precedence
- *
+ *
* @author ben
*
*/
@@ -10,7 +10,7 @@ package bjc.utils.parserutils;
public interface IPrecedent {
/**
* Create a new object with set precedence
- *
+ *
* @param precedence
* The precedence of the object to handle
* @return A new object with set precedence
@@ -21,7 +21,7 @@ public interface IPrecedent {
/**
* Get the precedence of the attached object
- *
+ *
* @return The precedence of the attached object
*/
public int getPrecedence();
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
index 2da4f7e..b26030c 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
@@ -1,11 +1,5 @@
package bjc.utils.parserutils;
-import java.io.InputStream;
-import java.util.InputMismatchException;
-import java.util.Scanner;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-
import bjc.utils.data.IHolder;
import bjc.utils.data.IPair;
import bjc.utils.data.Identity;
@@ -15,15 +9,21 @@ import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.FunctionalStringTokenizer;
import bjc.utils.funcdata.IMap;
+import java.io.InputStream;
+import java.util.InputMismatchException;
+import java.util.Scanner;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
/**
* This class parses a rules based config file, and uses it to drive a provided
* set of actions
- *
+ *
* @author ben
*
* @param <E>
* The type of the state object to use
- *
+ *
*/
public class RuleBasedConfigReader<E> {
// Function to execute when starting a rule
@@ -45,7 +45,7 @@ public class RuleBasedConfigReader<E> {
/**
* Create a new rule-based config reader
- *
+ *
* @param start
* The action to fire when starting a rule
* @param continueRule
@@ -64,29 +64,26 @@ public class RuleBasedConfigReader<E> {
/**
* Add a pragma to this reader
- *
+ *
* @param name
* The name of the pragma to add
* @param action
* The function to execute when this pragma is read
*/
public void addPragma(String name, BiConsumer<FunctionalStringTokenizer, E> action) {
- if (name == null) {
+ if(name == null)
throw new NullPointerException("Pragma name must not be null");
- } else if (action == null) {
- throw new NullPointerException("Pragma action must not be null");
- }
+ else if(action == null) throw new NullPointerException("Pragma action must not be null");
pragmas.put(name, action);
}
private void continueRule(E state, boolean isRuleOpen, String line) {
// Make sure our input is correct
- if (isRuleOpen == false) {
+ if(isRuleOpen == false)
throw new InputMismatchException("Cannot continue rule with no rule open");
- } else if (continueRule == null) {
+ else if(continueRule == null)
throw new InputMismatchException("Rule continuation not supported for current grammar");
- }
// Accept the rule
continueRule.accept(new FunctionalStringTokenizer(line.substring(1), " "), state);
@@ -94,12 +91,12 @@ public class RuleBasedConfigReader<E> {
private boolean endRule(E state, boolean isRuleOpen) {
// Ignore blank line without an open rule
- if (isRuleOpen == false) {
+ if(isRuleOpen == false)
// Do nothing
return false;
- } else {
+ else {
// Nothing happens on rule end
- if (end != null) {
+ if(end != null) {
// Process the rule ending
end.accept(state);
}
@@ -111,7 +108,7 @@ public class RuleBasedConfigReader<E> {
/**
* Run a stream through this reader
- *
+ *
* @param input
* The stream to get input
* @param initialState
@@ -119,15 +116,13 @@ public class RuleBasedConfigReader<E> {
* @return The final state of the reader
*/
public E fromStream(InputStream input, E initialState) {
- if (input == null) {
- throw new NullPointerException("Input stream must not be null");
- }
+ if(input == null) throw new NullPointerException("Input stream must not be null");
// Application state: We're giving this back later
E state = initialState;
// Prepare our input source
- try (Scanner source = new Scanner(input)) {
+ try(Scanner source = new Scanner(input)) {
source.useDelimiter("\n");
// This is true when a rule's open
IHolder<Boolean> isRuleOpen = new Identity<>(false);
@@ -135,13 +130,13 @@ public class RuleBasedConfigReader<E> {
// Do something for every line of the file
source.forEachRemaining((line) -> {
// Skip comment lines
- if (line.startsWith("#") || line.startsWith("//")) {
+ if(line.startsWith("#") || line.startsWith("//"))
// It's a comment
return;
- } else if (line.equals("")) {
+ else if(line.equals("")) {
// End the rule
isRuleOpen.replace(endRule(state, isRuleOpen.getValue()));
- } else if (line.startsWith("\t")) {
+ } else if(line.startsWith("\t")) {
// Continue the rule
continueRule(state, isRuleOpen.getValue(), line);
} else {
@@ -158,7 +153,7 @@ public class RuleBasedConfigReader<E> {
/**
* Set the action to execute when continuing a rule
- *
+ *
* @param continueRule
* The action to execute on continuation of a rule
*/
@@ -168,7 +163,7 @@ public class RuleBasedConfigReader<E> {
/**
* Set the action to execute when ending a rule
- *
+ *
* @param end
* The action to execute on ending of a rule
*/
@@ -178,14 +173,12 @@ public class RuleBasedConfigReader<E> {
/**
* Set the action to execute when starting a rule
- *
+ *
* @param start
* The action to execute on starting of a rule
*/
public void setStartRule(BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start) {
- if (start == null) {
- throw new NullPointerException("Action on rule start must be non-null");
- }
+ if(start == null) throw new NullPointerException("Action on rule start must be non-null");
this.start = start;
}
@@ -198,7 +191,7 @@ public class RuleBasedConfigReader<E> {
String nextToken = tokenizer.nextToken();
// Handle pragmas
- if (nextToken.equals("pragma")) {
+ if(nextToken.equals("pragma")) {
// Get the pragma name
String token = tokenizer.nextToken();
@@ -208,9 +201,8 @@ public class RuleBasedConfigReader<E> {
}).accept(tokenizer, state);
} else {
// Make sure input is correct
- if (isRuleOpen == true) {
+ if(isRuleOpen == true)
throw new InputMismatchException("Nested rules are currently not supported");
- }
// Start a rule
start.accept(tokenizer, new Pair<>(nextToken, state));
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
index 6c660c6..65add27 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
@@ -1,14 +1,14 @@
package bjc.utils.parserutils;
-import java.util.function.BiConsumer;
-
import bjc.utils.exceptions.PragmaFormatException;
import bjc.utils.funcdata.FunctionalStringTokenizer;
import bjc.utils.funcutils.ListUtils;
+import java.util.function.BiConsumer;
+
/**
* Contains factory methods for common pragma types
- *
+ *
* @author ben
*
*/
@@ -16,7 +16,7 @@ public class RuleBasedReaderPragmas {
/**
* Creates a pragma that takes a single integer argument
- *
+ *
* @param <StateType>
* The type of state that goes along with this pragma
* @param name
@@ -29,9 +29,8 @@ public class RuleBasedReaderPragmas {
BiConsumer<Integer, StateType> consumer) {
return (tokenizer, state) -> {
// Check our input is correct
- if (!tokenizer.hasMoreTokens()) {
+ if(!tokenizer.hasMoreTokens())
throw new PragmaFormatException("Pragma " + name + " requires one integer argument");
- }
// Read the argument
String token = tokenizer.nextToken();
@@ -39,7 +38,7 @@ public class RuleBasedReaderPragmas {
try {
// Run the pragma
consumer.accept(Integer.parseInt(token), state);
- } catch (NumberFormatException nfex) {
+ } catch(NumberFormatException nfex) {
// Tell the user their argument isn't correct
PragmaFormatException pfex = new PragmaFormatException(
"Argument " + token + " to " + name + " pragma isn't a valid integer. "
@@ -55,7 +54,7 @@ public class RuleBasedReaderPragmas {
/**
* Creates a pragma that takes any number of arguments and collapses
* them all into a single string
- *
+ *
* @param <StateType>
* The type of state that goes along with this pragma
* @param name
@@ -68,10 +67,8 @@ public class RuleBasedReaderPragmas {
BiConsumer<String, StateType> consumer) {
return (tokenizer, state) -> {
// Check our input
- if (!tokenizer.hasMoreTokens()) {
- throw new PragmaFormatException(
- "Pragma " + name + " requires one or more string arguments");
- }
+ if(!tokenizer.hasMoreTokens()) throw new PragmaFormatException(
+ "Pragma " + name + " requires one or more string arguments");
// Build our argument
String collapsed = ListUtils.collapseTokens(tokenizer.toList());
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
index 19c1971..2a0bdff 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
@@ -1,19 +1,19 @@
package bjc.utils.parserutils;
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.IList;
import bjc.utils.funcdata.IMap;
import bjc.utils.funcutils.StringUtils;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
/**
* Utility to run the shunting yard algorithm on a bunch of tokens
- *
+ *
* @author ben
*
* @param <TokenType>
@@ -22,7 +22,7 @@ import bjc.utils.funcutils.StringUtils;
public class ShuntingYard<TokenType> {
/**
* A enum representing the fundamental operator types
- *
+ *
* @author ben
*
*/
@@ -58,9 +58,9 @@ public class ShuntingYard<TokenType> {
}
private final class TokenShunter implements Consumer<String> {
- private IList<TokenType> output;
- private Deque<String> stack;
- private Function<String, TokenType> transformer;
+ private IList<TokenType> output;
+ private Deque<String> stack;
+ private Function<String, TokenType> transformer;
public TokenShunter(IList<TokenType> outpt, Deque<String> stack,
Function<String, TokenType> transformer) {
@@ -72,26 +72,26 @@ public class ShuntingYard<TokenType> {
@Override
public void accept(String token) {
// Handle operators
- if (operators.containsKey(token)) {
+ if(operators.containsKey(token)) {
// Pop operators while there isn't a higher
// precedence one
- while (!stack.isEmpty() && isHigherPrec(token, stack.peek())) {
+ while(!stack.isEmpty() && isHigherPrec(token, stack.peek())) {
output.add(transformer.apply(stack.pop()));
}
// Put this operator onto the stack
stack.push(token);
- } else if (StringUtils.containsOnly(token, "\\(")) {
+ } else if(StringUtils.containsOnly(token, "\\(")) {
// Handle groups of parenthesis for multiple
// nesting levels
stack.push(token);
- } else if (StringUtils.containsOnly(token, "\\)")) {
+ } else if(StringUtils.containsOnly(token, "\\)")) {
// Handle groups of parenthesis for multiple
// nesting levels
String swappedToken = token.replace(')', '(');
// Remove tokens up to a matching parenthesis
- while (!stack.peek().equals(swappedToken)) {
+ while(!stack.peek().equals(swappedToken)) {
output.add(transformer.apply(stack.pop()));
}
@@ -111,7 +111,7 @@ public class ShuntingYard<TokenType> {
/**
* Create a new shunting yard with a default set of operators
- *
+ *
* @param configureBasics
* Whether or not basic math operators should be provided
*/
@@ -119,7 +119,7 @@ public class ShuntingYard<TokenType> {
operators = new FunctionalMap<>();
// Add basic operators if we're configured to do so
- if (configureBasics) {
+ if(configureBasics) {
operators.put("+", Operator.ADD);
operators.put("-", Operator.SUBTRACT);
operators.put("*", Operator.MULTIPLY);
@@ -129,7 +129,7 @@ public class ShuntingYard<TokenType> {
/**
* Add an operator to the list of shuntable operators
- *
+ *
* @param operatorToken
* The token representing the operator
* @param precedence
@@ -144,7 +144,7 @@ public class ShuntingYard<TokenType> {
/**
* Add an operator to the list of shuntable operators
- *
+ *
* @param operatorToken
* The token representing the operator
* @param precedence
@@ -152,11 +152,9 @@ public class ShuntingYard<TokenType> {
*/
public void addOp(String operator, IPrecedent precedence) {
// Complain about trying to add an incorrect operator
- if (operator == null) {
+ if(operator == null)
throw new NullPointerException("Operator must not be null");
- } else if (precedence == null) {
- throw new NullPointerException("Precedence must not be null");
- }
+ else if(precedence == null) throw new NullPointerException("Precedence must not be null");
// Add the operator to the ones we handle
operators.put(operator, precedence);
@@ -167,9 +165,7 @@ public class ShuntingYard<TokenType> {
boolean exists = operators.containsKey(right);
// If it doesn't, the left is higher precedence.
- if (!exists) {
- return false;
- }
+ if(!exists) return false;
// Get the precedence of operators
int rightPrecedence = operators.get(right).getPrecedence();
@@ -181,7 +177,7 @@ public class ShuntingYard<TokenType> {
/**
* Transform a string of tokens from infix notation to postfix
- *
+ *
* @param input
* The string to transform
* @param transformer
@@ -190,11 +186,9 @@ public class ShuntingYard<TokenType> {
*/
public IList<TokenType> postfix(IList<String> input, Function<String, TokenType> transformer) {
// Check our input
- if (input == null) {
+ if(input == null)
throw new NullPointerException("Input must not be null");
- } else if (transformer == null) {
- throw new NullPointerException("Transformer must not be null");
- }
+ else if(transformer == null) throw new NullPointerException("Transformer must not be null");
// Here's what we're handing back
IList<TokenType> output = new FunctionalList<>();
@@ -215,14 +209,14 @@ public class ShuntingYard<TokenType> {
/**
* Remove an operator from the list of shuntable operators
- *
+ *
* @param token
* The token representing the operator. If null, remove
* all operators
*/
public void removeOp(String operator) {
// Check if we want to remove all operators
- if (operator == null) {
+ if(operator == null) {
operators = new FunctionalMap<>();
} else {
operators.remove(operator);
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
index 1a4a6c4..5f843a2 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java
@@ -1,17 +1,17 @@
package bjc.utils.parserutils;
-import java.util.Deque;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-
import bjc.utils.data.IHolder;
import bjc.utils.data.IPair;
import bjc.utils.data.ITree;
import bjc.utils.data.Pair;
import bjc.utils.data.Tree;
+import java.util.Deque;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+
final class TokenTransformer<TokenType> implements Consumer<TokenType> {
// Handle operators
private final class OperatorHandler implements UnaryOperator<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> {
@@ -37,18 +37,15 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
ITree<TokenType> newAST;
// Handle special operators
- if (isSpecialOperator.test(element)) {
+ if(isSpecialOperator.test(element)) {
newAST = handleSpecialOperator.apply(element).apply(queuedASTs);
} else {
// Error if we don't have enough for a binary
// operator
- if (queuedASTs.size() < 2) {
- throw new IllegalStateException(
- "Attempted to parse binary operator without enough operands.\n"
- + "Problem operator is " + element
- + "\nPossible operand is: \n\t"
- + queuedASTs.peek());
- }
+ if(queuedASTs.size() < 2) throw new IllegalStateException(
+ "Attempted to parse binary operator without enough operands.\n"
+ + "Problem operator is " + element
+ + "\nPossible operand is: \n\t" + queuedASTs.peek());
// Grab the two operands
ITree<TokenType> right = queuedASTs.pop();
@@ -70,8 +67,8 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
private Predicate<TokenType> operatorPredicate;
- private Predicate<TokenType> isSpecialOperator;
- private Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator;
+ private Predicate<TokenType> isSpecialOperator;
+ private Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator;
// Create a new transformer
public TokenTransformer(IHolder<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> initialState,
@@ -86,7 +83,7 @@ final class TokenTransformer<TokenType> implements Consumer<TokenType> {
@Override
public void accept(TokenType element) {
// Handle operators
- if (operatorPredicate.test(element)) {
+ if(operatorPredicate.test(element)) {
initialState.transform(new OperatorHandler(element));
} else {
ITree<TokenType> newAST = new Tree<>(element);
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
index 6f4e384..82ded42 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
@@ -1,10 +1,5 @@
package bjc.utils.parserutils;
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
import bjc.utils.data.IHolder;
import bjc.utils.data.IPair;
import bjc.utils.data.ITree;
@@ -12,18 +7,23 @@ import bjc.utils.data.Identity;
import bjc.utils.data.Pair;
import bjc.utils.funcdata.IList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
/**
* Creates a parse tree from a postfix expression
- *
+ *
* @author ben
*
*/
public class TreeConstructor {
/**
* Construct a tree from a list of tokens in postfix notation
- *
+ *
* Only binary operators are accepted.
- *
+ *
* @param <TokenType>
* The elements of the parse tree
* @param tokens
@@ -41,10 +41,10 @@ public class TreeConstructor {
/**
* Construct a tree from a list of tokens in postfix notation
- *
+ *
* Only binary operators are accepted by default. Use the last two
* parameters to handle non-binary operators
- *
+ *
* @param <TokenType>
* The elements of the parse tree
* @param tokens
@@ -58,7 +58,7 @@ public class TreeConstructor {
* @param handleSpecialOperator
* The function to use to handle special case operators
* @return A AST from the expression
- *
+ *
* FIXME The handleSpecialOp function seems like an ugly
* interface. Maybe there's a better way to express how that
* works.
@@ -67,13 +67,12 @@ public class TreeConstructor {
Predicate<TokenType> isOperator, Predicate<TokenType> isSpecialOperator,
Function<TokenType, Function<Deque<ITree<TokenType>>, ITree<TokenType>>> handleSpecialOperator) {
// Make sure our parameters are valid
- if (tokens == null) {
+ if(tokens == null)
throw new NullPointerException("Tokens must not be null");
- } else if (isOperator == null) {
+ else if(isOperator == null)
throw new NullPointerException("Operator predicate must not be null");
- } else if (isSpecialOperator == null) {
+ else if(isSpecialOperator == null)
throw new NullPointerException("Special operator determiner must not be null");
- }
// Here is the state for the tree construction
IHolder<IPair<Deque<ITree<TokenType>>, ITree<TokenType>>> initialState = new Identity<>(