diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/commands')
15 files changed, 402 insertions, 145 deletions
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 |
