summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/parserutils
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2017-03-25 20:34:42 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2017-03-25 20:34:42 -0400
commitb53c1ef47c438fb1144b961d1939c37a4bfe9120 (patch)
treeeec3e8737831dfa245fdee31fb4b25bffac03aff /BJC-Utils2/src/main/java/bjc/utils/parserutils
parent9716b1ac09eb92c4ed001be4350d54b41b953239 (diff)
Separate general I/O from parsing.
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/parserutils')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/BlockReader.java208
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java215
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java80
3 files changed, 0 insertions, 503 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/BlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/BlockReader.java
deleted file mode 100644
index 1f0d6d0..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/BlockReader.java
+++ /dev/null
@@ -1,208 +0,0 @@
-package bjc.utils.parserutils;
-
-import java.io.LineNumberReader;
-import java.io.Reader;
-import java.util.NoSuchElementException;
-import java.util.Scanner;
-import java.util.function.Consumer;
-import java.util.regex.Pattern;
-
-/**
- * Implements reading numbered blocks from a source.
- *
- * A block is a series of characters, seperated by some regular expression.
- *
- * NOTE: The EOF marker is always treated as a delimiter. You are expected to
- * handle blocks that may be shorter than you expect.
- *
- * @author EVE
- *
- */
-public class BlockReader implements AutoCloseable {
- /**
- * Represents a block of text read in from a source.
- *
- * @author EVE
- *
- */
- public static class Block {
- /**
- * The contents of this block.
- */
- public final String contents;
-
- /**
- * The line of the source this block started on.
- */
- public final int startLine;
-
- /**
- * The line of the source this block ended on.
- */
- public final int endLine;
-
- /**
- * The number of this block.
- */
- public final int blockNo;
-
- /**
- * Create a new block.
- *
- * @param blockNo
- * The number of this block.
- * @param contents
- * The contents of this block.
- * @param startLine
- * The line this block started on.
- * @param endLine
- * The line this block ended.
- */
- public Block(int blockNo, String contents, int startLine, int endLine) {
- this.contents = contents;
- this.startLine = startLine;
- this.endLine = endLine;
- this.blockNo = blockNo;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
-
- result = prime * result + blockNo;
- result = prime * result + ((contents == null) ? 0 : contents.hashCode());
- result = prime * result + endLine;
- result = prime * result + startLine;
-
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if(this == obj) return true;
- if(obj == null) return false;
- if(!(obj instanceof Block)) return false;
-
- Block other = (Block) obj;
-
- if(blockNo != other.blockNo) return false;
-
- if(contents == null) {
- if(other.contents != null) return false;
- } else if(!contents.equals(other.contents)) return false;
-
- if(endLine != other.endLine) return false;
- if(startLine != other.startLine) return false;
-
- return true;
- }
-
- @Override
- public String toString() {
- return String.format("Block #%d (from lines %d to %d) length: %d characters", blockNo, startLine,
- endLine, contents.length());
- }
- }
-
- /*
- * I/O source for blocks.
- */
- private LineNumberReader lnReader;
- private Scanner blockReader;
-
- /*
- * The current block.
- */
- private Block currBlock;
- private int blockNo;
-
- /**
- * Create a new block reader.
- *
- * @param blockDelim
- * The pattern that separates blocks. Note that the end
- * of file is always considered to end a block.
- *
- * @param source
- * The source to read blocks from.
- */
- public BlockReader(String blockDelim, Reader source) {
- lnReader = new LineNumberReader(source);
-
- blockReader = new Scanner(lnReader);
-
- String pattern = String.format("(?:%s)|\\Z", blockDelim);
- Pattern pt = Pattern.compile(pattern, Pattern.MULTILINE);
-
- blockReader.useDelimiter(pt);
- }
-
- /**
- * Check if this reader has an available block.
- *
- * @return Whether or not another block is available.
- */
- public boolean hasNextBlock() {
- return blockReader.hasNext();
- }
-
- /**
- * Get the current block.
- *
- * @return The current block, or null if there is no current block.
- */
- public Block getBlock() {
- return currBlock;
- }
-
- /**
- * Move to the next block.
- *
- * @return Whether or not the next block was succesfully read.
- */
- public boolean nextBlock() {
- try {
- int blockStartLine = lnReader.getLineNumber();
- String blockContents = blockReader.next();
- int blockEndLine = lnReader.getLineNumber();
- blockNo += 1;
-
- currBlock = new Block(blockNo, blockContents, blockStartLine, blockEndLine);
-
- return true;
- } catch(NoSuchElementException nseex) {
- return false;
- }
- }
-
- /**
- * Execute an action for each remaining block.
- *
- * @param action
- * The action to execute for each block
- */
- public void forEachBlock(Consumer<Block> action) {
- while(hasNextBlock()) {
- nextBlock();
-
- action.accept(currBlock);
- }
- }
-
- /**
- * Retrieve the number of blocks that have been read so far.
- *
- * @return The number of blocks read so far.
- */
- public int getBlockCount() {
- return blockNo;
- }
-
- @Override
- public void close() throws Exception {
- blockReader.close();
-
- lnReader.close();
- }
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
deleted file mode 100644
index b26030c..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package bjc.utils.parserutils;
-
-import bjc.utils.data.IHolder;
-import bjc.utils.data.IPair;
-import bjc.utils.data.Identity;
-import bjc.utils.data.Pair;
-import bjc.utils.exceptions.UnknownPragmaException;
-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
- // Takes the tokenizer, and a pair of the read token and application
- // state
- private BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start;
-
- // Function to use when continuing a rule
- // Takes a tokenizer and application state
- private BiConsumer<FunctionalStringTokenizer, E> continueRule;
-
- // Function to use when ending a rule
- // Takes an application state
- private Consumer<E> end;
-
- // Map of pragma names to pragma actions
- // Pragma actions are functions taking a tokenizer and application state
- private IMap<String, BiConsumer<FunctionalStringTokenizer, E>> pragmas;
-
- /**
- * Create a new rule-based config reader
- *
- * @param start
- * The action to fire when starting a rule
- * @param continueRule
- * The action to fire when continuing a rule
- * @param end
- * The action to fire when ending a rule
- */
- public RuleBasedConfigReader(BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start,
- BiConsumer<FunctionalStringTokenizer, E> continueRule, Consumer<E> end) {
- this.start = start;
- this.continueRule = continueRule;
- this.end = end;
-
- this.pragmas = new FunctionalMap<>();
- }
-
- /**
- * 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)
- throw new NullPointerException("Pragma name 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)
- throw new InputMismatchException("Cannot continue rule with no rule open");
- 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);
- }
-
- private boolean endRule(E state, boolean isRuleOpen) {
- // Ignore blank line without an open rule
- if(isRuleOpen == false)
- // Do nothing
- return false;
- else {
- // Nothing happens on rule end
- if(end != null) {
- // Process the rule ending
- end.accept(state);
- }
-
- // Return a closed rule
- return false;
- }
- }
-
- /**
- * Run a stream through this reader
- *
- * @param input
- * The stream to get input
- * @param initialState
- * The initial state of the reader
- * @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");
-
- // Application state: We're giving this back later
- E state = initialState;
-
- // Prepare our input source
- try(Scanner source = new Scanner(input)) {
- source.useDelimiter("\n");
- // This is true when a rule's open
- IHolder<Boolean> isRuleOpen = new Identity<>(false);
-
- // Do something for every line of the file
- source.forEachRemaining((line) -> {
- // Skip comment lines
- if(line.startsWith("#") || line.startsWith("//"))
- // It's a comment
- return;
- else if(line.equals("")) {
- // End the rule
- isRuleOpen.replace(endRule(state, isRuleOpen.getValue()));
- } else if(line.startsWith("\t")) {
- // Continue the rule
- continueRule(state, isRuleOpen.getValue(), line);
- } else {
- // Open a rule
- isRuleOpen.replace(startRule(state, isRuleOpen.getValue(), line));
- }
- });
- }
-
- // Return the state that the user has created
- return state;
-
- }
-
- /**
- * Set the action to execute when continuing a rule
- *
- * @param continueRule
- * The action to execute on continuation of a rule
- */
- public void setContinueRule(BiConsumer<FunctionalStringTokenizer, E> continueRule) {
- this.continueRule = continueRule;
- }
-
- /**
- * Set the action to execute when ending a rule
- *
- * @param end
- * The action to execute on ending of a rule
- */
- public void setEndRule(Consumer<E> end) {
- this.end = end;
- }
-
- /**
- * 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");
-
- this.start = start;
- }
-
- private boolean startRule(E state, boolean isRuleOpen, String line) {
- // Create the line tokenizer
- FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line, " ");
-
- // Get the initial token
- String nextToken = tokenizer.nextToken();
-
- // Handle pragmas
- if(nextToken.equals("pragma")) {
- // Get the pragma name
- String token = tokenizer.nextToken();
-
- // Handle pragmas
- pragmas.getOrDefault(token, (tokenzer, stat) -> {
- throw new UnknownPragmaException("Unknown pragma " + token);
- }).accept(tokenizer, state);
- } else {
- // Make sure input is correct
- if(isRuleOpen == true)
- throw new InputMismatchException("Nested rules are currently not supported");
-
- // Start a rule
- start.accept(tokenizer, new Pair<>(nextToken, state));
-
- isRuleOpen = true;
- }
-
- return isRuleOpen;
- }
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
deleted file mode 100644
index 65add27..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedReaderPragmas.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package bjc.utils.parserutils;
-
-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
- *
- */
-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
- * The name of this pragma, for error message purpose
- * @param consumer
- * The function to invoke with the parsed integer
- * @return A pragma that functions as described above.
- */
- public static <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildInteger(String name,
- BiConsumer<Integer, StateType> consumer) {
- return (tokenizer, state) -> {
- // Check our input is correct
- if(!tokenizer.hasMoreTokens())
- throw new PragmaFormatException("Pragma " + name + " requires one integer argument");
-
- // Read the argument
- String token = tokenizer.nextToken();
-
- try {
- // Run the pragma
- consumer.accept(Integer.parseInt(token), state);
- } 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. "
- + "This pragma requires a integer argument");
-
- pfex.initCause(nfex);
-
- throw pfex;
- }
- };
- }
-
- /**
- * 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
- * The name of this pragma, for error message purpose
- * @param consumer
- * The function to invoke with the parsed string
- * @return A pragma that functions as described above.
- */
- public static <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildStringCollapser(String name,
- BiConsumer<String, StateType> consumer) {
- return (tokenizer, state) -> {
- // Check our input
- if(!tokenizer.hasMoreTokens()) throw new PragmaFormatException(
- "Pragma " + name + " requires one or more string arguments");
-
- // Build our argument
- String collapsed = ListUtils.collapseTokens(tokenizer.toList());
-
- // Run the pragma
- consumer.accept(collapsed, state);
- };
- }
-}