package bjc.pratt.commands.impls; import static bjc.pratt.blocks.ParseBlocks.repeating; import static bjc.pratt.blocks.ParseBlocks.simple; import static bjc.pratt.blocks.ParseBlocks.trigger; import java.util.function.UnaryOperator; import bjc.pratt.blocks.ParseBlock; import bjc.pratt.commands.InitialCommand; import bjc.pratt.tokens.Token; import bjc.data.ITree; /** * * Contains factory methods for producing common implementations of * {@link InitialCommand} * * @author EVE * */ public class InitialCommands { /** * Create a new unary operator. * * @param precedence * The precedence of the operator. * * @return A command implementing that operator. */ public static InitialCommand unary(final int precedence) { return new UnaryCommand<>(precedence); } /** * Create a new grouping operator. * * @param precedence * The precedence of the expression in the operator. * * @param term * The type that closes the group. * * @param mark * The token for the AST node of the group. * * @return A command implementing the operator. */ public static InitialCommand grouping(final int precedence, final K term, final Token mark) { final ParseBlock innerBlock = simple(precedence, term, null); return new GroupingCommand<>(innerBlock, mark); } /** * Create a new leaf operator. * * @return A command implementing the operator. */ public static InitialCommand leaf() { return new LeafCommand<>(); } /** * Create a new pre-ternary operator, like an if-then-else statement. * * @param cond1 * The priority of the first block. * * @param block1 * The priority of the second block. * * @param block2 * The priority of the third block. * * @param mark1 * The marker that ends the first block. * * @param mark2 * The marker that ends the second block. * * @param term * The token for the AST node of the group. * * @return A command implementing the operator. */ public static InitialCommand preTernary(final int cond1, final int block1, final int block2, final K mark1, final K mark2, final Token term) { final ParseBlock condBlock = simple(cond1, mark1, null); final ParseBlock opblock1 = simple(block1, mark2, null); final ParseBlock opblock2 = simple(block2, null, null); return new PreTernaryCommand<>(condBlock, opblock1, opblock2, term); } /** * Create a new named constant. * * @param val * The value of the constant. * * @return A command implementing the constant. */ public static InitialCommand constant(final ITree> val) { return new ConstantCommand<>(val); } /** * Create a new delimited command. This is for block-like constructs. * * @param inner * The precedence of the inner blocks. * * @param delim * The marker between sub-blocks. * * @param mark * The block terminator. * * @param term * The token for the AST node of the group. * * @param onEnter * The function to apply to the state on entering the block. * * @param onDelim * The function to apply to the state on finishing a sub-block. * * @param onExit * The function to apply to the state on exiting the block. * * @param statement * Whether or not the sub-blocks are statements or expressions. * * @return A command implementing the operator. */ public static InitialCommand delimited(final int inner, final K delim, final K mark, final Token term, final UnaryOperator onEnter, final UnaryOperator onDelim, final UnaryOperator onExit, final boolean statement) { final ParseBlock innerBlock = simple(inner, null, null); final ParseBlock delimsBlock = repeating(innerBlock, delim, mark, term, onDelim); final ParseBlock scopedBlock = trigger(delimsBlock, onEnter, onExit); final GroupingCommand command = new GroupingCommand<>(scopedBlock, term); /* * Remove the wrapper layer from grouping-command on top of * RepeatingParseBlock. */ return denest(command); } /** * Create a new denesting command. * * This removes one tree-level, and is useful when combining complex * parse blocks with commands. * * @param comm * The command to denest. * * @return A command that denests the result of the provided command. */ public static InitialCommand denest(final InitialCommand comm) { return new DenestingCommand<>(comm); } }