summaryrefslogtreecommitdiff
path: root/RGens/src
diff options
context:
space:
mode:
Diffstat (limited to 'RGens/src')
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/GrammarException.java39
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java19
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java256
3 files changed, 206 insertions, 108 deletions
diff --git a/RGens/src/main/java/bjc/rgens/newparser/GrammarException.java b/RGens/src/main/java/bjc/rgens/newparser/GrammarException.java
new file mode 100644
index 0000000..c9f2723
--- /dev/null
+++ b/RGens/src/main/java/bjc/rgens/newparser/GrammarException.java
@@ -0,0 +1,39 @@
+package bjc.rgens.newparser;
+
+/**
+ * The exception thrown when something goes wrong while parsing a
+ * grammar.
+ *
+ * @author student
+ *
+ */
+public class GrammarException extends RuntimeException {
+ /*
+ * Serialization ID.
+ */
+ private static final long serialVersionUID = -7287427479316953668L;
+
+ /**
+ * Create a new grammar exception with the specified message.
+ *
+ * @param msg
+ * The message for this exception.
+ */
+ public GrammarException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Create a new grammar exception with the specified message and
+ * cause.
+ *
+ * @param msg
+ * The message for this exception.
+ *
+ * @param cause
+ * The cause of this exception.
+ */
+ public GrammarException(String msg, Exception cause) {
+ super(msg, cause);
+ }
+} \ No newline at end of file
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
index 073e0ee..fdf2433 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
@@ -29,4 +29,23 @@ public class RGrammarBuilder {
*/
return null;
}
+
+ public void addCasePart(String csepart) {
+ // TODO Auto-generated method stub
+ }
+
+ public void endRule() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void finishCase() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void startWhereBlock(String string) {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
index cf85cb5..9e55736 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
@@ -1,6 +1,8 @@
package bjc.rgens.newparser;
import bjc.utils.funcutils.TriConsumer;
+import bjc.utils.parserutils.BlockReader;
+import bjc.utils.parserutils.BlockReader.Block;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -17,43 +19,16 @@ import java.util.Scanner;
*
*/
public class RGrammarParser {
- /**
- * The exception thrown when something goes wrong while parsing a
- * grammar.
- *
- * @author student
- *
+ /*
+ * Templates for level-dependent delimiters.
*/
- public static class GrammarException extends Exception {
- /*
- * Serialization ID.
- */
- private static final long serialVersionUID = -7287427479316953668L;
-
- /**
- * Create a new grammar exception with the specified message.
- *
- * @param msg
- * The message for this exception.
- */
- public GrammarException(String msg) {
- super(msg);
- }
+ private static final String TMPL_PRAGMA_BLOCK_DELIM = "\\n\\t{%d}(?!\\t)";
+ private static final String TMPL_RULEDECL_BLOCK_DELIM = "\\n\\t\\t{%d}";
- /**
- * Create a new grammar exception with the specified message and
- * cause.
- *
- * @param msg
- * The message for this exception.
- *
- * @param cause
- * The cause of this exception.
- */
- public GrammarException(String msg, Exception cause) {
- super(msg, cause);
- }
- }
+ /*
+ * Templates for non-level-dependent delimiters.
+ */
+ private static final String TOPLEVEL_BLOCK_DELIM = "\\n\\.?\\n";
/*
* Pragma impls.
@@ -79,25 +54,25 @@ public class RGrammarParser {
* Thrown if the grammar has a syntax error.
*/
public RGrammar readGrammar(InputStream is) throws GrammarException {
- LineNumberReader lnReader = new LineNumberReader(new InputStreamReader(is));
-
- int blockNo = 0;
- try(Scanner scn = new Scanner(lnReader)) {
- scn.useDelimiter("\\n\\.?\\n");
+ try(BlockReader reader = new BlockReader(TOPLEVEL_BLOCK_DELIM, new InputStreamReader(is))) {
+ if(!reader.hasNextBlock()) {
+ throw new GrammarException("At least one top-level block must be present");
+ }
- RGrammarBuilder build = new RGrammarBuilder();
+ try {
+ RGrammarBuilder build = new RGrammarBuilder();
- while(scn.hasNext()) {
- String block = scn.next();
- blockNo += 1;
+ reader.forEachBlock((block) -> {
+ handleBlock(build, block.contents, 0);
+ });
- handleBlock(build, block, 0);
+ return build.toRGrammar();
+ } catch(GrammarException gex) {
+ throw new GrammarException(String.format("Error in block (%s)", reader.getBlock()),
+ gex);
}
-
- return build.toRGrammar();
- } catch(GrammarException gex) {
- throw new GrammarException(String.format("Error in block %d at line %d of stream", blockNo,
- lnReader.getLineNumber()), gex);
+ } catch(Exception ex) {
+ throw new GrammarException(String.format("Unknown error handling block"), ex);
}
}
@@ -110,14 +85,23 @@ public class RGrammarParser {
* Handles an arbitrary block.
*/
private void handleBlock(RGrammarBuilder build, String block, int level) throws GrammarException {
- if(block.startsWith("pragma")) {
+ int typeSep = block.indexOf(' ');
+
+ if(typeSep == -1) {
+ throw new GrammarException(
+ "A block must start with a type, followed by a space, then the rest of the block");
+ }
+
+ String blockType = block.substring(0, typeSep);
+
+ if(blockType.equalsIgnoreCase("pragma")) {
handlePragmaBlock(block, build, level);
- } else if(block.startsWith("[")) {
+ } else if(blockType.startsWith("[")) {
handleRuleBlock(block, build, level);
- } else if(block.startsWith("where")) {
+ } else if(blockType.equalsIgnoreCase("where")) {
handleWhereBlock(block, build, level);
} else {
- throw new GrammarException(String.format("Unknown block: %s", block));
+ throw new GrammarException(String.format("Unknown block type: '%s'", blockType));
}
}
@@ -125,88 +109,144 @@ public class RGrammarParser {
* Handle reading a block of pragmas.
*/
private void handlePragmaBlock(String block, RGrammarBuilder build, int level) throws GrammarException {
- LineNumberReader lnReader = new LineNumberReader(new StringReader(block));
-
- int pragmaNo = 0;
- try(Scanner deblocker = new Scanner(lnReader)) {
- deblocker.useDelimiter(String.format("\\n\\t{%d}(?!\\t)", level));
-
- while(deblocker.hasNext()) {
- String pragma = deblocker.next();
- pragmaNo += 1;
-
- if(!pragma.startsWith("pragma")) {
- throw new GrammarException(String.format("Illegal line: %s", pragma));
- } else {
- handlePragma(pragma.substring(7), build, level);
- }
+ try(BlockReader pragmaReader = new BlockReader(String.format(TMPL_PRAGMA_BLOCK_DELIM, level),
+ new StringReader(block))) {
+ try {
+ pragmaReader.forEachBlock((pragma) -> {
+ String pragmaContents = pragma.contents;
+
+ int pragmaSep = pragmaContents.indexOf(' ');
+
+ if(pragmaSep == -1) {
+ throw new GrammarException(
+ "A pragma invocation must consist of the word pragma,"
+ + " followed by a space, then the body of the pragma");
+ }
+
+ String pragmaLeader = pragmaContents.substring(0, pragmaSep);
+ String pragmaBody = pragmaContents.substring(pragmaSep);
+
+ if(!pragmaLeader.equalsIgnoreCase("pragma")) {
+ throw new GrammarException(
+ String.format("Illegal line leader in pragma block: '%s'",
+ pragmaLeader));
+ } else {
+ handlePragma(pragmaBody, build, level);
+ }
+ });
+ } catch(GrammarException gex) {
+ Block pragma = pragmaReader.getBlock();
+
+ throw new GrammarException(String.format("Error in pragma: (%s)", pragma), gex);
}
- } catch(GrammarException gex) {
- throw new GrammarException(String.format("Error in pragma %d at line %d", pragmaNo,
- lnReader.getLineNumber()), gex);
+ } catch(Exception ex) {
+ throw new GrammarException("Unknown error handling pragma block", ex);
}
}
+ /*
+ * Handle an individual pragma in a block.
+ */
private void handlePragma(String pragma, RGrammarBuilder build, int level) throws GrammarException {
- String pragmaName = pragma.substring(0, pragma.indexOf(' '));
+ int bodySep = pragma.indexOf(' ');
+
+ if(bodySep == -1) bodySep = pragma.length();
+
+ String pragmaName = pragma.substring(0, bodySep);
+ String pragmaBody = pragma.substring(bodySep);
if(pragmas.containsKey(pragmaName)) {
- pragmas.get(pragmaName).accept(pragma.substring(pragma.indexOf(' ')), build, level);
+ pragmas.get(pragmaName).accept(pragmaBody, build, level);
} else {
- throw new GrammarException(String.format("Unknown pragma %s", pragmaName));
+ throw new GrammarException(String.format("Unknown pragma named '%s'", pragmaName));
}
}
/*
- * Handle a block of a rule and multiple cases.
+ * Handle a block of a rule declaration and one or more cases.
*/
- private void handleRuleBlock(String block, RGrammarBuilder build, int level) throws GrammarException {
- LineNumberReader lnReader = new LineNumberReader(new StringReader(block));
-
- int caseNo = 0;
- try(Scanner scn = new Scanner(lnReader)) {
- scn.useDelimiter(String.format("\\n\\t\\t{%d}", level));
-
- String decl = scn.next();
-
- String ruleName = decl.substring(0, decl.indexOf(' '));
-
- if(ruleName.equals("")) {
- throw new GrammarException("The empty string is not a valid rule name");
+ private void handleRuleBlock(String ruleBlock, RGrammarBuilder build, int level) throws GrammarException {
+ try(BlockReader ruleReader = new BlockReader(String.format(TMPL_RULEDECL_BLOCK_DELIM, level),
+ new StringReader(ruleBlock))) {
+ try {
+ if(ruleReader.hasNextBlock()) {
+ /*
+ * Rule with a declaration followed by
+ * multiple cases.
+ */
+ ruleReader.nextBlock();
+ Block declBlock = ruleReader.getBlock();
+
+ String declContents = declBlock.contents;
+ handleRuleDecl(build, declContents);
+
+ ruleReader.forEachBlock((block) -> {
+ handleRuleCase(block.contents, build);
+ });
+ } else {
+ /*
+ * Rule with a declaration followed by a
+ * single case.
+ */
+ handleRuleDecl(build, ruleBlock);
+ }
+ } catch(GrammarException gex) {
+ throw new GrammarException(
+ String.format("Error in rule case (%s)", ruleReader.getBlock()), gex);
}
+ } catch(Exception ex) {
+ throw new GrammarException("Unknown error handling rule block", ex);
+ }
+ }
- build.setCurrentRule(ruleName);
-
- String initCase = decl.substring(decl.indexOf(' '));
- caseNo += 1;
+ /*
+ * Handle a rule declaration and its initial case.
+ */
+ private void handleRuleDecl(RGrammarBuilder build, String declContents) {
+ int declSep = declContents.indexOf("\u2192");
- handleRuleCase(initCase, build);
+ if(declSep == -1) {
+ throw new GrammarException("A rule must be given at least one case in its declaration, and"
+ + "seperated from that case by \u2192");
+ }
- while(scn.hasNext()) {
- String cse = scn.next();
- caseNo += 1;
+ String ruleName = declContents.substring(0, declSep).trim();
+ String ruleBody = declContents.substring(declSep).trim();
- handleRuleCase(cse, build);
- }
- } catch(GrammarException gex) {
- throw new GrammarException(
- String.format("Error in case %d at line %d", caseNo, lnReader.getLineNumber()),
- gex);
+ if(ruleName.equals("")) {
+ throw new GrammarException("The empty string is not a valid rule name");
}
+
+ build.setCurrentRule(ruleName);
+
+ handleRuleCase(ruleBody, build);
}
/*
* Handle a single case of a rule.
*/
- private void handleRuleCase(String initCase, RGrammarBuilder build) {
- // TODO Auto-generated method stub
+ private void handleRuleCase(String cse, RGrammarBuilder build) {
+ for(String csepart : cse.split(" ")) {
+ build.addCasePart(csepart);
+ }
+ build.finishCase();
}
/*
- * Handle a block of a rule with local rules.
+ * Handle a where block (a block with local rules).
*/
- private void handleWhereBlock(String block, RGrammarBuilder build, int level) {
- // TODO Auto-generated method stub
+ private void handleWhereBlock(String block, RGrammarBuilder build, int level) throws GrammarException {
+ try(BlockReader whereReader = new BlockReader("", new StringReader(block))) {
+ try {
+
+ } catch(GrammarException gex) {
+ throw new GrammarException(
+ String.format("Error in where block (%s)", whereReader.getBlock()),
+ gex);
+ }
+ } catch(Exception ex) {
+ throw new GrammarException("Unknown error in where block", ex);
+ }
}
}