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 * The token key type. * * @param * The token value type. * * @param * The parser state type. * */ public class ChainParseBlock implements ParseBlock { private ParseBlock iner; private Set indicators; private Token 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 inner, Set chainIndicators, Token term) { iner = inner; indicators = chainIndicators; trm = term; } @Override public CommandResult parse(ParserContext ctx) throws ParserException { CommandResult resOuter = iner.parse(ctx); if (resOuter.status != Status.SUCCESS) return resOuter; Tree> expression = resOuter.success(); Token currentToken = ctx.tokens.current(); if(indicators.contains(currentToken.getKey())) { Tree> res = new SimpleTree<>(trm); res.addChild(expression); while(indicators.contains(currentToken.getKey())) { res.addChild(new SimpleTree<>(currentToken)); ctx.tokens.next(); CommandResult resInner = iner.parse(ctx); if (resInner.status != Status.SUCCESS) return resInner; Tree> innerExpression = resInner.success(); res.addChild(innerExpression); currentToken = ctx.tokens.current(); } return CommandResult.success(res); } return resOuter; } }