summaryrefslogtreecommitdiff
path: root/BJC-Utils2
diff options
context:
space:
mode:
authorstudent <student@192.168.1.186>2017-03-24 11:51:10 -0400
committerstudent <student@192.168.1.186>2017-03-24 11:51:10 -0400
commitb168fd38be0bb344d268bfd11d14df36bb9fd4f2 (patch)
treeeed830c512ffa54b7afc4972cba67c2c818b8740 /BJC-Utils2
parent33918524d7faab0146a0a92c13eaaef46cdbea8a (diff)
Update Pratt parser
Diffstat (limited to 'BJC-Utils2')
-rw-r--r--BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/PrattParserTest.java42
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/LeftCommands.java10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/NullCommands.java112
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/PrattParser.java53
4 files changed, 167 insertions, 50 deletions
diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/PrattParserTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/PrattParserTest.java
index 8634641..b4d40b2 100644
--- a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/PrattParserTest.java
+++ b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/PrattParserTest.java
@@ -32,7 +32,7 @@ public class PrattParserTest {
* Main method.
*
* @param args
- * Unused CLI arguments.
+ * Unused CLI arguments.
*/
public static void main(String[] args) {
/*
@@ -41,8 +41,10 @@ public class PrattParserTest {
Set<String> ops = new LinkedHashSet<>();
ops.add(":=");
+ ops.addAll(Arrays.asList("||", "&&"));
ops.addAll(Arrays.asList("<=", ">="));
+ ops.add(".");
ops.addAll(Arrays.asList("=", "<", ">"));
ops.addAll(Arrays.asList("+", "-", "*", "/"));
ops.addAll(Arrays.asList("^", "!"));
@@ -53,9 +55,9 @@ public class PrattParserTest {
* Reserved words that represent themselves, not literals.
*/
Set<String> reserved = new LinkedHashSet<>();
- reserved.add("if");
- reserved.add("else");
-
+ reserved.addAll(Arrays.asList("if", "then", "else"));
+ reserved.addAll(Arrays.asList("and", "or"));
+
TokenSplitter split = new TokenSplitter();
ops.forEach(split::addDelimiter);
@@ -81,7 +83,7 @@ public class PrattParserTest {
*/
tokenStream.next();
- ITree<Token<String, String>> tree = parser.parseExpression(0, tokenStream, null);
+ ITree<Token<String, String>> tree = parser.parseExpression(0, tokenStream, null, true);
if (!tokenStream.current().getKey().equals("(end)")) {
System.out.println("Multipe expressions on line");
@@ -129,8 +131,8 @@ public class PrattParserTest {
/*
* Set of which relational operators chain with each other.
*/
- HashSet<String> chainSet = new HashSet<>();
- chainSet.addAll(Arrays.asList("=", "<", ">", "<=", ">="));
+ HashSet<String> relChain = new HashSet<>();
+ relChain.addAll(Arrays.asList("=", "<", ">", "<=", ">="));
/*
* Token for marking chains.
@@ -143,12 +145,18 @@ public class PrattParserTest {
parser.addNonInitialCommand(":=", infixNon(10));
- parser.addNonInitialCommand("=", chain(10, chainSet, chainToken));
- parser.addNonInitialCommand("<", chain(10, chainSet, chainToken));
- parser.addNonInitialCommand(">", chain(10, chainSet, chainToken));
- parser.addNonInitialCommand("<=", chain(10, chainSet, chainToken));
- parser.addNonInitialCommand(">=", chain(10, chainSet, chainToken));
-
+ parser.addNonInitialCommand("and", infixLeft(13));
+ parser.addNonInitialCommand("or", infixLeft(13));
+
+ parser.addNonInitialCommand("=", chain(15, relChain, chainToken));
+ parser.addNonInitialCommand("<", chain(15, relChain, chainToken));
+ parser.addNonInitialCommand(">", chain(15, relChain, chainToken));
+ parser.addNonInitialCommand("<=", chain(15, relChain, chainToken));
+ parser.addNonInitialCommand(">=", chain(15, relChain, chainToken));
+
+ parser.addNonInitialCommand("&&", infixRight(17));
+ parser.addNonInitialCommand("||", infixRight(17));
+
parser.addNonInitialCommand("+", infixLeft(20));
parser.addNonInitialCommand("-", infixLeft(20));
@@ -159,10 +167,18 @@ public class PrattParserTest {
parser.addNonInitialCommand("^", infixRight(50));
+ parser.addNonInitialCommand(".", infixLeft(60));
+
parser.addNonInitialCommand("[", postCircumfix(60, 0, "]", new StringToken("idx", "idx")));
+ parser.addInitialCommand("if", preTernary(0, 0, 0, "then", "else", new StringToken("ifelse", "ifelse")));
+
parser.addInitialCommand("(", grouping(0, ")", new StringToken("()", "()")));
+
+ parser.addInitialCommand("-", unary(30));
+
parser.addInitialCommand("(literal)", leaf());
+
return parser;
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/LeftCommands.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/LeftCommands.java
index 5844c49..82ec843 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/LeftCommands.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/LeftCommands.java
@@ -40,7 +40,7 @@ public class LeftCommands {
@Override
public ITree<Token<K, V>> leftDenote(ITree<Token<K, V>> operand, Token<K, V> operator,
ParserContext<K, V, C> ctx) throws ParserException {
- ITree<Token<K, V>> opr = ctx.parse.parseExpression(rightBinding(), ctx.tokens, ctx.state);
+ ITree<Token<K, V>> opr = ctx.parse.parseExpression(rightBinding(), ctx.tokens, ctx.state, false);
return new Tree<>(operator, operand, opr);
}
@@ -101,7 +101,7 @@ public class LeftCommands {
@Override
public ITree<Token<K, V>> leftDenote(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);
+ ITree<Token<K, V>> inside = ctx.parse.parseExpression(insidePrec, ctx.tokens, ctx.state, false);
ctx.tokens.expect(term);
@@ -142,11 +142,11 @@ public class LeftCommands {
@Override
public ITree<Token<K, V>> leftDenote(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);
+ ITree<Token<K, V>> inner = ctx.parse.parseExpression(innerExp, ctx.tokens, ctx.state, false);
ctx.tokens.expect(term);
- ITree<Token<K, V>> outer = ctx.parse.parseExpression(1 + leftBinding(), ctx.tokens, ctx.state);
+ ITree<Token<K, V>> outer = ctx.parse.parseExpression(1 + leftBinding(), ctx.tokens, ctx.state, false);
return new Tree<>(mark, inner, operand, outer);
}
@@ -176,7 +176,7 @@ public class LeftCommands {
@Override
public ITree<Token<K, V>> leftDenote(ITree<Token<K, V>> operand, Token<K, V> operator,
ParserContext<K, V, C> ctx) throws ParserException {
- ITree<Token<K, V>> tree = ctx.parse.parseExpression(1 + leftBinding(), ctx.tokens, ctx.state);
+ ITree<Token<K, V>> tree = ctx.parse.parseExpression(1 + leftBinding(), ctx.tokens, ctx.state, false);
ITree<Token<K, V>> res = new Tree<>(operator, operand, tree);
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/NullCommands.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/NullCommands.java
index cf57241..f0c2a80 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/NullCommands.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/NullCommands.java
@@ -16,7 +16,7 @@ public class NullCommands {
@Override
public ITree<Token<K, V>> nullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
throws ParserException {
- //tokens.next();
+ // tokens.next();
return intNullDenotation(operator, ctx);
}
@@ -36,16 +36,16 @@ public class NullCommands {
@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(nullPwer, ctx.tokens, ctx.state);
+ ITree<Token<K, V>> opr = ctx.parse.parseExpression(nullPwer, ctx.tokens, ctx.state, false);
return new Tree<>(operator, opr);
}
}
private static class GroupingCommand<K, V, C> extends AbstractNullCommand<K, V, C> {
- private K term;
- private Token<K, V> mark;
- private int inner;
+ private K term;
+ private Token<K, V> mark;
+ private int inner;
public GroupingCommand(int innerPrec, K terminator, Token<K, V> marker) {
inner = innerPrec;
@@ -57,7 +57,7 @@ public class NullCommands {
@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);
+ ITree<Token<K, V>> opr = ctx.parse.parseExpression(inner, ctx.tokens, ctx.state, false);
ctx.tokens.expect(term);
@@ -74,11 +74,63 @@ public class NullCommands {
}
}
+ private static class ConstantCommand<K, V, C> extends NullCommand<K, V, C> {
+ private ITree<Token<K, V>> val;
+
+ public ConstantCommand(ITree<Token<K, V>> con) {
+ val = con;
+ }
+
+ @Override
+ public ITree<Token<K, V>> nullDenotation(Token<K, V> operator, ParserContext<K, V, C> ctx)
+ throws ParserException {
+ return val;
+ }
+ }
+
+ private static class PreTernaryCommand<K, V, C> extends AbstractNullCommand<K, V, C> {
+ private int cond1;
+ private int block1;
+ private int block2;
+
+ private K mark1;
+ private K mark2;
+
+ private Token<K, V> term;
+
+ public PreTernaryCommand(int cond1, int block1, int block2, K mark1, K mark2, Token<K, V> term) {
+ super();
+ this.cond1 = cond1;
+ this.block1 = block1;
+ this.block2 = block2;
+ this.mark1 = mark1;
+ this.mark2 = mark2;
+ 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);
+
+ ctx.tokens.expect(mark2);
+
+ ITree<Token<K, V>> sndBlock = ctx.parse.parseExpression(block2, ctx.tokens, ctx.state, false);
+
+ return new Tree<>(term, cond, fstBlock, sndBlock);
+ }
+ }
+
/**
* Create a new unary operator.
*
* @param precedence
- * The precedence of the operator.
+ * The precedence of the operator.
*
* @return A command implementing that operator.
*/
@@ -90,13 +142,13 @@ public class NullCommands {
* Create a new grouping operator.
*
* @param precedence
- * The precedence of the expression in the operator.
+ * The precedence of the expression in the operator.
*
* @param term
- * The type that closes the group.
+ * The type that closes the group.
*
* @param mark
- * The token for the AST node of the group.
+ * The token for the AST node of the group.
*
* @return A command implementing the operator.
*/
@@ -112,4 +164,44 @@ public class NullCommands {
public static <K, V, C> NullCommand<K, V, C> 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 <K, V, C> NullCommand<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);
+ }
+
+ /**
+ * Create a new named constant.
+ *
+ * @param val
+ * The value of the constant.
+ *
+ * @return A command implementing the constant.
+ */
+ public static <K, V, C> NullCommand<K, V, C> constant(ITree<Token<K, V>> val) {
+ return new ConstantCommand<>(val);
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/PrattParser.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/PrattParser.java
index a2cefda..a8c273d 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/PrattParser.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/pratt/PrattParser.java
@@ -13,66 +13,75 @@ import java.util.Map;
* @author EVE
*
* @param <K>
- * The key type for the tokens.
+ * The key type for the tokens.
*
* @param <V>
- * The value type for the tokens.
+ * The value type for the tokens.
*
* @param <C>
- * The state type of the parser.
+ * The state type of the parser.
*
*
*/
public class PrattParser<K, V, C> {
- private final LeftCommand<K, V, C> DEFAULT_LEFT_COMMAND = new DefaultLeftCommand<>();
- private final NullCommand<K, V, C> DEFAULT_NULL_COMMAND = new DefaultNullCommand<>();
+ private final LeftCommand<K, V, C> DEFAULT_LEFT_COMMAND = new DefaultLeftCommand<>();
+ private final NullCommand<K, V, C> DEFAULT_NULL_COMMAND = new DefaultNullCommand<>();
- private Map<K, LeftCommand<K, V, C>> leftCommands;
- private Map<K, NullCommand<K, V, C>> nullCommands;
+ private Map<K, LeftCommand<K, V, C>> leftCommands;
+ private Map<K, NullCommand<K, V, C>> nullCommands;
+ private Map<K, NullCommand<K, V, C>> statementCommands;
/**
* Create a new Pratt parser.
*
* @param terminal
- * The terminal symbol.
+ * The terminal symbol.
*/
public PrattParser() {
leftCommands = new HashMap<>();
nullCommands = new HashMap<>();
+ statementCommands = new HashMap<>();
}
/**
* Parse an expression.
*
* @param precedence
- * The initial precedence for the expression.
+ * The initial precedence for the expression.
*
* @param tokens
- * The tokens for the expression.
+ * The tokens for the expression.
*
* @param state
- * The state of the parser.
+ * The state of the parser.
*
* @return The expression as an AST.
*
* @throws ParserException
- * If something goes wrong during parsing.
+ * If something goes wrong during parsing.
*/
- public ITree<Token<K, V>> parseExpression(int precedence, TokenStream<K, V> tokens, C state)
+ public ITree<Token<K, V>> parseExpression(int precedence, TokenStream<K, V> tokens, C state, boolean isStatement)
throws ParserException {
- if(precedence < 0) {
+ if (precedence < 0) {
throw new IllegalArgumentException("Precedence must be greater than zero");
}
Token<K, V> initToken = tokens.current();
tokens.next();
- ITree<Token<K, V>> ast = nullCommands.getOrDefault(initToken.getKey(), DEFAULT_NULL_COMMAND)
- .nullDenotation(initToken, new ParserContext<>(tokens, this, state));
+ ITree<Token<K, V>> ast;
+
+ if (isStatement && statementCommands.containsKey(initToken.getKey())) {
+ ast = statementCommands.getOrDefault(initToken.getKey(), DEFAULT_NULL_COMMAND).nullDenotation(initToken,
+ new ParserContext<>(tokens, this, state));
+ } else {
+ ast = nullCommands.getOrDefault(initToken.getKey(), DEFAULT_NULL_COMMAND).nullDenotation(initToken,
+ new ParserContext<>(tokens, this, state));
+ }
int rightPrec = Integer.MAX_VALUE;
- while(true) {
+ while (true) {
Token<K, V> tok = tokens.current();
K key = tok.getKey();
@@ -80,7 +89,7 @@ public class PrattParser<K, V, C> {
LeftCommand<K, V, C> command = leftCommands.getOrDefault(key, DEFAULT_LEFT_COMMAND);
int leftBind = command.leftBinding();
- if(NumberUtils.between(precedence, rightPrec, leftBind)) {
+ if (NumberUtils.between(precedence, rightPrec, leftBind)) {
tokens.next();
ast = command.leftDenote(ast, tok, new ParserContext<>(tokens, this, state));
@@ -97,10 +106,10 @@ public class PrattParser<K, V, C> {
* Add a non-initial command to this parser.
*
* @param marker
- * The key that marks the command.
+ * The key that marks the command.
*
* @param comm
- * The command.
+ * The command.
*/
public void addNonInitialCommand(K marker, LeftCommand<K, V, C> comm) {
leftCommands.put(marker, comm);
@@ -110,10 +119,10 @@ public class PrattParser<K, V, C> {
* Add a initial command to this parser.
*
* @param marker
- * The key that marks the command.
+ * The key that marks the command.
*
* @param comm
- * The command.
+ * The command.
*/
public void addInitialCommand(K marker, NullCommand<K, V, C> comm) {
nullCommands.put(marker, comm);