summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/ParseBlock.java37
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/TokenStream.java23
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/ParseBlocks.java13
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/RepeatingParseBlock.java96
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/SimpleParseBlock.java101
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/TriggeredParseBlock.java61
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/BinaryPostCommand.java29
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/DelimitedCommand.java65
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/GroupingCommand.java41
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/InitialCommands.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeafCommand.java18
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeftBinaryCommand.java24
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonBinaryCommand.java24
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonInitialCommands.java10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostCircumfixCommand.java54
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostfixCommand.java28
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PreTernaryCommand.java72
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/RightBinaryCommand.java22
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TernaryCommand.java54
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TransformingInitialCommand.java52
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/UnaryCommand.java28
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringToken.java (renamed from BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringToken.java)4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringTokenStream.java (renamed from BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringTokenStream.java)18
23 files changed, 739 insertions, 161 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/ParseBlock.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/ParseBlock.java
new file mode 100644
index 0000000..4542107
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/ParseBlock.java
@@ -0,0 +1,37 @@
+package bjc.utils.parserutils.pratt;
+
+import bjc.utils.data.ITree;
+import bjc.utils.parserutils.ParserException;
+
+/**
+ * Represents a embedded block in an expression.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the token.
+ *
+ * @param <V>
+ * The value type of the token.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
+@FunctionalInterface
+public interface ParseBlock<K, V, C> {
+
+ /**
+ * Parse the block this represents.
+ *
+ * @param ctx
+ * The context for parsing.
+ *
+ * @return A AST for this block.
+ *
+ * @throws ParserException
+ * If something goes wrong during parsing, or the block
+ * fails validation.
+ */
+ ITree<Token<K, V>> parse(ParserContext<K, V, C> ctx) throws ParserException;
+
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/TokenStream.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/TokenStream.java
index 8decc09..71482b4 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/TokenStream.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/TokenStream.java
@@ -4,6 +4,7 @@ import bjc.utils.funcutils.StringUtils;
import bjc.utils.parserutils.ParserException;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
/**
@@ -17,7 +18,7 @@ import java.util.Set;
* @param <V>
* The value type of the token.
*/
-public interface TokenStream<K, V> {
+public abstract class TokenStream<K, V> implements Iterator<Token<K, V>> {
/**
* The exception thrown when an expectation fails.
*
@@ -41,14 +42,13 @@ public interface TokenStream<K, V> {
*
* @return The current token.
*/
- Token<K, V> current();
+ public abstract Token<K, V> current();
- /**
- * Advance to the next token in the stream.
- *
- * Has no effect when the end of the stream is reached.
- */
- void next();
+ @Override
+ public abstract Token<K, V> next();
+
+ @Override
+ public abstract boolean hasNext();
/**
* Utility method for checking that the next token is one of a specific
@@ -60,10 +60,10 @@ public interface TokenStream<K, V> {
* @throws ExpectationException
* If the token is not one of the expected types.
*/
- default void expect(Set<K> expectedKeys) throws ExpectationException {
+ public void expect(Set<K> expectedKeys) throws ExpectationException {
K curKey = current().getKey();
- if(!expectedKeys.contains(curKey)) {
+ if (!expectedKeys.contains(curKey)) {
String expectedList = StringUtils.toEnglishList(expectedKeys.toArray(), false);
throw new ExpectationException("One of '" + expectedList + "' was expected, not " + curKey);
@@ -82,7 +82,8 @@ public interface TokenStream<K, V> {
* @throws ExpectationException
* If the token is not one of the expected types.
*/
- default void expect(@SuppressWarnings("unchecked") K... expectedKeys) throws ExpectationException {
+ @SafeVarargs
+ public final void expect(K... expectedKeys) throws ExpectationException {
expect(new HashSet<>(Arrays.asList(expectedKeys)));
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/ParseBlocks.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/ParseBlocks.java
new file mode 100644
index 0000000..43163e6
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/ParseBlocks.java
@@ -0,0 +1,13 @@
+package bjc.utils.parserutils.pratt.blocks;
+
+import bjc.utils.parserutils.pratt.ParseBlock;
+
+/**
+ * Utility class for creating common implementations of {@link ParseBlock}
+ *
+ * @author bjculkin
+ *
+ */
+public class ParseBlocks {
+
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/RepeatingParseBlock.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/RepeatingParseBlock.java
new file mode 100644
index 0000000..08a4bae
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/RepeatingParseBlock.java
@@ -0,0 +1,96 @@
+package bjc.utils.parserutils.pratt.blocks;
+
+import java.util.function.UnaryOperator;
+
+import bjc.utils.data.ITree;
+import bjc.utils.data.Tree;
+import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
+import bjc.utils.parserutils.pratt.ParserContext;
+import bjc.utils.parserutils.pratt.Token;
+
+/**
+ * A parse block that can parse a sequnce of zero or more occurances of another
+ * block.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
+public class RepeatingParseBlock<K, V, C> implements ParseBlock<K, V, C> {
+ private ParseBlock<K, V, C> innerBlock;
+
+ private K delim;
+ private K term;
+
+ private UnaryOperator<C> onDelim;
+
+ private Token<K, V> mark;
+
+ /**
+ * Create a new repeating block.
+ *
+ * @param inner
+ * The inner block for elements.
+ *
+ * @param delimiter
+ * The token that delimits elements in the sequence.
+ *
+ * @param terminator
+ * The token that terminates the sequence.
+ *
+ * @param marker
+ * The token to use as the node in the AST.
+ *
+ * @param action
+ * The action to apply to the state after every
+ * delimiter.
+ */
+ public RepeatingParseBlock(ParseBlock<K, V, C> inner, K delimiter, K terminator, Token<K, V> marker,
+ UnaryOperator<C> action) {
+ super();
+
+ if (inner == null)
+ throw new NullPointerException("Inner block must not be null");
+ else if (delimiter == null)
+ throw new NullPointerException("Delimiter must not be null");
+ else if (terminator == null) throw new NullPointerException("Terminator must not be null");
+
+ innerBlock = inner;
+
+ delim = delimiter;
+ term = terminator;
+
+ mark = marker;
+
+ onDelim = action;
+ }
+
+ @Override
+ public ITree<Token<K, V>> parse(ParserContext<K, V, C> ctx) throws ParserException {
+ ITree<Token<K, V>> ret = new Tree<>(mark);
+
+ Token<K, V> tok = ctx.tokens.current();
+
+ while (!tok.getKey().equals(term)) {
+ ITree<Token<K, V>> kid = innerBlock.parse(ctx);
+ ret.addChild(kid);
+
+ tok = ctx.tokens.current();
+
+ ctx.tokens.expect(delim, term);
+
+ if (onDelim != null) ctx.state = onDelim.apply(ctx.state);
+ }
+
+ return ret;
+ }
+
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/SimpleParseBlock.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/SimpleParseBlock.java
new file mode 100644
index 0000000..c2e9e54
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/SimpleParseBlock.java
@@ -0,0 +1,101 @@
+package bjc.utils.parserutils.pratt.blocks;
+
+import java.util.function.Predicate;
+
+import bjc.utils.data.ITree;
+import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
+import bjc.utils.parserutils.pratt.ParserContext;
+import bjc.utils.parserutils.pratt.Token;
+
+/**
+ * Simple implementation of {@link ParseBlock}
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
+public class SimpleParseBlock<K, V, C> implements ParseBlock<K, V, C> {
+ private int pow;
+
+ private K term;
+
+ private Predicate<ITree<Token<K, V>>> validatr;
+
+ /**
+ * Create a new block.
+ *
+ * @param precedence
+ * The precedence of this block.
+ *
+ * @param terminator
+ * The token type that terminates the block. If this is
+ * null, don't check for a terminator.
+ *
+ * @param validator
+ * The predicate to apply to blocks.
+ */
+ public SimpleParseBlock(int precedence, K terminator, Predicate<ITree<Token<K, V>>> validator) {
+ if (precedence < 0) throw new IllegalArgumentException("Precedence must be non-negative");
+
+ pow = precedence;
+ term = terminator;
+ validatr = validator;
+ }
+
+ @Override
+ public ITree<Token<K, V>> parse(ParserContext<K, V, C> ctx) throws ParserException {
+ ITree<Token<K, V>> res = ctx.parse.parseExpression(pow, ctx.tokens, ctx.state, false);
+
+ if (term != null) {
+ ctx.tokens.expect(term);
+ }
+
+ if (validatr == null || validatr.test(res)) {
+ return res;
+ }
+
+ throw new ParserException("Block failed validation");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+
+ int result = 1;
+
+ result = prime * result + pow;
+ result = prime * result + ((term == null) ? 0 : term.hashCode());
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (!(obj instanceof SimpleParseBlock)) return false;
+
+ SimpleParseBlock<?, ?, ?> other = (SimpleParseBlock<?, ?, ?>) obj;
+
+ if (pow != other.pow) return false;
+
+ if (term == null) {
+ if (other.term != null) return false;
+ } else if (!term.equals(other.term)) return false;
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ParseBlock [pow=%s, term='%s']", pow, term);
+ }
+} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/TriggeredParseBlock.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/TriggeredParseBlock.java
new file mode 100644
index 0000000..fbfc61b
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/blocks/TriggeredParseBlock.java
@@ -0,0 +1,61 @@
+package bjc.utils.parserutils.pratt.blocks;
+
+import java.util.function.UnaryOperator;
+
+import bjc.utils.data.ITree;
+import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
+import bjc.utils.parserutils.pratt.ParserContext;
+import bjc.utils.parserutils.pratt.Token;
+
+/**
+ * A parse block that can adjust the state before handling its context.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ * @param <V>
+ * The value type of the tokens.
+ * @param <C>
+ * The state type of the parser.
+ */
+public class TriggeredParseBlock<K, V, C> implements ParseBlock<K, V, C> {
+ private UnaryOperator<C> onEnter;
+ private UnaryOperator<C> onExit;
+
+ private ParseBlock<K, V, C> source;
+
+ /**
+ * Create a new triggered parse block.
+ *
+ * @param onEnter
+ * The action to fire before parsing the block.
+ *
+ * @param onExit
+ * The action to fire after parsing the block.
+ *
+ * @param source
+ * The block to use for parsing.
+ */
+ public TriggeredParseBlock(UnaryOperator<C> onEnter, UnaryOperator<C> onExit, ParseBlock<K, V, C> source) {
+ super();
+ this.onEnter = onEnter;
+ this.onExit = onExit;
+ this.source = source;
+ }
+
+ @Override
+ public ITree<Token<K, V>> parse(ParserContext<K, V, C> ctx) throws ParserException {
+ C newState = onEnter.apply(ctx.state);
+
+ ParserContext<K, V, C> newCtx = new ParserContext<>(ctx.tokens, ctx.parse, newState);
+
+ ITree<Token<K, V>> res = source.parse(newCtx);
+
+ ctx.state = onExit.apply(newState);
+
+ return res;
+ }
+
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/BinaryPostCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/BinaryPostCommand.java
index 7aaf735..806f2f3 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/BinaryPostCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/BinaryPostCommand.java
@@ -2,14 +2,35 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.parserutils.pratt.NonInitialCommand;
-/*
- * A command with constant binding power.
+/**
+ * A operator with fixed precedence.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
*/
public abstract class BinaryPostCommand<K, V, C> extends NonInitialCommand<K, V, C> {
private final int leftPower;
- public BinaryPostCommand(int power) {
- leftPower = power;
+ /**
+ * Create a new operator with fixed precedence.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ */
+ public BinaryPostCommand(int precedence) {
+ if (precedence < 0) {
+ throw new IllegalArgumentException("Precedence must be non-negative");
+ }
+
+ leftPower = precedence;
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/DelimitedCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/DelimitedCommand.java
deleted file mode 100644
index 090b2f4..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/DelimitedCommand.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package bjc.utils.parserutils.pratt.commands;
-
-import bjc.utils.data.ITree;
-import bjc.utils.data.Tree;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.IList;
-import bjc.utils.parserutils.ParserException;
-import bjc.utils.parserutils.pratt.ParserContext;
-import bjc.utils.parserutils.pratt.Token;
-
-import java.util.function.UnaryOperator;
-
-public class DelimitedCommand<K, V, C> extends AbstractInitialCommand<K, V, C> {
- private int inner;
-
- private K delim;
- private K mark;
-
- private Token<K, V> term;
-
- private UnaryOperator<C> onEnter;
- private UnaryOperator<C> onDelim;
- private UnaryOperator<C> onExit;
-
- private boolean statement;
-
- public DelimitedCommand(int inner, K delim, K mark, Token<K, V> term, UnaryOperator<C> onEnter,
- UnaryOperator<C> onDelim, UnaryOperator<C> onExit, boolean statement) {
- this.inner = inner;
- this.delim = delim;
- this.mark = mark;
- this.term = term;
- this.onEnter = onEnter;
- this.onDelim = onDelim;
- this.onExit = onExit;
- this.statement = statement;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected ITree<Token<K, V>> intNullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
- throws ParserException {
- C newState = onEnter.apply(ctx.state);
-
- IList<ITree<Token<K, V>>> kids = new FunctionalList<>();
-
- while(true) {
- ITree<Token<K, V>> kid = ctx.parse.parseExpression(inner, ctx.tokens, newState,
- statement);
- kids.add(kid);
-
- Token<K, V> tok = ctx.tokens.current();
-
- ctx.tokens.expect(delim, mark);
-
- if(tok.getKey().equals(mark)) break;
-
- newState = onDelim.apply(newState);
- }
-
- ctx.state = onExit.apply(newState);
-
- return new Tree<>(term, kids);
- }
-} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/GroupingCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/GroupingCommand.java
index 407a39e..37cc6ee 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/GroupingCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/GroupingCommand.java
@@ -3,27 +3,48 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.data.ITree;
import bjc.utils.data.Tree;
import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A grouping operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class GroupingCommand<K, V, C> extends AbstractInitialCommand<K, V, C> {
- private K term;
- private Token<K, V> mark;
- private int inner;
+ private ParseBlock<K, V, C> innerBlock;
+
+ private Token<K, V> mark;
+
+ /**
+ * Create a new grouping command.
+ *
+ * @param inner
+ * The inner block.
+ *
+ * @param marker
+ * The token to use as the node in the AST.
+ */
+ public GroupingCommand(ParseBlock<K, V, C> inner, Token<K, V> marker) {
+ innerBlock = inner;
- public GroupingCommand(int innerPrec, K terminator, Token<K, V> marker) {
- inner = innerPrec;
- term = terminator;
mark = marker;
}
- @SuppressWarnings("unchecked")
@Override
protected ITree<Token<K, V>> intNullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
throws ParserException {
- ITree<Token<K, V>> opr = ctx.parse.parseExpression(inner, ctx.tokens, ctx.state, false);
-
- ctx.tokens.expect(term);
+ ITree<Token<K, V>> opr = innerBlock.parse(ctx);
return new Tree<>(mark, opr);
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/InitialCommands.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/InitialCommands.java
index d9e7f90..bad5964 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/InitialCommands.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/InitialCommands.java
@@ -2,7 +2,11 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.data.ITree;
import bjc.utils.parserutils.pratt.InitialCommand;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.Token;
+import bjc.utils.parserutils.pratt.blocks.RepeatingParseBlock;
+import bjc.utils.parserutils.pratt.blocks.SimpleParseBlock;
+import bjc.utils.parserutils.pratt.blocks.TriggeredParseBlock;
import java.util.function.UnaryOperator;
@@ -41,7 +45,9 @@ public class InitialCommands {
* @return A command implementing the operator.
*/
public static <K, V, C> InitialCommand<K, V, C> grouping(int precedence, K term, Token<K, V> mark) {
- return new GroupingCommand<>(precedence, term, mark);
+ ParseBlock<K, V, C> innerBlock = new SimpleParseBlock<>(precedence, term, null);
+
+ return new GroupingCommand<>(innerBlock, mark);
}
/**
@@ -78,7 +84,11 @@ public class InitialCommands {
*/
public static <K, V, C> InitialCommand<K, V, C> preTernary(int cond1, int block1, int block2, K mark1, K mark2,
Token<K, V> term) {
- return new PreTernaryCommand<>(cond1, block1, block2, mark1, mark2, term);
+ ParseBlock<K, V, C> condBlock = new SimpleParseBlock<>(cond1, mark1, null);
+ ParseBlock<K, V, C> opblock1 = new SimpleParseBlock<>(block1, mark2, null);
+ ParseBlock<K, V, C> opblock2 = new SimpleParseBlock<>(block2, null, null);
+
+ return new PreTernaryCommand<>(condBlock, opblock1, opblock2, term);
}
/**
@@ -129,6 +139,16 @@ public class InitialCommands {
public static <K, V, C> InitialCommand<K, V, C> delimited(int inner, K delim, K mark, Token<K, V> term,
UnaryOperator<C> onEnter, UnaryOperator<C> onDelim, UnaryOperator<C> onExit,
boolean statement) {
- return new DelimitedCommand<>(inner, delim, mark, term, onEnter, onDelim, onExit, statement);
+ ParseBlock<K, V, C> innerBlock = new SimpleParseBlock<>(inner, null, null);
+ ParseBlock<K, V, C> delimsBlock = new RepeatingParseBlock<>(innerBlock, delim, mark, term, onDelim);
+ ParseBlock<K, V, C> scopedBlock = new TriggeredParseBlock<>(onEnter, onExit, delimsBlock);
+
+ GroupingCommand<K, V, C> command = new GroupingCommand<>(scopedBlock, term);
+
+ /*
+ * Remove the wrapper layer from grouping-command on top of
+ * RepeatingParseBlock.
+ */
+ return new TransformingInitialCommand<>(command, (tree) -> tree.getChild(0));
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeafCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeafCommand.java
index 87fe7c1..3937f5f 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeafCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeafCommand.java
@@ -7,11 +7,23 @@ import bjc.utils.parserutils.pratt.InitialCommand;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A operator that stands for itself.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class LeafCommand<K, V, C> implements InitialCommand<K, V, C> {
@Override
- public ITree<Token<K, V>> denote(Token<K, V> operator, ParserContext<K, V, C> ctx)
- throws ParserException {
-
+ public ITree<Token<K, V>> denote(Token<K, V> operator, ParserContext<K, V, C> ctx) throws ParserException {
return new Tree<>(operator);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeftBinaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeftBinaryCommand.java
index 1306735..58d7261 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeftBinaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/LeftBinaryCommand.java
@@ -1,8 +1,28 @@
package bjc.utils.parserutils.pratt.commands;
+/**
+ * A left-associative operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class LeftBinaryCommand<K, V, C> extends BinaryCommand<K, V, C> {
- public LeftBinaryCommand(int leftPower) {
- super(leftPower);
+ /**
+ * Create a new left-associative operator.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ */
+ public LeftBinaryCommand(int precedence) {
+ super(precedence);
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonBinaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonBinaryCommand.java
index 36ea0e1..d32a1a7 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonBinaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonBinaryCommand.java
@@ -1,8 +1,28 @@
package bjc.utils.parserutils.pratt.commands;
+/**
+ * A non-associative operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class NonBinaryCommand<K, V, C> extends BinaryCommand<K, V, C> {
- public NonBinaryCommand(int leftPower) {
- super(leftPower);
+ /**
+ * Create a new non-associative operator.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ */
+ public NonBinaryCommand(int precedence) {
+ super(precedence);
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonInitialCommands.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonInitialCommands.java
index 086ecf8..45bdc51 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonInitialCommands.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/NonInitialCommands.java
@@ -1,7 +1,9 @@
package bjc.utils.parserutils.pratt.commands;
import bjc.utils.parserutils.pratt.NonInitialCommand;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.Token;
+import bjc.utils.parserutils.pratt.blocks.SimpleParseBlock;
import java.util.Set;
@@ -101,7 +103,9 @@ public class NonInitialCommands {
*/
public static <K, V, C> NonInitialCommand<K, V, C> postCircumfix(int precedence, int insidePrecedence, K closer,
Token<K, V> marker) {
- return new PostCircumfixCommand<>(precedence, insidePrecedence, closer, marker);
+ ParseBlock<K, V, C> innerBlock = new SimpleParseBlock<>(insidePrecedence, closer, null);
+
+ return new PostCircumfixCommand<>(precedence, innerBlock, marker);
}
/**
@@ -129,6 +133,8 @@ public class NonInitialCommands {
*/
public static <K, V, C> NonInitialCommand<K, V, C> ternary(int precedence, int insidePrecedence, K closer,
Token<K, V> marker, boolean nonassoc) {
- return new TernaryCommand<>(insidePrecedence, closer, marker, nonassoc);
+ ParseBlock<K, V, C> innerBlock = new SimpleParseBlock<>(insidePrecedence, closer, null);
+
+ return new TernaryCommand<>(precedence, innerBlock, marker, nonassoc);
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostCircumfixCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostCircumfixCommand.java
index ba5099e..90fca00 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostCircumfixCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostCircumfixCommand.java
@@ -3,29 +3,57 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.data.ITree;
import bjc.utils.data.Tree;
import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A post-circumfix operator, like array indexing.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class PostCircumfixCommand<K, V, C> extends BinaryPostCommand<K, V, C> {
- private int insidePrec;
- private K term;
- private Token<K, V> mark;
+ private ParseBlock<K, V, C> innerBlock;
- public PostCircumfixCommand(int leftPower, int insidePower, K terminator, Token<K, V> marker) {
- super(leftPower);
+ private Token<K, V> mark;
+
+ /**
+ * Create a new post-circumfix operator.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ *
+ * @param inner
+ * The block inside the expression.
+ *
+ * @param marker
+ * The token to use as the node for the AST.
+ */
+ public PostCircumfixCommand(int precedence, ParseBlock<K, V, C> inner, Token<K, V> marker) {
+ super(precedence);
+
+ if (inner == null) {
+ throw new NullPointerException("Inner block must not be null");
+ }
+
+ innerBlock = inner;
- insidePrec = insidePower;
- term = terminator;
mark = marker;
}
- @SuppressWarnings("unchecked")
@Override
- public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator,
- ParserContext<K, V, C> ctx) throws ParserException {
- ITree<Token<K, V>> inside = ctx.parse.parseExpression(insidePrec, ctx.tokens, ctx.state, false);
-
- ctx.tokens.expect(term);
+ public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator, ParserContext<K, V, C> ctx)
+ throws ParserException {
+ ITree<Token<K, V>> inside = innerBlock.parse(ctx);
return new Tree<>(mark, operand, inside);
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostfixCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostfixCommand.java
index 19c540a..bab3de4 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostfixCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PostfixCommand.java
@@ -6,14 +6,34 @@ import bjc.utils.parserutils.ParserException;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A postfix operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class PostfixCommand<K, V, C> extends BinaryPostCommand<K, V, C> {
- public PostfixCommand(int leftPower) {
- super(leftPower);
+ /**
+ * Create a new postfix operator.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ */
+ public PostfixCommand(int precedence) {
+ super(precedence);
}
@Override
- public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator,
- ParserContext<K, V, C> ctx) throws ParserException {
+ public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator, ParserContext<K, V, C> ctx)
+ throws ParserException {
return new Tree<>(operator, operand);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PreTernaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PreTernaryCommand.java
index 04604be..42d1a6e 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PreTernaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/PreTernaryCommand.java
@@ -3,43 +3,73 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.data.ITree;
import bjc.utils.data.Tree;
import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A prefix ternary operator, like an if/then/else group.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class PreTernaryCommand<K, V, C> extends AbstractInitialCommand<K, V, C> {
- private int cond1;
- private int block1;
- private int block2;
+ private Token<K, V> term;
- private K mark1;
- private K mark2;
+ private ParseBlock<K, V, C> condBlock;
- private Token<K, V> term;
+ private ParseBlock<K, V, C> opblock1;
+ private ParseBlock<K, V, C> opblock2;
- public PreTernaryCommand(int cond1, int block1, int block2, K mark1, K mark2, Token<K, V> term) {
+ /**
+ * Create a new ternary statement.
+ *
+ * @param cond
+ * The block for handling the condition.
+ *
+ * @param op1
+ * The block for handling the first operator.
+ *
+ * @param op2
+ * The block for handling the second operator.
+ *
+ * @param term
+ * The token to use as the node for the AST.
+ */
+ public PreTernaryCommand(ParseBlock<K, V, C> cond, ParseBlock<K, V, C> op1, ParseBlock<K, V, C> op2,
+ Token<K, V> term) {
super();
- this.cond1 = cond1;
- this.block1 = block1;
- this.block2 = block2;
- this.mark1 = mark1;
- this.mark2 = mark2;
+
+ if (cond == null)
+ throw new NullPointerException("Cond block must not be null");
+ else if (op1 == null)
+ throw new NullPointerException("Op block #1 must not be null");
+ else if (op2 == null) throw new NullPointerException("Op block #2 must not be null");
+
+ this.condBlock = cond;
+ this.opblock1 = op1;
+ this.opblock2 = op2;
+
this.term = term;
}
- @SuppressWarnings("unchecked")
@Override
protected ITree<Token<K, V>> intNullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
throws ParserException {
- ITree<Token<K, V>> cond = ctx.parse.parseExpression(cond1, ctx.tokens, ctx.state, false);
-
- ctx.tokens.expect(mark1);
-
- ITree<Token<K, V>> fstBlock = ctx.parse.parseExpression(block1, ctx.tokens, ctx.state, false);
+ ITree<Token<K, V>> cond = condBlock.parse(ctx);
- ctx.tokens.expect(mark2);
+ ITree<Token<K, V>> op1 = opblock1.parse(ctx);
- ITree<Token<K, V>> sndBlock = ctx.parse.parseExpression(block2, ctx.tokens, ctx.state, false);
+ ITree<Token<K, V>> op2 = opblock2.parse(ctx);
- return new Tree<>(term, cond, fstBlock, sndBlock);
+ return new Tree<>(term, cond, op1, op2);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/RightBinaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/RightBinaryCommand.java
index 729c33d..5f3d9f2 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/RightBinaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/RightBinaryCommand.java
@@ -1,8 +1,26 @@
package bjc.utils.parserutils.pratt.commands;
+/**
+ * A right-associative binary operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ * @param <V>
+ * The value type of the tokens.
+ * @param <C>
+ * The state type of the parser.
+ */
public class RightBinaryCommand<K, V, C> extends BinaryCommand<K, V, C> {
- public RightBinaryCommand(int leftPower) {
- super(leftPower);
+ /**
+ * Create a new right-associative operator.
+ *
+ * @param precedence
+ * The precedence of the operator.
+ */
+ public RightBinaryCommand(int precedence) {
+ super(precedence);
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TernaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TernaryCommand.java
index c3204b9..8f04368 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TernaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TernaryCommand.java
@@ -3,33 +3,63 @@ package bjc.utils.parserutils.pratt.commands;
import bjc.utils.data.ITree;
import bjc.utils.data.Tree;
import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.ParseBlock;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A ternary command, like C's ?:
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class TernaryCommand<K, V, C> extends BinaryPostCommand<K, V, C> {
- private K term;
-
- private int innerExp;
+ private ParseBlock<K, V, C> innerBlck;
private Token<K, V> mark;
private boolean nonassoc;
- public TernaryCommand(int leftPower, K terminator, Token<K, V> marker, boolean isNonassoc) {
- super(leftPower);
+ /**
+ * Create a new ternary command.
+ *
+ * @param precedence
+ * The precedence of this operator.
+ *
+ * @param innerBlock
+ * The representation of the inner block of the
+ * expression.
+ *
+ * @param marker
+ * The token to use as the root of the AST node.
+ *
+ * @param isNonassoc
+ * Whether or not the conditional is associative.
+ */
+ public TernaryCommand(int precedence, ParseBlock<K, V, C> innerBlock, Token<K, V> marker, boolean isNonassoc) {
+ super(precedence);
+
+ if (innerBlock == null)
+ throw new NullPointerException("Inner block must not be null");
+ else if (marker == null) throw new NullPointerException("Marker must not be null");
- term = terminator;
+ innerBlck = innerBlock;
mark = marker;
nonassoc = isNonassoc;
}
- @SuppressWarnings("unchecked")
@Override
- public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator,
- ParserContext<K, V, C> ctx) throws ParserException {
- ITree<Token<K, V>> inner = ctx.parse.parseExpression(innerExp, ctx.tokens, ctx.state, false);
-
- ctx.tokens.expect(term);
+ public ITree<Token<K, V>> denote(ITree<Token<K, V>> operand, Token<K, V> operator, ParserContext<K, V, C> ctx)
+ throws ParserException {
+ ITree<Token<K, V>> inner = innerBlck.parse(ctx);
ITree<Token<K, V>> outer = ctx.parse.parseExpression(1 + leftBinding(), ctx.tokens, ctx.state, false);
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TransformingInitialCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TransformingInitialCommand.java
new file mode 100644
index 0000000..88803df
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/TransformingInitialCommand.java
@@ -0,0 +1,52 @@
+package bjc.utils.parserutils.pratt.commands;
+
+import java.util.function.UnaryOperator;
+
+import bjc.utils.data.ITree;
+import bjc.utils.parserutils.ParserException;
+import bjc.utils.parserutils.pratt.InitialCommand;
+import bjc.utils.parserutils.pratt.ParserContext;
+import bjc.utils.parserutils.pratt.Token;
+
+/**
+ * An initial command that transforms the result of another command.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
+public class TransformingInitialCommand<K, V, C> extends AbstractInitialCommand<K, V, C> {
+ private InitialCommand<K, V, C> internal;
+
+ private UnaryOperator<ITree<Token<K, V>>> transform;
+
+ /**
+ * Create a new transforming initial command.
+ *
+ * @param internal
+ * The initial command to delegate to.
+ *
+ * @param transform
+ * The transform to apply to the returned tree.
+ */
+ public TransformingInitialCommand(InitialCommand<K, V, C> internal,
+ UnaryOperator<ITree<Token<K, V>>> transform) {
+ super();
+ this.internal = internal;
+ this.transform = transform;
+ }
+
+ @Override
+ protected ITree<Token<K, V>> intNullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
+ throws ParserException {
+ return transform.apply(internal.denote(operator, ctx));
+ }
+
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/UnaryCommand.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/UnaryCommand.java
index 9a79d21..c608362 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/UnaryCommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands/UnaryCommand.java
@@ -6,11 +6,35 @@ import bjc.utils.parserutils.ParserException;
import bjc.utils.parserutils.pratt.ParserContext;
import bjc.utils.parserutils.pratt.Token;
+/**
+ * A unary operator.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The key type of the tokens.
+ *
+ * @param <V>
+ * The value type of the tokens.
+ *
+ * @param <C>
+ * The state type of the parser.
+ */
public class UnaryCommand<K, V, C> extends AbstractInitialCommand<K, V, C> {
private final int nullPwer;
- public UnaryCommand(int nullPower) {
- nullPwer = nullPower;
+ /**
+ * Create a new unary command.
+ *
+ * @param precedence
+ * The precedence of this operator.
+ */
+ public UnaryCommand(int precedence) {
+ if(precedence < 0) {
+ throw new IllegalArgumentException("Precedence must be non-negative");
+ }
+
+ nullPwer = precedence;
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringToken.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringToken.java
index 74f9c63..7e779aa 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringToken.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringToken.java
@@ -1,4 +1,6 @@
-package bjc.utils.parserutils.pratt;
+package bjc.utils.parserutils.pratt.tokens;
+
+import bjc.utils.parserutils.pratt.Token;
/**
* Simple token implementation for strings.
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringTokenStream.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringTokenStream.java
index 8caeef9..d7d4a66 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/StringTokenStream.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/tokens/StringTokenStream.java
@@ -1,7 +1,10 @@
-package bjc.utils.parserutils.pratt;
+package bjc.utils.parserutils.pratt.tokens;
import java.util.Iterator;
+import bjc.utils.parserutils.pratt.Token;
+import bjc.utils.parserutils.pratt.TokenStream;
+
/**
* Simple implementation of token stream for strings.
*
@@ -11,7 +14,7 @@ import java.util.Iterator;
* @author EVE
*
*/
-public class StringTokenStream implements TokenStream<String, String> {
+public class StringTokenStream extends TokenStream<String, String> {
private Iterator<Token<String, String>> iter;
private Token<String, String> curr;
@@ -34,11 +37,18 @@ public class StringTokenStream implements TokenStream<String, String> {
}
@Override
- public void next() {
- if(iter.hasNext()) {
+ public Token<String, String> next() {
+ if (iter.hasNext()) {
curr = iter.next();
} else {
curr = new StringToken("(end)", null);
}
+
+ return curr;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
}
}