summaryrefslogtreecommitdiff
path: root/JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java
diff options
context:
space:
mode:
Diffstat (limited to 'JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java')
-rw-r--r--JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java86
1 files changed, 86 insertions, 0 deletions
diff --git a/JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java b/JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java
new file mode 100644
index 0000000..fe04070
--- /dev/null
+++ b/JPratt/src/main/java/com/ashardalon/pratt/blocks/ChainParseBlock.java
@@ -0,0 +1,86 @@
+package com.ashardalon.pratt.blocks;
+
+import java.util.Set;
+
+import com.ashardalon.pratt.ParserContext;
+import com.ashardalon.pratt.commands.CommandResult;
+import com.ashardalon.pratt.commands.CommandResult.Status;
+import com.ashardalon.pratt.tokens.Token;
+
+import bjc.data.Tree;
+import bjc.data.SimpleTree;
+import bjc.utils.parserutils.ParserException;
+
+/**
+ * A {@link ParseBlock} for a series of parse blocks, linked by a set of tokens.
+ *
+ * Roughly analogous to Perl 6s list associative operators.
+ *
+ * @author bjculkin
+ *
+ * @param <K>
+ * The token key type.
+ *
+ * @param <V>
+ * The token value type.
+ *
+ * @param <C>
+ * The parser state type.
+ *
+ */
+public class ChainParseBlock<K, V, C> implements ParseBlock<K, V, C> {
+ private ParseBlock<K, V, C> iner;
+
+ private Set<K> indicators;
+
+ private Token<K, V> trm;
+
+ /**
+ * Create a new chain parser block.
+ *
+ * @param inner
+ * The block for the chains interior.
+ *
+ * @param chainIndicators
+ * The set of markers that indicate continuing the chain
+ *
+ * @param term
+ * The node in the AST for the expression.
+ */
+ public ChainParseBlock(ParseBlock<K, V, C> inner, Set<K> chainIndicators, Token<K, V> term) {
+ iner = inner;
+ indicators = chainIndicators;
+ trm = term;
+ }
+
+ @Override
+ public CommandResult<K, V> parse(ParserContext<K, V, C> ctx) throws ParserException {
+ CommandResult<K,V> resOuter = iner.parse(ctx);
+ if (resOuter.status != Status.SUCCESS) return resOuter;
+
+ Tree<Token<K, V>> expression = resOuter.success();
+ Token<K, V> currentToken = ctx.tokens.current();
+ if(indicators.contains(currentToken.getKey())) {
+ Tree<Token<K, V>> res = new SimpleTree<>(trm);
+ res.addChild(expression);
+
+ while(indicators.contains(currentToken.getKey())) {
+ res.addChild(new SimpleTree<>(currentToken));
+ ctx.tokens.next();
+
+ CommandResult<K,V> resInner = iner.parse(ctx);
+ if (resInner.status != Status.SUCCESS) return resInner;
+
+ Tree<Token<K, V>> innerExpression = resInner.success();
+ res.addChild(innerExpression);
+
+ currentToken = ctx.tokens.current();
+ }
+
+ return CommandResult.success(res);
+ }
+
+ return resOuter;
+ }
+
+}