From a00c9708a8aaae4074d218201b74057fc4c41d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rg=20Prante?= Date: Tue, 25 Oct 2016 22:27:05 +0200 Subject: [PATCH] fixes for sonarqube --- build.gradle | 9 +- gradle/publish.gradle | 24 +- gradle/sonarqube.gradle | 2 +- .../jacc/{Output.java => AbstractOutput.java} | 31 +- src/main/java/org/xbib/jacc/Conflicts.java | 21 +- src/main/java/org/xbib/jacc/Fixity.java | 1 + src/main/java/org/xbib/jacc/Jacc.java | 330 +++++---- .../java/org/xbib/jacc/JaccException.java | 11 + src/main/java/org/xbib/jacc/JaccJob.java | 115 ++-- src/main/java/org/xbib/jacc/JaccLexer.java | 212 +++--- src/main/java/org/xbib/jacc/JaccParser.java | 222 +++--- src/main/java/org/xbib/jacc/JaccProd.java | 7 +- src/main/java/org/xbib/jacc/JaccResolver.java | 7 +- .../jacc/{Settings.java => JaccSettings.java} | 39 +- src/main/java/org/xbib/jacc/JaccSymbol.java | 4 +- src/main/java/org/xbib/jacc/JaccSymbols.java | 11 +- src/main/java/org/xbib/jacc/JaccTables.java | 13 +- src/main/java/org/xbib/jacc/MachineType.java | 7 + src/main/java/org/xbib/jacc/ParserOutput.java | 66 +- src/main/java/org/xbib/jacc/TextOutput.java | 15 +- src/main/java/org/xbib/jacc/TokensOutput.java | 6 +- .../xbib/jacc/compiler/ConsoleHandler.java | 19 +- .../org/xbib/jacc/compiler/Diagnostic.java | 9 +- .../org/xbib/jacc/compiler/JavaSource.java | 44 +- .../java/org/xbib/jacc/compiler/Position.java | 6 +- .../java/org/xbib/jacc/compiler/Source.java | 7 +- .../org/xbib/jacc/compiler/SourceLexer.java | 8 +- .../xbib/jacc/compiler/SourcePosition.java | 5 +- .../java/org/xbib/jacc/grammar/Analysis.java | 21 +- .../java/org/xbib/jacc/grammar/Finitary.java | 41 +- .../java/org/xbib/jacc/grammar/First.java | 22 +- .../java/org/xbib/jacc/grammar/Follow.java | 28 +- .../java/org/xbib/jacc/grammar/Grammar.java | 25 +- .../org/xbib/jacc/grammar/LALRMachine.java | 24 +- src/main/java/org/xbib/jacc/grammar/Left.java | 5 + .../java/org/xbib/jacc/grammar/Machine.java | 4 +- .../java/org/xbib/jacc/grammar/Nullable.java | 42 +- .../java/org/xbib/jacc/grammar/Parser.java | 29 +- .../org/xbib/jacc/grammar/SLRMachine.java | 2 + src/main/java/org/xbib/jacc/util/BitSet.java | 43 +- .../org/xbib/jacc/util/BitSetInterator.java | 44 ++ .../org/xbib/jacc/util/ElemInterator.java | 4 +- src/main/java/org/xbib/jacc/util/IntSet.java | 4 +- .../java/org/xbib/jacc/util/Interator.java | 6 +- src/main/java/org/xbib/jacc/util/SCC.java | 15 +- .../java/org/xbib/jacc/util/SeqInterator.java | 4 +- src/site/resources/Calc.errs | 36 + src/site/resources/MoreCalc.errs | 7 + src/test/java/org/xbib/jacc/JaccTest.java | 73 ++ .../org/xbib/jacc/helper/StreamMatcher.java | 76 +++ .../org/xbib/jacc/helper/package-info.java | 4 + src/test/java/org/xbib/jacc/package-info.java | 4 + src/test/resources/org/xbib/jacc/Calc.errs | 36 + src/test/resources/org/xbib/jacc/Calc.jacc | 165 +++++ src/test/resources/org/xbib/jacc/Calc.java | 536 +++++++++++++++ .../resources/org/xbib/jacc/CalcParser.java | 644 ++++++++++++++++++ .../resources/org/xbib/jacc/CalcParser.output | 203 ++++++ .../resources/org/xbib/jacc/CalcTokens.java | 13 + src/test/resources/org/xbib/jacc/example1 | 4 + src/test/resources/org/xbib/jacc/example1.out | 38 ++ .../resources/org/xbib/jacc/simpleCalc.jacc | 104 +++ 61 files changed, 2838 insertions(+), 719 deletions(-) rename src/main/java/org/xbib/jacc/{Output.java => AbstractOutput.java} (66%) create mode 100644 src/main/java/org/xbib/jacc/JaccException.java rename src/main/java/org/xbib/jacc/{Settings.java => JaccSettings.java} (82%) create mode 100644 src/main/java/org/xbib/jacc/MachineType.java create mode 100644 src/main/java/org/xbib/jacc/util/BitSetInterator.java create mode 100644 src/site/resources/Calc.errs create mode 100644 src/site/resources/MoreCalc.errs create mode 100644 src/test/java/org/xbib/jacc/JaccTest.java create mode 100644 src/test/java/org/xbib/jacc/helper/StreamMatcher.java create mode 100644 src/test/java/org/xbib/jacc/helper/package-info.java create mode 100644 src/test/java/org/xbib/jacc/package-info.java create mode 100644 src/test/resources/org/xbib/jacc/Calc.errs create mode 100644 src/test/resources/org/xbib/jacc/Calc.jacc create mode 100644 src/test/resources/org/xbib/jacc/Calc.java create mode 100644 src/test/resources/org/xbib/jacc/CalcParser.java create mode 100644 src/test/resources/org/xbib/jacc/CalcParser.output create mode 100644 src/test/resources/org/xbib/jacc/CalcTokens.java create mode 100644 src/test/resources/org/xbib/jacc/example1 create mode 100644 src/test/resources/org/xbib/jacc/example1.out create mode 100644 src/test/resources/org/xbib/jacc/simpleCalc.jacc diff --git a/build.gradle b/build.gradle index b511086..3f6ef05 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id "org.sonarqube" version '2.1-rc1' + id "org.sonarqube" version '2.2' } ext { @@ -41,5 +41,12 @@ dependencies { wagon 'org.apache.maven.wagon:wagon-ssh-external:2.10' } +test { + testLogging { + showStandardStreams = false + exceptionFormat = 'full' + } +} + apply from: 'gradle/publish.gradle' apply from: 'gradle/sonarqube.gradle' diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 951f131..4ec7113 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -52,8 +52,8 @@ task sonaTypeUpload(type: Upload) { } licenses { license { - name 'The Apache License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + name 'BSD 3-Clause License' + url 'https://opensource.org/licenses/BSD-3-Clause' } } } @@ -77,6 +77,15 @@ task hbzUpload(type: Upload) { authentication(userName: hbzUserName, privateKey: hbzPrivateKey) } pom.project { + name name + description description + packaging 'jar' + inceptionYear '2012' + url scmUrl + organization { + name 'xbib' + url 'http://xbib.org' + } developers { developer { id 'jprante' @@ -86,15 +95,14 @@ task hbzUpload(type: Upload) { } } scm { - url 'https://github.com/xbib/groovy-webapp' - connection 'scm:git:git://github.com/xbib/groovy-webapp.git' - developerConnection 'scm:git:git://github.com/xbib/groovy-webapp.git' + url scmUrl + connection scmConnection + developerConnection scmDeveloperConnection } - inceptionYear '2016' licenses { license { - name 'The Apache License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + name 'BSD 3-Clause License' + url 'https://opensource.org/licenses/BSD-3-Clause' } } } diff --git a/gradle/sonarqube.gradle b/gradle/sonarqube.gradle index 6230b16..d864fe9 100644 --- a/gradle/sonarqube.gradle +++ b/gradle/sonarqube.gradle @@ -30,7 +30,7 @@ jacocoTestReport { sonarqube { properties { - property "sonar.projectName", "jacc" + property "sonar.projectName", "${project.group} ${project.name}" property "sonar.sourceEncoding", "UTF-8" property "sonar.language", "java" property "sonar.sources", "src/main/java" diff --git a/src/main/java/org/xbib/jacc/Output.java b/src/main/java/org/xbib/jacc/AbstractOutput.java similarity index 66% rename from src/main/java/org/xbib/jacc/Output.java rename to src/main/java/org/xbib/jacc/AbstractOutput.java index 37fe7c9..0c6d7a3 100644 --- a/src/main/java/org/xbib/jacc/Output.java +++ b/src/main/java/org/xbib/jacc/AbstractOutput.java @@ -1,6 +1,5 @@ package org.xbib.jacc; -import org.xbib.jacc.compiler.Failure; import org.xbib.jacc.compiler.Handler; import org.xbib.jacc.compiler.Phase; import org.xbib.jacc.grammar.Grammar; @@ -12,12 +11,11 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; /** * */ -abstract class Output extends Phase { +abstract class AbstractOutput extends Phase { protected Grammar grammar; protected int numTs; @@ -27,9 +25,9 @@ abstract class Output extends Phase { int numStates; JaccTables tables; JaccResolver resolver; - Settings settings; + JaccSettings jaccSettings; - Output(Handler handler, JaccJob jaccjob) { + AbstractOutput(Handler handler, JaccJob jaccjob) { super(handler); tables = jaccjob.getTables(); machine = tables.getMachine(); @@ -39,7 +37,7 @@ abstract class Output extends Phase { numSyms = grammar.getNumSyms(); numStates = machine.getNumStates(); resolver = jaccjob.getResolver(); - settings = jaccjob.getSettings(); + jaccSettings = jaccjob.getJaccSettings(); } static void indent(Writer writer, int i, String[] as) throws IOException { @@ -60,24 +58,17 @@ abstract class Output extends Phase { } static void datestamp(Writer writer) throws IOException { - writer.write("// Output created by jacc 2.1.0 on " + LocalDateTime.now() + "\n"); + writer.write("// Output created by jacc 2.1.0\n"); } public void write(String s) throws IOException { - Writer writer = null; - try { - File file = new File(s); - File parent = file.getParentFile(); - if (!parent.exists()) { - boolean mkdirs = parent.mkdirs(); - } - writer = new OutputStreamWriter(new FileOutputStream(s), StandardCharsets.UTF_8); - write(writer); - } catch (IOException ioexception) { - report(new Failure("Cannot write to file \"" + s + "\"")); + File file = new File(s); + File parent = file.getParentFile(); + if (parent != null && !parent.exists() && !parent.mkdirs()) { + return; } - if (writer != null) { - writer.close(); + try (Writer writer = new OutputStreamWriter(new FileOutputStream(s), StandardCharsets.UTF_8)) { + write(writer); } } diff --git a/src/main/java/org/xbib/jacc/Conflicts.java b/src/main/java/org/xbib/jacc/Conflicts.java index 8460674..c5cb116 100644 --- a/src/main/java/org/xbib/jacc/Conflicts.java +++ b/src/main/java/org/xbib/jacc/Conflicts.java @@ -8,18 +8,18 @@ import org.xbib.jacc.grammar.Machine; */ class Conflicts { - private int type; - private int arg1; - private int arg2; - private Grammar.Symbol sym; + private final int type; + private final int arg1; + private final int arg2; + private final Grammar.Symbol sym; private Conflicts next; private Conflicts(int i, int j, int k, Grammar.Symbol symbol, Conflicts conflicts) { - type = i; - arg1 = j; - arg2 = k; - sym = symbol; - next = conflicts; + this.type = i; + this.arg1 = j; + this.arg2 = k; + this.sym = symbol; + this.next = conflicts; } static Conflicts sr(int i, int j, Grammar.Symbol symbol, Conflicts conflicts) { @@ -43,7 +43,8 @@ class Conflicts { return conflicts; } - static String describe(Machine machine, int i, Conflicts conflicts) { + static String describe(Machine machine, int i, Conflicts c) { + Conflicts conflicts = c; if (conflicts == null) { return ""; } diff --git a/src/main/java/org/xbib/jacc/Fixity.java b/src/main/java/org/xbib/jacc/Fixity.java index fc0f81b..cd7deca 100644 --- a/src/main/java/org/xbib/jacc/Fixity.java +++ b/src/main/java/org/xbib/jacc/Fixity.java @@ -52,6 +52,7 @@ class Fixity { return obj instanceof Fixity && equalsFixity((Fixity) obj); } + @Override public int hashCode() { return assoc ^ prec; } diff --git a/src/main/java/org/xbib/jacc/Jacc.java b/src/main/java/org/xbib/jacc/Jacc.java index 2fd56f5..2120d30 100644 --- a/src/main/java/org/xbib/jacc/Jacc.java +++ b/src/main/java/org/xbib/jacc/Jacc.java @@ -4,198 +4,248 @@ import org.xbib.jacc.compiler.ConsoleHandler; import java.io.BufferedWriter; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.logging.Level; +import java.util.logging.Logger; /** * */ public class Jacc { + private static final Logger logger = Logger.getLogger(Jacc.class.getName()); + + private String className; + private InputStream inputStream; + private InputStream errorDiagnostics; + private InputStream parserInputs; + private OutputStream outputStream; + private String suffix; + private JaccSettings jaccSettings; + private boolean enableParserOutput; + private boolean enableTokenOutput; + private boolean enableVerboseMachineDescription; + private boolean includeCalculations; + private boolean includeStateNumbers; + private String dir; + public Jacc() { + this.className = null; + this.inputStream = null; + this.suffix = ".jacc"; + this.jaccSettings = new JaccSettings(); + this.enableParserOutput = true; + this.enableTokenOutput = true; + this.enableVerboseMachineDescription = false; + this.includeCalculations = false; + this.errorDiagnostics = null; + this.parserInputs = null; + this.includeStateNumbers = false; + this.dir = null; + this.outputStream = System.out; + } + + public void setIncludeCalculations(boolean includeCalculations) { + this.includeCalculations = includeCalculations; + } + + public void setEnableParserOutput(boolean enableParserOutput) { + this.enableParserOutput = enableParserOutput; + } + + public void setEnableTokenOutput(boolean enableTokenOutput) { + this.enableTokenOutput = enableTokenOutput; + } + + public void setEnableVerboseMachineDescription(boolean enableVerboseMachineDescription) { + this.enableVerboseMachineDescription = enableVerboseMachineDescription; + } + + public void setMachineType(MachineType machineType) { + jaccSettings.setMachineType(machineType); + } + + public void setIncludeStateNumbers(boolean includeStateNumbers) { + this.includeStateNumbers = includeStateNumbers; + } + + public void setName(String name) { + this.className = name; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setErrorDiagnostics(InputStream errorDiagnostics) { + this.errorDiagnostics = errorDiagnostics; + } + + public InputStream getErrorDiagnostics() { + return errorDiagnostics; + } + + public void setParserInputs(InputStream parserInputs) { + this.parserInputs = parserInputs; + } + + public InputStream getParserInputs() { + return parserInputs; + } + + public String getSuffix() { + return suffix; + } + + public void setDir(String dir) { + this.dir = dir; + } + + public void setOutputStream(OutputStream outputStream) { + this.outputStream = outputStream; } public static void main(String[] args) throws Exception { - NameList namelist = null; - String s = ".jacc"; - Settings settings = new Settings(); - boolean flag = true; - boolean flag1 = true; - boolean flag2 = false; - boolean flag4 = false; - NameList namelist1 = null; - NameList namelist2 = null; - boolean flag5 = false; - String dir = null; - Writer writer = new BufferedWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); - label0: + Jacc jacc = new Jacc(); for (int i = 0; i < args.length; i++) { - String s1 = args[i]; - if (s1.startsWith("-")) { - if (s1.length() == 1) { + String arg = args[i]; + if (arg.startsWith("-")) { + if (arg.length() == 1) { usage("Missing command line options"); } int j = 1; - do { - if (j >= s1.length()) { - continue label0; - } - switch (s1.charAt(j)) { - case 102: // 'f' - flag4 = true; + while (j < arg.length()) { + switch (arg.charAt(j)) { + case 'f': + jacc.setIncludeCalculations(true); break; - - case 112: // 'p' - flag = false; + case 'p': + jacc.setEnableParserOutput(false); break; - - case 116: // 't' - flag1 = false; + case 't': + jacc.setEnableTokenOutput(false); break; - - case 118: // 'v' - flag2 = true; + case 'v': + jacc.setEnableVerboseMachineDescription(true); break; - - case 48: // '0' - settings.setMachineType(0); + case '0': + jacc.setMachineType(MachineType.LR0); break; - - case 115: // 's' - settings.setMachineType(1); + case 's': + jacc.setMachineType(MachineType.SLR1); break; - - case 97: // 'a' - settings.setMachineType(2); + case 'a': + jacc.setMachineType(MachineType.LALR1); break; - - case 101: // 'e' + case 'n': + jacc.setIncludeStateNumbers(true); + break; + case 'e': if (i + 1 >= args.length) { usage("Missing filename for -e option"); } - namelist1 = new NameList(args[++i], namelist1); + jacc.setErrorDiagnostics(Files.newInputStream(Paths.get(args[++i]))); break; - - case 114: // 'r' + case 'r': if (i + 1 >= args.length) { usage("Missing filename for -r option"); } - namelist2 = new NameList(args[++i], namelist2); + jacc.setParserInputs(Files.newInputStream(Paths.get(args[++i]))); break; - - case 110: // 'n' - flag5 = true; - break; - case 'd': if (i + 1 >= args.length) { usage("Missing directory for -d option"); } - dir = args[++i]; + jacc.setDir(args[++i]); + break; + case 'o': + if (i + 1 >= args.length) { + usage("Missing filename for -o option"); + } + jacc.setOutputStream(Files.newOutputStream(Paths.get(args[++i]))); break; - default: - usage("Unrecognized command line option " + s1.charAt(j)); + usage("Unrecognized command line option " + arg.charAt(j)); break; } j++; - } while (true); + } } - if (!s1.endsWith(s)) { - usage("Input file must have \"" + s + "\" suffix"); + if (!arg.endsWith(jacc.getSuffix())) { + usage("Input file must have \"" + jacc.getSuffix() + "\" suffix"); } else { - namelist = new NameList(s1, namelist); + jacc.setInputStream(Files.newInputStream(Paths.get(arg))); } } - - if (namelist == null) { + if (jacc.getInputStream() == null) { usage("No input file(s) specified"); + } else { + jacc.execute(); } - ConsoleHandler simplehandler = new ConsoleHandler(); - String s2 = namelist.getFirst(); - int k = 1 + Math.max(s2.lastIndexOf('\\'), s2.lastIndexOf('/')); - dir = dir == null ? s2.substring(0, k) : dir; - String s4 = s2.substring(k, s2.length() - s.length()); - final JaccJob job = new JaccJob(simplehandler, writer, settings); - NameList.visit(namelist, new NameList.Visitor() { - public void visit(String s5) throws IOException { - job.parseGrammarFile(s5); - } - }); + } + + public void execute() throws IOException { + Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)); + ConsoleHandler consoleHandler = new ConsoleHandler(); + if (dir == null) { + dir = "."; + } + if (!dir.endsWith("/")) { + dir = dir + "/"; + } + final JaccJob job = new JaccJob(consoleHandler, writer, jaccSettings); + job.parseGrammarStream(inputStream); job.buildTables(); - settings.fillBlanks(s4); - NameList.visit(namelist1, new NameList.Visitor() { - public void visit(String s5) throws IOException { - job.readErrorExamples(s5); + jaccSettings.fillBlanks(className); + if (errorDiagnostics != null) { + job.readErrorExamples(errorDiagnostics); + } + if (consoleHandler.getNumFailures() == 0) { + if (enableParserOutput) { + (new ParserOutput(consoleHandler, job)).write(dir + jaccSettings.getClassName() + ".java"); } - }); - if (simplehandler.getNumFailures() > 0) { - return; - } - if (flag) { - (new ParserOutput(simplehandler, job)).write(dir + settings.getClassName() + ".java"); - } - if (flag1) { - (new TokensOutput(simplehandler, job)).write(dir + settings.getInterfaceName() + ".java"); - } - if (flag2) { - (new TextOutput(simplehandler, job, flag4)).write(dir + s4 + ".output"); - } - final boolean showState = flag5; - NameList.visit(namelist2, new NameList.Visitor() { - public void visit(String s5) throws IOException { - job.readRunExample(s5, showState); + if (enableTokenOutput) { + (new TokensOutput(consoleHandler, job)).write(dir + jaccSettings.getInterfaceName() + ".java"); } - }); + if (enableVerboseMachineDescription) { + (new TextOutput(consoleHandler, job, includeCalculations)).write(dir + jaccSettings.getClassName() + ".output"); + } + if (parserInputs != null) { + job.readRunExample(parserInputs, includeStateNumbers); + } + } else { + writer.write("There were failures.\n"); + } + writer.close(); } private static void usage(String s) { - System.err.println(s); - System.err.println("usage: jacc [options] file.jacc ..."); - System.err.println("options (individually, or in combination):"); - System.err.println(" -p do not generate parser"); - System.err.println(" -t do not generate token specification"); - System.err.println(" -v output text description of machine"); - System.err.println(" -f show first/follow sets (with -h or -v)"); - System.err.println(" -a treat as LALR(1) grammar (default)"); - System.err.println(" -s treat as SLR(1) grammar"); - System.err.println(" -0 treat as LR(0) grammar"); - System.err.println(" -r file run parser on input in file"); - System.err.println(" -n show state numbers in parser output"); - System.err.println(" -e file read error cases from file"); - System.err.println(" -d dir output files to directory"); - System.exit(1); - } - - private static class NameList { - - String name; - NameList names; - - NameList(String s, NameList namelist) { - name = s; - names = namelist; - } - - static void visit(NameList namelist, Visitor visitor) throws IOException { - if (namelist != null) { - visit(namelist.names, visitor); - visitor.visit(namelist.name); - } - } - - String getFirst() { - NameList namelist; - namelist = this; - while (namelist.names != null) { - namelist = namelist.names; - } - return namelist.name; - } - - interface Visitor { - void visit(String s) throws IOException; - } + logger.log(Level.INFO, s); + String mesg = "usage: jacc [options] file.jacc ...\n" + + "options (individually, or in combination):\n" + + " -p do not generate parser\n" + + " -t do not generate token specification\n" + + " -v output text description of machine\n" + + " -f show first/follow sets (with -h or -v)\n" + + " -a treat as LALR(1) grammar (default)\n" + + " -s treat as SLR(1) grammar\n" + + " -0 treat as LR(0) grammar\n" + + " -r file run parser on input in file\n" + + " -n show state numbers in parser output\n" + + " -e file read error cases from file\n" + + " -d dir output files to directory\n" + + " -o file name of output file for parser runs\n"; + logger.log(Level.INFO, mesg); } } + diff --git a/src/main/java/org/xbib/jacc/JaccException.java b/src/main/java/org/xbib/jacc/JaccException.java new file mode 100644 index 0000000..b131349 --- /dev/null +++ b/src/main/java/org/xbib/jacc/JaccException.java @@ -0,0 +1,11 @@ +package org.xbib.jacc; + +/** + * + */ +public class JaccException extends Exception { + + public JaccException(String message) { + super(message); + } +} diff --git a/src/main/java/org/xbib/jacc/JaccJob.java b/src/main/java/org/xbib/jacc/JaccJob.java index 3656c54..71c9752 100644 --- a/src/main/java/org/xbib/jacc/JaccJob.java +++ b/src/main/java/org/xbib/jacc/JaccJob.java @@ -13,14 +13,18 @@ import org.xbib.jacc.grammar.Parser; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.Writer; import java.nio.charset.StandardCharsets; +/** + * + */ class JaccJob extends Phase { - private Settings settings; + private JaccSettings jaccSettings; private JaccParser parser; @@ -30,15 +34,15 @@ class JaccJob extends Phase { private Writer out; - JaccJob(Handler handler, Writer out, Settings settings) { + JaccJob(Handler handler, Writer out, JaccSettings jaccSettings) { super(handler); this.out = out; - this.settings = settings; - this.parser = new JaccParser(handler, settings); + this.jaccSettings = jaccSettings; + this.parser = new JaccParser(handler, jaccSettings); } - Settings getSettings() { - return settings; + JaccSettings getJaccSettings() { + return jaccSettings; } JaccTables getTables() { @@ -49,23 +53,62 @@ class JaccJob extends Phase { return resolver; } - private JaccLexer lexerFromFile(String s) { - JaccLexer jacclexer; - try { - Reader filereader = new InputStreamReader(new FileInputStream(s), StandardCharsets.UTF_8); - jacclexer = new JaccLexer(getHandler(), new JavaSource(getHandler(), s, filereader)); - jacclexer.nextToken(); - return jacclexer; - } catch (IOException e) { - report(new Failure("Could not open file \"" + s + "\"")); - return null; + void parseGrammarStream(InputStream inputStream) throws IOException { + JaccLexer jacclexer = lexerFromInputStream(inputStream); + if (jacclexer != null) { + parser.parse(jacclexer); + jacclexer.close(); } } - void parseGrammarFile(String s) throws IOException { + private JaccLexer lexerFromFile(String s) throws IOException { + JaccLexer jacclexer; + Reader filereader = new InputStreamReader(new FileInputStream(s), StandardCharsets.UTF_8); + jacclexer = new JaccLexer(getHandler(), new JavaSource(getHandler(), filereader)); + jacclexer.nextToken(); + return jacclexer; + } + + private JaccLexer lexerFromInputStream(InputStream inputStream) throws IOException { + JaccLexer jacclexer; + Reader filereader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); + jacclexer = new JaccLexer(getHandler(), new JavaSource(getHandler(), filereader)); + jacclexer.nextToken(); + return jacclexer; + } + + void readErrorExamples(String s) throws IOException { + out.write("Reading error examples from \"" + s + "\""); JaccLexer jacclexer = lexerFromFile(s); if (jacclexer != null) { - parser.parse(jacclexer); + parser.parseErrorExamples(jacclexer, this); + jacclexer.close(); + } + } + + void readErrorExamples(InputStream inputStream) throws IOException { + JaccLexer jacclexer = lexerFromInputStream(inputStream); + if (jacclexer != null) { + parser.parseErrorExamples(jacclexer, this); + jacclexer.close(); + } + } + + void readRunExample(String s, boolean flag) throws IOException { + out.write("Running example from \"" + s + "\"]\n"); + JaccLexer jacclexer = lexerFromFile(s); + if (jacclexer != null) { + runExample(parser.parseSymbols(jacclexer), flag); + jacclexer.close(); + } + } + + void readRunExample(InputStream inputStream, boolean flag) throws IOException { + out.write("Running example from input stream\n"); + JaccLexer jacclexer = lexerFromInputStream(inputStream); + if (jacclexer != null) { + runExample(parser.parseSymbols(jacclexer), flag); + jacclexer.close(); } } @@ -74,9 +117,9 @@ class JaccJob extends Phase { if (grammar == null || !allDeriveFinite(grammar)) { return; } - LookaheadMachine lookaheadmachine = settings.makeMachine(grammar); - resolver = new JaccResolver(lookaheadmachine); - tables = new JaccTables(lookaheadmachine, resolver); + LookaheadMachine lookaheadmachine = jaccSettings.makeMachine(grammar); + this.resolver = new JaccResolver(lookaheadmachine); + this.tables = new JaccTables(lookaheadmachine, resolver); if (tables.getProdUnused() > 0) { report(new Warning(tables.getProdUnused() + " rules never reduced")); } @@ -93,7 +136,7 @@ class JaccJob extends Phase { Finitary finitary = grammar.getFinitary(); boolean flag = true; for (int i = 0; i < grammar.getNumNTs(); i++) { - if (!finitary.at(i)) { + if (!finitary.isAt(i)) { flag = false; report(new Failure("No finite strings can be derived for " + grammar.getNonterminal(i))); @@ -102,15 +145,7 @@ class JaccJob extends Phase { return flag; } - void readRunExample(String s, boolean flag) throws IOException { - out.write("Running example from \"" + s + "\"]\n"); - JaccLexer jacclexer = lexerFromFile(s); - if (jacclexer != null) { - runExample(parser.parseSymbols(jacclexer), flag); - } - } - - private void runExample(int ai[], boolean flag) throws IOException { + private void runExample(int[] ai, boolean flag) throws IOException { Grammar grammar = parser.getGrammar(); Parser parser1 = new Parser(tables, ai); out.write("start "); @@ -142,30 +177,22 @@ class JaccJob extends Phase { } while (true); } - void readErrorExamples(String s) throws IOException { - out.write("Reading error examples from \"" + s + "\""); - JaccLexer jacclexer = lexerFromFile(s); - if (jacclexer != null) { - parser.parseErrorExamples(jacclexer, this); - } - } - - void errorExample(Position position, String s, int ai[]) { - Parser parser1 = new Parser(tables, ai); + void errorExample(Position position, String s, int[] ai) { + Parser p = new Parser(tables, ai); int i; do { - i = parser1.step(); + i = p.step(); } while (i != 0 && i != 1); if (i == 0) { report(new Warning(position, "Example for \"" + s + "\" does not produce an error")); } else { Grammar grammar = tables.getMachine().getGrammar(); - int j = parser1.getNextSymbol(); + int j = p.getNextSymbol(); if (grammar.isNonterminal(j)) { report(new Warning(position, "Example for \"" + s + "\" reaches an error at the nonterminal " + grammar.getSymbol(j))); } else { - int k = parser1.getState(); + int k = p.getState(); if (!tables.errorAt(k, j)) { report(new Failure(position, "Error example results in internal error")); } else { diff --git a/src/main/java/org/xbib/jacc/JaccLexer.java b/src/main/java/org/xbib/jacc/JaccLexer.java index 70f0553..130ba40 100644 --- a/src/main/java/org/xbib/jacc/JaccLexer.java +++ b/src/main/java/org/xbib/jacc/JaccLexer.java @@ -21,74 +21,69 @@ class JaccLexer extends SourceLexer implements JaccTokens { @Override public int nextToken() throws IOException { - do { + while (true) { skipWhitespace(); markPosition(); lexemeText = null; switch (c) { case -1: - return token = ENDINPUT; - - case 58: // ':' + token = ENDINPUT; + return token; + case ':': nextChar(); - return token = COLON; - - case 59: // ';' + token = COLON; + return token; + case ';': nextChar(); - return token = SEMI; - - case 124: // '|' + token = SEMI; + return token; + case '|': nextChar(); - return token = BAR; - - case 60: // '<' + token = BAR; + return token; + case '<': nextChar(); - return token = TOPEN; - - case 62: // '>' + token = TOPEN; + return token; + case '>': nextChar(); - return token = TCLOSE; - - case 91: // '[' + token = TCLOSE; + return token; + case '[': nextChar(); - return token = BOPEN; - - case 93: // ']' + token = BOPEN; + return token; + case ']': nextChar(); - return token = BCLOSE; - - case 46: // '.' + token = BCLOSE; + return token; + case '.': nextChar(); - return token = DOT; - - case 37: // '%' + token = DOT; + return token; + case '%': if (directive() != -1) { return token; } break; - - case 34: // '"' + case '"': if (string() != -1) { return token; } break; - - case 39: // '\'' + case '\'': if (literal() != -1) { return token; } break; - - case 123: // '{' + case '{': if (action() != -1) { return token; } break; - - case 47: // '/' + case '/': skipComment(); break; - default: if (Character.isJavaIdentifierStart((char) c)) { return identifier(); @@ -100,7 +95,7 @@ class JaccLexer extends SourceLexer implements JaccTokens { nextChar(); break; } - } while (true); + } } String readWholeLine() throws IOException { @@ -176,64 +171,68 @@ class JaccLexer extends SourceLexer implements JaccTokens { nextChar(); } while (c != -1 && Character.isJavaIdentifierPart((char) c)); lexemeText = line.substring(i, col); - return token = IDENT; + token = IDENT; + return token; } private int directive() throws IOException { nextChar(); if (c == 37) { nextChar(); - return token = MARK; + token = MARK; + return token; } if (Character.isJavaIdentifierStart((char) c)) { identifier(); - if (lexemeText.equals("token")) { - return token = TOKEN; - } - if (lexemeText.equals("type")) { - return token = TYPE; - } - if (lexemeText.equals("prec")) { - return token = PREC; - } - if (lexemeText.equals("left")) { - return token = LEFT; - } - if (lexemeText.equals("right")) { - return token = RIGHT; - } - if (lexemeText.equals("nonassoc")) { - return token = NONASSOC; - } - if (lexemeText.equals("start")) { - return token = START; - } - if (lexemeText.equals("package")) { - return token = PACKAGE; - } - if (lexemeText.equals("extends")) { - return token = EXTENDS; - } - if (lexemeText.equals("implements")) { - return token = IMPLEMENTS; - } - if (lexemeText.equals("semantic")) { - return token = SEMANTIC; - } - if (lexemeText.equals("get")) { - return token = GETTOKEN; - } - if (lexemeText.equals("next")) { - return token = NEXTTOKEN; - } - if (lexemeText.equals("class")) { - return token = CLASS; - } - if (lexemeText.equals("interface")) { - return token = INTERFACE; - } else { - report(new Failure(getPos(), "Unrecognized directive")); - return ERROR; + switch (lexemeText) { + case "token": + token = TOKEN; + return token; + case "type": + token = TYPE; + return token; + case "prec": + token = PREC; + return token; + case "left": + token = LEFT; + return token; + case "right": + token = RIGHT; + return token; + case "nonassoc": + token = NONASSOC; + return token; + case "start": + token = START; + return token; + case "package": + token = PACKAGE; + return token; + case "extends": + token = EXTENDS; + return token; + case "implements": + token = IMPLEMENTS; + return token; + case "semantic": + token = SEMANTIC; + return token; + case "get": + token = GETTOKEN; + return token; + case "next": + token = NEXTTOKEN; + return token; + case "class": + token = CLASS; + return token; + case "interface": + token = INTERFACE; + return token; + default: + report(new Failure(getPos(), "Unrecognized directive")); + return ERROR; } } if (c == 123) { @@ -256,13 +255,15 @@ class JaccLexer extends SourceLexer implements JaccTokens { if (c == 125) { lexemeText = endBuffer(sb, i, col - 1); nextChar(); - return token = CODE; + token = CODE; + return token; } } if (c == -1) { report(new Failure(getPos(), "Code fragment terminator %} not found")); lexemeText = endBuffer(sb, i, col); - return token = CODE; + token = CODE; + return token; } if (c == 10) { if (sb == null) { @@ -304,7 +305,8 @@ class JaccLexer extends SourceLexer implements JaccTokens { } while (k >= 0); lexemeText = line.substring(i, col); lastLiteral = j; - return token = INTLIT; + token = INTLIT; + return token; } private int string() { @@ -323,7 +325,8 @@ class JaccLexer extends SourceLexer implements JaccTokens { } else { report(new Warning(getPos(), "Missing \" on string literal")); } - return token = STRLIT; + token = STRLIT; + return token; } private int literal() { @@ -346,23 +349,26 @@ class JaccLexer extends SourceLexer implements JaccTokens { report(new Warning(getPos(), "Missing ' on character literal")); } lexemeText = line.substring(i, col); - return token = CHARLIT; + token = CHARLIT; + return token; } private void escapeChar() { nextChar(); switch (c) { - case 34: // '"' - case 39: // '\'' - case 92: // '\\' - case 98: // 'b' - case 102: // 'f' - case 110: // 'n' - case 114: // 'r' - case 116: // 't' + case '"': + case '\'': + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': lastLiteral = c; nextChar(); return; + default: + break; } int i = Character.digit((char) c, 8); if (i >= 0) { @@ -387,7 +393,8 @@ class JaccLexer extends SourceLexer implements JaccTokens { if (--j == 0) { nextChar(); lexemeText = endBuffer(sb, i, col); - return token = ACTION; + token = ACTION; + return token; } } else { if (c == 123) { @@ -397,7 +404,8 @@ class JaccLexer extends SourceLexer implements JaccTokens { if (c == -1) { report(new Failure(getPos(), "Unterminated action")); lexemeText = endBuffer(sb, i, col); - return token = ACTION; + token = ACTION; + return token; } if (c == 10) { if (sb == null) { diff --git a/src/main/java/org/xbib/jacc/JaccParser.java b/src/main/java/org/xbib/jacc/JaccParser.java index 06e05ad..791ba73 100644 --- a/src/main/java/org/xbib/jacc/JaccParser.java +++ b/src/main/java/org/xbib/jacc/JaccParser.java @@ -8,38 +8,43 @@ import org.xbib.jacc.compiler.Warning; import org.xbib.jacc.grammar.Grammar; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * */ class JaccParser extends Phase implements JaccTokens { - private Settings settings; + private static final Logger logger = Logger.getLogger(JaccParser.class.getName()); + + private final JaccSettings jaccSettings; + private final NamedJaccSymbols terminals; + private final NamedJaccSymbols nonterms; + private final NumJaccSymbols literals; private int seqNo; private JaccLexer lexer; private int precedence; - private NamedJaccSymbols terminals; - private NamedJaccSymbols nonterms; - private NumJaccSymbols literals; - private JaccSymbol start; - JaccParser(Handler handler, Settings settings1) { + private JaccSymbol startSymbol; + + JaccParser(Handler handler, JaccSettings jaccSettings) { super(handler); - seqNo = 1; - precedence = 0; - settings = settings1; - terminals = new NamedJaccSymbols(); - nonterms = new NamedJaccSymbols(); - literals = new NumJaccSymbols(); - start = null; + this.jaccSettings = jaccSettings; + this.terminals = new NamedJaccSymbols(); + this.nonterms = new NamedJaccSymbols(); + this.literals = new NumJaccSymbols(); + this.seqNo = 1; + this.precedence = 0; + this.startSymbol = null; } public Grammar getGrammar() { try { - JaccSymbol ajaccsymbol[]; - JaccProd ajaccprod[][]; + JaccSymbol[] ajaccsymbol; + JaccProd[][] ajaccprod; int i = nonterms.getSize(); int j = terminals.getSize() + literals.getSize() + 1; - if (i == 0 || start == null) { + if (i == 0 || startSymbol == null) { report(new Failure("No nonterminals defined")); return null; } @@ -58,11 +63,11 @@ class JaccParser extends Phase implements JaccTokens { ajaccsymbol[i + l].setNum(k++); } int i1 = 0; - do { + while (true) { if (i1 >= i) { break; } - if (ajaccsymbol[i1] == start) { + if (ajaccsymbol[i1] == startSymbol) { if (i1 > 0) { JaccSymbol jaccsymbol = ajaccsymbol[0]; ajaccsymbol[0] = ajaccsymbol[i1]; @@ -71,7 +76,7 @@ class JaccParser extends Phase implements JaccTokens { break; } i1++; - } while (true); + } for (int j1 = 0; j1 < ajaccsymbol.length; j1++) { ajaccsymbol[j1].setTokenNo(j1); } @@ -83,7 +88,8 @@ class JaccParser extends Phase implements JaccTokens { } } return new Grammar(ajaccsymbol, ajaccprod); - } catch (Exception e) { + } catch (JaccException e) { + logger.log(Level.SEVERE, e.getMessage(), e); report(new Failure("Internal problem " + e.getMessage())); return null; } @@ -101,8 +107,8 @@ class JaccParser extends Phase implements JaccTokens { String s; if (jacclexer.getToken() == 1) { while ((s = jacclexer.readWholeLine()) != null) { - settings.addPostText(s); - settings.addPostText("\n"); + jaccSettings.addPostText(s); + jaccSettings.addPostText("\n"); } } } @@ -112,7 +118,7 @@ class JaccParser extends Phase implements JaccTokens { int[] parseSymbols(JaccLexer jacclexer) throws IOException { lexer = jacclexer; SymList symlist = null; - do { + while (true) { JaccSymbol jaccsymbol = parseDefinedSymbol(); if (jaccsymbol == null) { if (jacclexer.getToken() != 0) { @@ -123,12 +129,12 @@ class JaccParser extends Phase implements JaccTokens { } symlist = new SymList(jaccsymbol, symlist); jacclexer.nextToken(); - } while (true); + } } void parseErrorExamples(JaccLexer jacclexer, JaccJob jaccjob) throws IOException { lexer = jacclexer; - do { + while (true) { if (jacclexer.getToken() != 5) { break; } @@ -139,7 +145,7 @@ class JaccParser extends Phase implements JaccTokens { report(new Warning(jacclexer.getPos(), "A colon was expected here")); } int i; - do { + while (true) { Position position = jacclexer.getPos(); SymList symlist = null; JaccSymbol jaccsymbol; @@ -147,14 +153,14 @@ class JaccParser extends Phase implements JaccTokens { symlist = new SymList(jaccsymbol, symlist); jacclexer.nextToken(); } - int ai[] = SymList.toIntArray(symlist); + int[] ai = SymList.toIntArray(symlist); jaccjob.errorExample(position, s, ai); i = jacclexer.getToken(); if (i != 124) { break; } jacclexer.nextToken(); - } while (true); + } if (i != 0) { if (i != 59) { report(new Failure(jacclexer.getPos(), "Unexpected token; a semicolon was expected here")); @@ -166,7 +172,7 @@ class JaccParser extends Phase implements JaccTokens { jacclexer.nextToken(); } } - } while (true); + } if (jacclexer.getToken() != 0) { report(new Failure(jacclexer.getPos(), "Unexpected token; ignoring the rest of this file")); } @@ -175,11 +181,13 @@ class JaccParser extends Phase implements JaccTokens { private void parseDefinitions() throws IOException { boolean flag = false; - do { + while (true) { switch (lexer.getToken()) { case 0: // '\0' case 1: // '\001' return; + default: + break; } if (parseDefinition()) { flag = false; @@ -190,88 +198,73 @@ class JaccParser extends Phase implements JaccTokens { } lexer.nextToken(); } - } while (true); + } } private boolean parseDefinition() throws IOException { switch (lexer.getToken()) { - case 2: // '\002' - settings.addPreText(lexer.getLexeme()); + case CODE: + jaccSettings.addPreText(lexer.getLexeme()); lexer.nextToken(); return true; - - case 8: // '\b' + case TOKEN: parseTokenDefn(); return true; - - case 9: // '\t' + case TYPE: parseTypeDefn(); return true; - - case 11: // '\013' + case LEFT: parseFixityDefn(Fixity.left(precedence++)); return true; - - case 13: // '\r' + case NONASSOC: parseFixityDefn(Fixity.nonass(precedence++)); return true; - - case 12: // '\f' + case RIGHT: parseFixityDefn(Fixity.right(precedence++)); return true; - - case 14: // '\016' + case START: parseStart(); return true; - - case 16: // '\020' - settings.setClassName(parseIdent(lexer.getLexeme(), settings.getClassName())); + case CLASS: + jaccSettings.setClassName(parseIdent(lexer.getLexeme(), jaccSettings.getClassName())); return true; - - case 17: // '\021' - settings.setInterfaceName(parseIdent(lexer.getLexeme(), settings.getInterfaceName())); + case INTERFACE: + jaccSettings.setInterfaceName(parseIdent(lexer.getLexeme(), jaccSettings.getInterfaceName())); return true; - - case 15: // '\017' - settings.setPackageName(parseDefnQualName(lexer.getLexeme(), settings.getPackageName())); + case PACKAGE: + jaccSettings.setPackageName(parseDefnQualName(lexer.getLexeme(), jaccSettings.getPackageName())); return true; - - case 18: // '\022' - settings.setExtendsName(parseDefnQualName(lexer.getLexeme(), settings.getExtendsName())); + case EXTENDS: + jaccSettings.setExtendsName(parseDefnQualName(lexer.getLexeme(), jaccSettings.getExtendsName())); return true; - - case 19: // '\023' + case IMPLEMENTS: lexer.nextToken(); String s = parseQualName(); if (s != null) { - settings.addImplementsNames(s); + jaccSettings.addImplementsNames(s); } return true; - - case 20: // '\024' - settings.setTypeName(parseDefnQualName(lexer.getLexeme(), settings.getTypeName())); + case SEMANTIC: + jaccSettings.setTypeName(parseDefnQualName(lexer.getLexeme(), jaccSettings.getTypeName())); if (lexer.getToken() == 58) { - settings.setGetSemantic(lexer.readCodeLine()); + jaccSettings.setGetSemantic(lexer.readCodeLine()); lexer.nextToken(); } return true; - - case 21: // '\025' - settings.setGetToken(lexer.readCodeLine()); + case GETTOKEN: + jaccSettings.setGetToken(lexer.readCodeLine()); lexer.nextToken(); return true; - - case 22: // '\026' - settings.setNextToken(lexer.readCodeLine()); + case NEXTTOKEN: + jaccSettings.setNextToken(lexer.readCodeLine()); lexer.nextToken(); return true; - - case 3: // '\003' - case 4: // '\004' - case 5: // '\005' - case 6: // '\006' - case 7: // '\007' - case 10: // '\n' + case IDENT: + case CHARLIT: + case STRLIT: + case INTLIT: + case ACTION: + case PREC: default: return false; } @@ -284,8 +277,8 @@ class JaccParser extends Phase implements JaccTokens { if (jaccsymbol == null) { report(new Failure(position, "Missing start symbol")); } else { - if (start == null) { - start = jaccsymbol; + if (startSymbol == null) { + startSymbol = jaccsymbol; } else { report(new Failure(position, "Multiple %start definitions are not permitted")); } @@ -323,7 +316,7 @@ class JaccParser extends Phase implements JaccTokens { Position position = lexer.getPos(); String s = optionalType(); int i = 0; - do { + while (true) { JaccSymbol jaccsymbol = parseTerminal(); if (jaccsymbol == null) { if (i == 0) { @@ -334,14 +327,14 @@ class JaccParser extends Phase implements JaccTokens { addType(jaccsymbol, s); lexer.nextToken(); i++; - } while (true); + } } private void parseTypeDefn() throws IOException { Position position = lexer.getPos(); String s = optionalType(); int i = 0; - do { + while (true) { JaccSymbol jaccsymbol = parseSymbol(); if (jaccsymbol == null) { if (i == 0) { @@ -352,14 +345,14 @@ class JaccParser extends Phase implements JaccTokens { addType(jaccsymbol, s); lexer.nextToken(); i++; - } while (true); + } } private void parseFixityDefn(Fixity fixity) throws IOException { Position position = lexer.getPos(); String s = optionalType(); int i = 0; - do { + while (true) { JaccSymbol jaccsymbol = parseTerminal(); if (jaccsymbol == null) { if (i == 0) { @@ -371,7 +364,7 @@ class JaccParser extends Phase implements JaccTokens { addType(jaccsymbol, s); lexer.nextToken(); i++; - } while (true); + } } private String optionalType() throws IOException { @@ -380,24 +373,24 @@ class JaccParser extends Phase implements JaccTokens { StringBuilder sb = new StringBuilder(); label1: { - if (lexer.nextToken() != 60) { + if (lexer.nextToken() != TOPEN) { break label0; } lexer.nextToken(); sb.append(parseQualName()); - do { - if (lexer.getToken() != 91) { + while (true) { + if (lexer.getToken() != BOPEN) { break label1; } - if (lexer.nextToken() != 93) { + if (lexer.nextToken() != BCLOSE) { break; } lexer.nextToken(); sb.append("[]"); - } while (true); + } report(new Failure(lexer.getPos(), "Missing ']' in array type")); } - if (lexer.getToken() == 62) { + if (lexer.getToken() == TCLOSE) { lexer.nextToken(); } else if (sb.length() > 0) { report(new Failure(lexer.getPos(), "Missing `>' in type specification")); @@ -422,8 +415,8 @@ class JaccParser extends Phase implements JaccTokens { private void parseGrammar() throws IOException { JaccSymbol jaccsymbol; while ((jaccsymbol = parseLhs()) != null) { - if (start == null) { - start = jaccsymbol; + if (startSymbol == null) { + startSymbol = jaccsymbol; } jaccsymbol.addProduction(parseRhs()); for (; lexer.getToken() == 124; jaccsymbol.addProduction(parseRhs())) { @@ -472,7 +465,7 @@ class JaccParser extends Phase implements JaccTokens { private JaccProd parseRhs() throws IOException { Fixity fixity = null; SymList symlist = null; - do { + while (true) { while (lexer.getToken() == 10) { lexer.nextToken(); JaccSymbol jaccsymbol = parseSymbol(); @@ -497,7 +490,7 @@ class JaccParser extends Phase implements JaccTokens { } symlist = new SymList(jaccsymbol1, symlist); lexer.nextToken(); - } while (true); + } String s = null; Position position = null; if (lexer.getToken() == 7) { @@ -505,7 +498,7 @@ class JaccParser extends Phase implements JaccTokens { position = lexer.getPos(); lexer.nextToken(); } - JaccSymbol ajaccsymbol[] = SymList.toArray(symlist); + JaccSymbol[] ajaccsymbol = SymList.toArray(symlist); return new JaccProd(fixity, ajaccsymbol, position, s, seqNo++); } @@ -515,7 +508,7 @@ class JaccParser extends Phase implements JaccTokens { return null; } StringBuilder stringbuffer = new StringBuilder(); - do { + while (true) { stringbuffer.append(lexer.getLexeme()); if (lexer.nextToken() != 46) { break; @@ -525,7 +518,7 @@ class JaccParser extends Phase implements JaccTokens { break; } stringbuffer.append('.'); - } while (true); + } return stringbuffer.toString(); } @@ -541,19 +534,20 @@ class JaccParser extends Phase implements JaccTokens { case 4: // '\004' return literals.findOrAdd(s, lexer.getLastLiteral()); + default: + break; } return null; } private JaccSymbol parseNonterminal() { String s = lexer.getLexeme(); - switch (lexer.getToken()) { - case 3: // '\003' - if (terminals.find(s) != null) { - return null; - } else { - return nonterms.findOrAdd(s); - } + if (lexer.getToken() == 3) { + if (terminals.find(s) != null) { + return null; + } else { + return nonterms.findOrAdd(s); + } } return null; } @@ -568,9 +562,10 @@ class JaccParser extends Phase implements JaccTokens { jaccsymbol = nonterms.findOrAdd(s); } return jaccsymbol; - case 4: // '\004' return literals.findOrAdd(s, lexer.getLastLiteral()); + default: + break; } return null; } @@ -584,6 +579,8 @@ class JaccParser extends Phase implements JaccTokens { case 4: // '\004' return literals.find(lexer.getLastLiteral()); + default: + break; } return null; } @@ -598,7 +595,8 @@ class JaccParser extends Phase implements JaccTokens { tail = symlist; } - static int length(SymList symlist) { + static int length(SymList list) { + SymList symlist = list; int i = 0; for (; symlist != null; symlist = symlist.tail) { i++; @@ -606,9 +604,10 @@ class JaccParser extends Phase implements JaccTokens { return i; } - static JaccSymbol[] toArray(SymList symlist) { + static JaccSymbol[] toArray(SymList list) { + SymList symlist = list; int i = length(symlist); - JaccSymbol ajaccsymbol[] = new JaccSymbol[i]; + JaccSymbol[] ajaccsymbol = new JaccSymbol[i]; while (i > 0) { ajaccsymbol[--i] = symlist.head; symlist = symlist.tail; @@ -616,9 +615,10 @@ class JaccParser extends Phase implements JaccTokens { return ajaccsymbol; } - static int[] toIntArray(SymList symlist) { + static int[] toIntArray(SymList list) { + SymList symlist = list; int i = length(symlist); - int ai[] = new int[i]; + int[] ai = new int[i]; while (i > 0) { ai[--i] = symlist.head.getTokenNo(); symlist = symlist.tail; diff --git a/src/main/java/org/xbib/jacc/JaccProd.java b/src/main/java/org/xbib/jacc/JaccProd.java index 2cb4c36..8d8443e 100644 --- a/src/main/java/org/xbib/jacc/JaccProd.java +++ b/src/main/java/org/xbib/jacc/JaccProd.java @@ -16,11 +16,12 @@ class JaccProd extends Grammar.Prod { JaccProd(Fixity fixity, JaccSymbol[] jaccsymbol, Position position, String s, int i) { super(new int[jaccsymbol.length], i); this.fixity = fixity; - prodSyms = jaccsymbol; - actPos = position; - action = s; + this.prodSyms = jaccsymbol; + this.actPos = position; + this.action = s; } + @Override public String getLabel() { return Integer.toString(getSeqNo()); } diff --git a/src/main/java/org/xbib/jacc/JaccResolver.java b/src/main/java/org/xbib/jacc/JaccResolver.java index 19c8c43..de79b69 100644 --- a/src/main/java/org/xbib/jacc/JaccResolver.java +++ b/src/main/java/org/xbib/jacc/JaccResolver.java @@ -7,12 +7,15 @@ import org.xbib.jacc.grammar.Resolver; import org.xbib.jacc.grammar.Tables; import org.xbib.jacc.util.IntSet; +/** + * + */ class JaccResolver implements Resolver { private LookaheadMachine machine; private int numSRConflicts; private int numRRConflicts; - private Conflicts conflicts[]; + private Conflicts[] conflicts; JaccResolver(LookaheadMachine lookaheadmachine) { numSRConflicts = 0; @@ -49,6 +52,8 @@ class JaccResolver implements Resolver { return; case 3: return; + default: + break; } } conflicts[i] = Conflicts.sr(tables.getArgAt(i)[j], k, symbol, conflicts[i]); diff --git a/src/main/java/org/xbib/jacc/Settings.java b/src/main/java/org/xbib/jacc/JaccSettings.java similarity index 82% rename from src/main/java/org/xbib/jacc/Settings.java rename to src/main/java/org/xbib/jacc/JaccSettings.java index 85b24c0..7b62b6e 100644 --- a/src/main/java/org/xbib/jacc/Settings.java +++ b/src/main/java/org/xbib/jacc/JaccSettings.java @@ -9,12 +9,9 @@ import org.xbib.jacc.grammar.SLRMachine; /** * */ -class Settings { +class JaccSettings { - private static final int LR0 = 0; - private static final int SLR1 = 1; - private static final int LALR1 = 2; - private int machineType; + private MachineType machineType; private String packageName; private String className; private String interfaceName; @@ -27,28 +24,26 @@ class Settings { private StringBuilder preTextBuffer; private StringBuilder postTextBuffer; - Settings() { - machineType = LALR1; - preTextBuffer = new StringBuilder(); - postTextBuffer = new StringBuilder(); + JaccSettings() { + this.machineType = MachineType.LALR1; + this.preTextBuffer = new StringBuilder(); + this.postTextBuffer = new StringBuilder(); } - public int getMachineType() { - return machineType; - } - - void setMachineType(int i) { - machineType = i; + void setMachineType(MachineType machineType) { + this.machineType = machineType; } LookaheadMachine makeMachine(Grammar grammar) { - if (machineType == LR0) { - return new LR0Machine(grammar); - } - if (machineType == SLR1) { - return new SLRMachine(grammar); - } else { - return new LALRMachine(grammar); + switch (machineType) { + case LR0: + return new LR0Machine(grammar); + case SLR1: + return new SLRMachine(grammar); + case LALR1: + return new LALRMachine(grammar); + default: + return null; } } diff --git a/src/main/java/org/xbib/jacc/JaccSymbol.java b/src/main/java/org/xbib/jacc/JaccSymbol.java index 6f24658..f37611b 100644 --- a/src/main/java/org/xbib/jacc/JaccSymbol.java +++ b/src/main/java/org/xbib/jacc/JaccSymbol.java @@ -51,7 +51,7 @@ class JaccSymbol extends Grammar.Symbol { jaccProds = new JaccProd[1]; } else { if (pused >= jaccProds.length) { - JaccProd ajaccprod[] = new JaccProd[2 * jaccProds.length]; + JaccProd[] ajaccprod = new JaccProd[2 * jaccProds.length]; System.arraycopy(jaccProds, 0, ajaccprod, 0, jaccProds.length); jaccProds = ajaccprod; @@ -61,7 +61,7 @@ class JaccSymbol extends Grammar.Symbol { } public JaccProd[] getProds() { - JaccProd ajaccprod[] = new JaccProd[pused]; + JaccProd[] ajaccprod = new JaccProd[pused]; for (int i = 0; i < pused; i++) { ajaccprod[i] = jaccProds[i]; ajaccprod[i].fixup(); diff --git a/src/main/java/org/xbib/jacc/JaccSymbols.java b/src/main/java/org/xbib/jacc/JaccSymbols.java index 15af15c..c9dc35f 100644 --- a/src/main/java/org/xbib/jacc/JaccSymbols.java +++ b/src/main/java/org/xbib/jacc/JaccSymbols.java @@ -3,12 +3,14 @@ package org.xbib.jacc; abstract class JaccSymbols { Node root; int size; + JaccSymbols() { root = null; size = 0; } - private static int fill(JaccSymbol ajaccsymbol[], int i, Node node) { + private static int fill(JaccSymbol[] ajaccsymbol, int pos, Node node) { + int i = pos; if (node != null) { i = fill(ajaccsymbol, i, node.left); ajaccsymbol[i++] = node.data; @@ -21,11 +23,14 @@ abstract class JaccSymbols { return size; } - int fill(JaccSymbol ajaccsymbol[], int i) { + int fill(JaccSymbol[] ajaccsymbol, int i) { return fill(ajaccsymbol, i, root); } - protected static class Node { + /** + * + */ + static class Node { Node left; JaccSymbol data; diff --git a/src/main/java/org/xbib/jacc/JaccTables.java b/src/main/java/org/xbib/jacc/JaccTables.java index d697a27..294d7d6 100644 --- a/src/main/java/org/xbib/jacc/JaccTables.java +++ b/src/main/java/org/xbib/jacc/JaccTables.java @@ -19,8 +19,8 @@ class JaccTables extends Tables { JaccTables(LookaheadMachine lookaheadmachine, Resolver resolver) { super(lookaheadmachine, resolver); - errors = null; - numErrors = 0; + this.errors = null; + this.numErrors = 0; } int getNumErrors() { @@ -50,8 +50,10 @@ class JaccTables extends Tables { return i; } } - String as[] = new String[numErrors != 0 ? 2 * numErrors : 1]; - System.arraycopy(errors, 0, as, 0, numErrors); + String[] as = new String[numErrors != 0 ? 2 * numErrors : 1]; + if (errors != null) { + System.arraycopy(errors, 0, as, 0, numErrors); + } errors = as; errors[numErrors] = s; return numErrors++; @@ -132,7 +134,8 @@ class JaccTables extends Tables { defaultRow[i] = findDefault(); } - private void heapify(int i) { + private void heapify(int pos) { + int i = pos; int j = i; int k = idx[j]; do { diff --git a/src/main/java/org/xbib/jacc/MachineType.java b/src/main/java/org/xbib/jacc/MachineType.java new file mode 100644 index 0000000..31fac95 --- /dev/null +++ b/src/main/java/org/xbib/jacc/MachineType.java @@ -0,0 +1,7 @@ +package org.xbib.jacc; + +/** + */ +public enum MachineType { + LR0, SLR1, LALR1 +} diff --git a/src/main/java/org/xbib/jacc/ParserOutput.java b/src/main/java/org/xbib/jacc/ParserOutput.java index 1c9d0d9..f992646 100644 --- a/src/main/java/org/xbib/jacc/ParserOutput.java +++ b/src/main/java/org/xbib/jacc/ParserOutput.java @@ -10,7 +10,7 @@ import java.io.Writer; /** * */ -class ParserOutput extends Output { +class ParserOutput extends AbstractOutput { private int yyaccept; private int yyabort; @@ -33,29 +33,30 @@ class ParserOutput extends Output { tables.analyzeRows(); } + @Override public void write(Writer writer) throws IOException { datestamp(writer); - String s = settings.getPackageName(); + String s = jaccSettings.getPackageName(); if (s != null) { writer.write("package " + s + ";\n"); } - if (settings.getPreText() != null) { - writer.write(settings.getPreText() + "\n"); + if (jaccSettings.getPreText() != null) { + writer.write(jaccSettings.getPreText() + "\n"); } yyaccept = 2 * numStates; stackOverflow = 2 * numStates + 1; yyabort = 2 * numStates + 2; errorHandler = 2 * numStates + 3; userErrorHandler = 2 * numStates + 4; - int ai[] = new int[numNTs]; + int[] ai = new int[numNTs]; stNumSwitches = new int[numStates]; for (int i = 0; i < numStates; i++) { - int ai1[] = machine.getGotosAt(i); + int[] ai1 = machine.getGotosAt(i); for (int anAi1 : ai1) { ai[machine.getEntry(anAi1)]++; } - byte abyte0[] = tables.getActionAt(i); - int ai4[] = tables.getArgAt(i); + byte[] abyte0 = tables.getActionAt(i); + int[] ai4 = tables.getArgAt(i); int l3 = tables.getDefaultRowAt(i); stNumSwitches[i] = 0; for (int j4 = 0; j4 < abyte0.length; j4++) { @@ -73,7 +74,7 @@ class ParserOutput extends Output { ntGotoSrc[j] = new int[ai[j]]; } for (int k = 0; k < numStates; k++) { - int ai2[] = machine.getGotosAt(k); + int[] ai2 = machine.getGotosAt(k); for (int anAi2 : ai2) { int j3 = machine.getEntry(anAi2); ntGoto[j3][--ai[j3]] = anAi2; @@ -101,12 +102,12 @@ class ParserOutput extends Output { } errMsgs = tables.getNumErrors() > 0; errTok = numNTs; - while (errTok < numSyms && !grammar.getSymbol(errTok).getName().equals("error")) { + while (errTok < numSyms && !"error".equals(grammar.getSymbol(errTok).getName())) { errTok++; } if (errTok < numSyms) { for (int i1 = 0; i1 < numStates && !errUsed; i1++) { - int ai3[] = machine.getShiftsAt(i1); + int[] ai3 = machine.getShiftsAt(i1); for (int l2 = 0; l2 < ai3.length && !errUsed; l2++) { if (machine.getEntry(ai3[l2]) == errTok) { errUsed = true; @@ -114,12 +115,12 @@ class ParserOutput extends Output { } } } - writer.write("public class " + settings.getClassName()); - if (settings.getExtendsName() != null) { - writer.write(" extends " + settings.getExtendsName()); + writer.write("public class " + jaccSettings.getClassName()); + if (jaccSettings.getExtendsName() != null) { + writer.write(" extends " + jaccSettings.getExtendsName()); } - if (settings.getImplementsNames() != null) { - writer.write(" implements " + settings.getImplementsNames()); + if (jaccSettings.getImplementsNames() != null) { + writer.write(" implements " + jaccSettings.getImplementsNames()); } writer.write(" {\n"); indent(writer, 1, new String[]{ @@ -132,8 +133,8 @@ class ParserOutput extends Output { if (errUsed) { indent(writer, 1, "private int yyerrstatus = 3;"); } - indent(writer, 1, "private " + settings.getTypeName() + "[] yysv;"); - indent(writer, 1, "private " + settings.getTypeName() + " yyrv;"); + indent(writer, 1, "private " + jaccSettings.getTypeName() + "[] yysv;"); + indent(writer, 1, "private " + jaccSettings.getTypeName() + " yyrv;"); writer.write("\n"); defineParse(writer, 1); defineExpand(writer, 1); @@ -142,15 +143,15 @@ class ParserOutput extends Output { defineState(writer, 1, j1); } for (int k1 = 0; k1 < numNTs; k1++) { - Grammar.Prod aprod[] = grammar.getProds(k1); + Grammar.Prod[] aprod = grammar.getProds(k1); for (Grammar.Prod anAprod : aprod) { defineReduce(writer, 1, anAprod, k1); } defineNonterminal(writer, 1, k1); } defineErrMsgs(writer); - if (settings.getPostText() != null) { - writer.write(settings.getPostText() + "\n"); + if (jaccSettings.getPostText() != null) { + writer.write(jaccSettings.getPostText() + "\n"); } writer.write("}\n"); } @@ -176,7 +177,10 @@ class ParserOutput extends Output { indent(writer, i, new String[]{ "protected void yyexpand() {", " int[] newyyst = new int[2*yyst.length];" }); - indent(writer, i + 1, settings.getTypeName() + "[] newyysv = new " + settings.getTypeName() + "[2*yyst.length];"); + indent(writer, i + 1, jaccSettings.getTypeName() + + "[] newyysv = new " + + jaccSettings.getTypeName() + + "[2*yyst.length];"); indent(writer, i, new String[]{ " for (int i=0; i 0) { indent(writer, i, "switch (yytok) {"); - int ai1[] = tables.indexAt(j); + int[] ai1 = tables.indexAt(j); int k1; for (int l = 0; l < ai1.length; l = k1) { int i1 = ai1[l]; @@ -357,7 +361,7 @@ class ParserOutput extends Output { } private void translateAction(Writer writer, JaccProd jaccprod, String s) throws IOException { - int ai[] = jaccprod.getRhs(); + int[] ai = jaccprod.getRhs(); int i = s.length(); for (int j = 0; j < i; j++) { char c = s.charAt(j); @@ -466,11 +470,11 @@ class ParserOutput extends Output { indent(writer, i, "case " + userErrorHandler + " :"); indent(writer, i + 1, new String[]{ "if (yyerrstatus==0) {", - " if ((" + settings.getGetToken(), + " if ((" + jaccSettings.getGetToken(), " )==ENDINPUT) {", " return false;", " }", - " " + settings.getNextToken(), + " " + jaccSettings.getNextToken(), " ;" }); indent(writer, i + 2, "yyn = " + numStates + " + yyst[yysp-1];"); diff --git a/src/main/java/org/xbib/jacc/TextOutput.java b/src/main/java/org/xbib/jacc/TextOutput.java index 832fa23..58bca37 100644 --- a/src/main/java/org/xbib/jacc/TextOutput.java +++ b/src/main/java/org/xbib/jacc/TextOutput.java @@ -9,7 +9,7 @@ import java.io.Writer; /** * */ -class TextOutput extends Output { +class TextOutput extends AbstractOutput { private boolean wantFirst; @@ -20,6 +20,7 @@ class TextOutput extends Output { tables.analyzeRows(); } + @Override public void write(Writer writer) throws IOException { datestamp(writer); for (int i = 0; i < numStates; i++) { @@ -33,10 +34,10 @@ class TextOutput extends Output { writer.write("\n"); } writer.write("\n"); - byte abyte0[] = tables.getActionAt(i); - int ai1[] = tables.getArgAt(i); + byte[] abyte0 = tables.getActionAt(i); + int[] ai1 = tables.getArgAt(i); int j1 = tables.getDefaultRowAt(i); - int ai2[] = tables.indexAt(i); + int[] ai2 = tables.indexAt(i); for (int k1 = 0; k1 < abyte0.length; k1++) { int l1 = ai2[k1]; if (j1 < 0 || abyte0[l1] != abyte0[j1] || ai1[l1] != ai1[j1]) { @@ -54,7 +55,7 @@ class TextOutput extends Output { writer.write(describeAction(i, abyte0[j1], ai1[j1]) + "\n"); } writer.write("\n"); - int ai3[] = machine.getGotosAt(i); + int[] ai3 = machine.getGotosAt(i); if (ai3.length <= 0) { continue; } @@ -77,10 +78,10 @@ class TextOutput extends Output { } if (tables.getProdUnused() > 0) { for (int j = 0; j < numNTs; j++) { - boolean aflag[] = tables.getProdsUsedAt(j); + boolean[] aflag = tables.getProdsUsedAt(j); for (int l = 0; l < aflag.length; l++) { if (!aflag[l]) { - int ai[] = grammar.getProds(j)[l].getRhs(); + int[] ai = grammar.getProds(j)[l].getRhs(); writer.write("Rule not reduced: "); writer.write(grammar.getNonterminal(j).getName()); writer.write(" : "); diff --git a/src/main/java/org/xbib/jacc/TokensOutput.java b/src/main/java/org/xbib/jacc/TokensOutput.java index 3a60e98..8a2ef98 100644 --- a/src/main/java/org/xbib/jacc/TokensOutput.java +++ b/src/main/java/org/xbib/jacc/TokensOutput.java @@ -9,7 +9,7 @@ import java.io.Writer; /** * */ -class TokensOutput extends Output { +class TokensOutput extends AbstractOutput { TokensOutput(Handler handler, JaccJob jaccjob) { super(handler, jaccjob); @@ -18,11 +18,11 @@ class TokensOutput extends Output { @Override public void write(Writer writer) throws IOException { datestamp(writer); - String s = settings.getPackageName(); + String s = jaccSettings.getPackageName(); if (s != null) { writer.write("package " + s + ";\n\n"); } - writer.write("interface " + settings.getInterfaceName() + " {\n"); + writer.write("interface " + jaccSettings.getInterfaceName() + " {\n"); indent(writer, 1); writer.write("int ENDINPUT = 0;\n"); for (int i = 0; i < numTs - 1; i++) { diff --git a/src/main/java/org/xbib/jacc/compiler/ConsoleHandler.java b/src/main/java/org/xbib/jacc/compiler/ConsoleHandler.java index 6ac588b..654f052 100644 --- a/src/main/java/org/xbib/jacc/compiler/ConsoleHandler.java +++ b/src/main/java/org/xbib/jacc/compiler/ConsoleHandler.java @@ -1,23 +1,32 @@ package org.xbib.jacc.compiler; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * */ public class ConsoleHandler extends Handler { + + private static final Logger logger = Logger.getLogger(ConsoleHandler.class.getName()); + + @Override protected void respondTo(Diagnostic diagnostic) { Position position = diagnostic.getPos(); + Level level; + StringBuilder sb = new StringBuilder(); if (diagnostic instanceof Warning) { - System.err.print("WARNING: "); + level = Level.WARNING; } else { - System.err.print("ERROR: "); + level = Level.SEVERE; } if (position != null) { - System.err.println(position.describe()); + sb.append(position.describe()); } String s = diagnostic.getText(); if (s != null) { - System.err.println(s); + sb.append(s); } - System.err.println(); + logger.log(level, sb.toString()); } } diff --git a/src/main/java/org/xbib/jacc/compiler/Diagnostic.java b/src/main/java/org/xbib/jacc/compiler/Diagnostic.java index a292061..dd08610 100644 --- a/src/main/java/org/xbib/jacc/compiler/Diagnostic.java +++ b/src/main/java/org/xbib/jacc/compiler/Diagnostic.java @@ -5,16 +5,17 @@ package org.xbib.jacc.compiler; */ abstract class Diagnostic extends Exception { - private String text; - private Position position; + private final String text; + private final transient Position position; Diagnostic(String s) { - text = s; + this.position = null; + this.text = s; } Diagnostic(Position position, String s) { this.position = position; - text = s; + this.text = s; } String getText() { diff --git a/src/main/java/org/xbib/jacc/compiler/JavaSource.java b/src/main/java/org/xbib/jacc/compiler/JavaSource.java index ddaf79e..35def08 100644 --- a/src/main/java/org/xbib/jacc/compiler/JavaSource.java +++ b/src/main/java/org/xbib/jacc/compiler/JavaSource.java @@ -8,30 +8,24 @@ import java.io.Reader; */ public class JavaSource extends Source { - private final StringBuilder buf; + private final StringBuilder sb; private Reader input; private int tabwidth; - private String description; private int c0; private int c1; private int lineNumber; - public JavaSource(Handler handler, String s, Reader reader) { - this(handler, s, reader, 8); + public JavaSource(Handler handler, Reader reader) { + this(handler, reader, 8); } - private JavaSource(Handler handler, String s, Reader reader, int i) { + private JavaSource(Handler handler, Reader reader, int i) { super(handler); - c1 = 0; - lineNumber = 0; - description = s; - input = reader; - tabwidth = i; - buf = new StringBuilder(); - } - - public String describe() { - return description; + this.c1 = 0; + this.lineNumber = 0; + this.input = reader; + this.tabwidth = i; + this.sb = new StringBuilder(); } private void skip() throws IOException { @@ -49,7 +43,7 @@ public class JavaSource extends Source { if (input == null) { return null; } - buf.setLength(0); + sb.setLength(0); if (lineNumber++ == 0) { skip(); skip(); @@ -77,24 +71,24 @@ public class JavaSource extends Source { if (k != 4) { report(new Warning("Error in Unicode escape sequence")); } else { - buf.append((char) i); + sb.append((char) i); } continue; } - buf.append('\\'); + sb.append('\\'); if (c0 == -1) { break; } - buf.append((char) c0); + sb.append((char) c0); skip(); } else if (c0 == 9 && tabwidth > 0) { - for (int j = tabwidth - buf.length() % tabwidth; j > 0; j--) { - buf.append(' '); + for (int j = tabwidth - sb.length() % tabwidth; j > 0; j--) { + sb.append(' '); } skip(); } else { - buf.append((char) c0); + sb.append((char) c0); skip(); } } while (true); @@ -104,18 +98,20 @@ public class JavaSource extends Source { if (c0 == 10) { skip(); } - return buf.toString(); + return sb.toString(); } + @Override public int getLineNo() { return lineNumber; } + @Override public void close() throws IOException { if (input != null) { input.close(); input = null; - buf.setLength(0); + sb.setLength(0); } } } diff --git a/src/main/java/org/xbib/jacc/compiler/Position.java b/src/main/java/org/xbib/jacc/compiler/Position.java index f90ef5d..01c062b 100644 --- a/src/main/java/org/xbib/jacc/compiler/Position.java +++ b/src/main/java/org/xbib/jacc/compiler/Position.java @@ -3,9 +3,9 @@ package org.xbib.jacc.compiler; /** * */ -public abstract class Position { +public interface Position { - public abstract String describe(); + String describe(); - public abstract Position copy(); + Position copy(); } diff --git a/src/main/java/org/xbib/jacc/compiler/Source.java b/src/main/java/org/xbib/jacc/compiler/Source.java index 1c7bfc3..d1414ea 100644 --- a/src/main/java/org/xbib/jacc/compiler/Source.java +++ b/src/main/java/org/xbib/jacc/compiler/Source.java @@ -1,18 +1,17 @@ package org.xbib.jacc.compiler; +import java.io.Closeable; import java.io.IOException; /** * */ -public abstract class Source extends Phase { +public abstract class Source extends Phase implements Closeable { Source(Handler handler) { super(handler); } - public abstract String describe(); - public abstract String readLine() throws IOException; public abstract int getLineNo(); @@ -21,6 +20,4 @@ public abstract class Source extends Phase { return null; } - public void close() throws IOException { - } } diff --git a/src/main/java/org/xbib/jacc/compiler/SourceLexer.java b/src/main/java/org/xbib/jacc/compiler/SourceLexer.java index 395de6a..118ca13 100644 --- a/src/main/java/org/xbib/jacc/compiler/SourceLexer.java +++ b/src/main/java/org/xbib/jacc/compiler/SourceLexer.java @@ -15,13 +15,14 @@ public abstract class SourceLexer extends Lexer { public SourceLexer(Handler handler, Source source) throws IOException { super(handler); - col = -1; + this.col = -1; this.source = source; - pos = new SourcePosition(source); - line = source.readLine(); + this.pos = new SourcePosition(source); + this.line = source.readLine(); nextChar(); } + @Override public Position getPos() { return pos.copy(); } @@ -50,6 +51,7 @@ public abstract class SourceLexer extends Lexer { return c; } + @Override public void close() throws IOException { if (source != null) { source.close(); diff --git a/src/main/java/org/xbib/jacc/compiler/SourcePosition.java b/src/main/java/org/xbib/jacc/compiler/SourcePosition.java index aae3771..de4a2f0 100644 --- a/src/main/java/org/xbib/jacc/compiler/SourcePosition.java +++ b/src/main/java/org/xbib/jacc/compiler/SourcePosition.java @@ -3,7 +3,7 @@ package org.xbib.jacc.compiler; /** * */ -class SourcePosition extends Position { +class SourcePosition implements Position { private final Source source; @@ -30,9 +30,6 @@ class SourcePosition extends Position { public String describe() { StringBuilder sb = new StringBuilder(); if (source != null) { - sb.append('"'); - sb.append(source.describe()); - sb.append('"'); if (row > 0) { sb.append(", "); } diff --git a/src/main/java/org/xbib/jacc/grammar/Analysis.java b/src/main/java/org/xbib/jacc/grammar/Analysis.java index f2277de..0f0c518 100644 --- a/src/main/java/org/xbib/jacc/grammar/Analysis.java +++ b/src/main/java/org/xbib/jacc/grammar/Analysis.java @@ -1,5 +1,8 @@ package org.xbib.jacc.grammar; +import java.io.IOException; +import java.io.Writer; + /** * */ @@ -23,7 +26,7 @@ abstract class Analysis { } } - private void analyzeComponent(int ai[]) { + private void analyzeComponent(int[] ai) { for (boolean flag = true; flag; ) { flag = false; int i = 0; @@ -34,5 +37,21 @@ abstract class Analysis { } } + public void display(Writer writer, int numNTs, Grammar grammar) throws IOException { + int i = 0; + for (int j = 0; j < numNTs; j++) { + if (!isAt(j)) { + continue; + } + if (i > 0) { + writer.write(", "); + } + writer.write(grammar.getSymbol(j).getName()); + i++; + } + } + + public abstract boolean isAt(int i); + protected abstract boolean analyze(int i); } diff --git a/src/main/java/org/xbib/jacc/grammar/Finitary.java b/src/main/java/org/xbib/jacc/grammar/Finitary.java index f1ad733..4f7bd95 100644 --- a/src/main/java/org/xbib/jacc/grammar/Finitary.java +++ b/src/main/java/org/xbib/jacc/grammar/Finitary.java @@ -8,38 +8,39 @@ import java.io.Writer; */ public final class Finitary extends Analysis { - private boolean[] finitary; - private boolean[] consider; - private Grammar grammar; - private int numNTs; + private final boolean[] finitaries; + private final boolean[] consider; + private final Grammar grammar; + private final int numNTs; Finitary(Grammar grammar) { super(grammar.getComponents()); this.grammar = grammar; numNTs = grammar.getNumNTs(); - finitary = new boolean[numNTs]; + finitaries = new boolean[numNTs]; consider = new boolean[numNTs]; for (int i = 0; i < numNTs; i++) { - finitary[i] = false; + finitaries[i] = false; consider[i] = true; } bottomUp(); } + @Override protected boolean analyze(int i) { boolean flag = false; if (consider[i]) { int j = 0; - Grammar.Prod[] aprod = grammar.getProds(i); - for (Grammar.Prod anAprod : aprod) { - int ai[] = anAprod.getRhs(); + Grammar.Prod[] prods = grammar.getProds(i); + for (Grammar.Prod prod : prods) { + int[] ai = prod.getRhs(); int l; l = 0; - while (l < ai.length && at(ai[l])) { + while (l < ai.length && isAt(ai[l])) { l++; } if (l >= ai.length) { - finitary[i] = true; + finitaries[i] = true; consider[i] = false; flag = true; break; @@ -48,30 +49,20 @@ public final class Finitary extends Analysis { j++; } } - if (j == aprod.length) { + if (j == prods.length) { consider[i] = false; } } return flag; } - public boolean at(int i) { - return grammar.isTerminal(i) || finitary[i]; + public boolean isAt(int i) { + return grammar.isTerminal(i) || finitaries[i]; } public void display(Writer writer) throws IOException { writer.write("Finitary = {"); - int i = 0; - for (int j = 0; j < numNTs; j++) { - if (!at(j)) { - continue; - } - if (i > 0) { - writer.write(", "); - } - writer.write(grammar.getSymbol(j).getName()); - i++; - } + super.display(writer, numNTs, grammar); writer.write("}\n"); } } diff --git a/src/main/java/org/xbib/jacc/grammar/First.java b/src/main/java/org/xbib/jacc/grammar/First.java index fdcef65..f830d00 100644 --- a/src/main/java/org/xbib/jacc/grammar/First.java +++ b/src/main/java/org/xbib/jacc/grammar/First.java @@ -13,7 +13,7 @@ public class First extends Analysis { private Grammar grammar; private Nullable nullable; private int numNTs; - private int[][] first; + private int[][] firsts; First(Grammar grammar1, Nullable nullable1) { super(grammar1.getComponents()); @@ -21,13 +21,19 @@ public class First extends Analysis { nullable = nullable1; numNTs = grammar1.getNumNTs(); int numTs = grammar1.getNumTs(); - first = new int[numNTs][]; + firsts = new int[numNTs][]; for (int i = 0; i < numNTs; i++) { - first[i] = BitSet.make(numTs); + firsts[i] = BitSet.make(numTs); } bottomUp(); } + @Override + public boolean isAt(int i) { + return false; + } + + @Override protected boolean analyze(int i) { boolean flag = false; Grammar.Prod[] aprod = grammar.getProds(i); @@ -40,15 +46,15 @@ public class First extends Analysis { continue label0; } if (grammar.isTerminal(ai[k])) { - if (BitSet.addTo(first[i], ai[k] - numNTs)) { + if (BitSet.addTo(firsts[i], ai[k] - numNTs)) { flag = true; } continue label0; } - if (BitSet.addTo(first[i], first[ai[k]])) { + if (BitSet.addTo(firsts[i], firsts[ai[k]])) { flag = true; } - if (!nullable.at(ai[k])) { + if (!nullable.isAt(ai[k])) { continue label0; } k++; @@ -59,12 +65,12 @@ public class First extends Analysis { } public int[] at(int i) { - return first[i]; + return firsts[i]; } public void display(Writer writer) throws IOException { writer.write("First sets:\n"); - for (int i = 0; i < first.length; i++) { + for (int i = 0; i < firsts.length; i++) { writer.write(" First(" + grammar.getSymbol(i) + "): {"); writer.write(grammar.displaySymbolSet(at(i), numNTs)); writer.write("}\n"); diff --git a/src/main/java/org/xbib/jacc/grammar/Follow.java b/src/main/java/org/xbib/jacc/grammar/Follow.java index db8fc25..0dad6f6 100644 --- a/src/main/java/org/xbib/jacc/grammar/Follow.java +++ b/src/main/java/org/xbib/jacc/grammar/Follow.java @@ -14,7 +14,7 @@ public class Follow extends Analysis { private Nullable nullable; private First first; private int numNTs; - private int[][] follow; + private int[][] follows; Follow(Grammar grammar, Nullable nullable, First first1) { super(grammar.getComponents()); @@ -23,17 +23,23 @@ public class Follow extends Analysis { first = first1; numNTs = grammar.getNumNTs(); int numTs = grammar.getNumTs(); - follow = new int[numNTs][]; + follows = new int[numNTs][]; for (int i = 0; i < numNTs; i++) { - follow[i] = BitSet.make(numTs); + follows[i] = BitSet.make(numTs); } - BitSet.set(follow[0], numTs - 1); + BitSet.set(follows[0], numTs - 1); topDown(); } + @Override + public boolean isAt(int i) { + return false; + } + + @Override protected boolean analyze(int i) { boolean flag = false; - Grammar.Prod aprod[] = grammar.getProds(i); + Grammar.Prod[] aprod = grammar.getProds(i); for (Grammar.Prod anAprod : aprod) { int[] ai = anAprod.getRhs(); for (int k = 0; k < ai.length; k++) { @@ -46,20 +52,20 @@ public class Follow extends Analysis { break; } if (grammar.isTerminal(ai[l])) { - if (BitSet.addTo(follow[ai[k]], ai[l] - numNTs)) { + if (BitSet.addTo(follows[ai[k]], ai[l] - numNTs)) { flag = true; } break; } - if (BitSet.addTo(follow[ai[k]], first.at(ai[l]))) { + if (BitSet.addTo(follows[ai[k]], first.at(ai[l]))) { flag = true; } - if (!nullable.at(ai[l])) { + if (!nullable.isAt(ai[l])) { break; } l++; } while (true); - if (l >= ai.length && BitSet.addTo(follow[ai[k]], follow[i])) { + if (l >= ai.length && BitSet.addTo(follows[ai[k]], follows[i])) { flag = true; } } @@ -68,12 +74,12 @@ public class Follow extends Analysis { } public int[] at(int i) { - return follow[i]; + return follows[i]; } public void display(Writer writer) throws IOException { writer.write("Follow sets:\n"); - for (int i = 0; i < follow.length; i++) { + for (int i = 0; i < follows.length; i++) { writer.write(" Follow(" + grammar.getSymbol(i) + "): {"); writer.write(grammar.displaySymbolSet(at(i), numNTs)); writer.write("}\n"); diff --git a/src/main/java/org/xbib/jacc/grammar/Grammar.java b/src/main/java/org/xbib/jacc/grammar/Grammar.java index dc36d29..7249260 100644 --- a/src/main/java/org/xbib/jacc/grammar/Grammar.java +++ b/src/main/java/org/xbib/jacc/grammar/Grammar.java @@ -1,5 +1,6 @@ package org.xbib.jacc.grammar; +import org.xbib.jacc.JaccException; import org.xbib.jacc.util.BitSet; import org.xbib.jacc.util.Interator; import org.xbib.jacc.util.SCC; @@ -25,7 +26,7 @@ public class Grammar { private First first; private Follow follow; - public Grammar(Symbol[] symbols, Prod[][] prods) throws Exception { + public Grammar(Symbol[] symbols, Prod[][] prods) throws JaccException { validate(symbols, prods); this.symbols = symbols; numSyms = symbols.length; @@ -36,37 +37,37 @@ public class Grammar { comps = SCC.get(depends, revdeps, numNTs); } - private static void validate(Symbol[] symbol, Prod[][] prod) throws Exception { + private static void validate(Symbol[] symbol, Prod[][] prod) throws JaccException { if (symbol == null || symbol.length == 0) { - throw new Exception("No symbols specified"); + throw new JaccException("No symbols specified"); } for (int i = 0; i < symbol.length; i++) { if (symbol[i] == null) { - throw new Exception("Symbol " + i + " is null"); + throw new JaccException("Symbol " + i + " is null"); } } int j = symbol.length; if (prod == null || prod.length == 0) { - throw new Exception("No nonterminals specified"); + throw new JaccException("No nonterminals specified"); } if (prod.length > j) { - throw new Exception("To many nonterminals specified"); + throw new JaccException("To many nonterminals specified"); } if (prod.length == j) { - throw new Exception("No terminals specified"); + throw new JaccException("No terminals specified"); } for (int k = 0; k < prod.length; k++) { if (prod[k] == null || prod[k].length == 0) { - throw new Exception("Nonterminal " + symbol[k] + " (number " + k + ") has no productions"); + throw new JaccException("Nonterminal " + symbol[k] + " (number " + k + ") has no productions"); } for (int l = 0; l < prod[k].length; l++) { int[] ai = prod[k][l].getRhs(); if (ai == null) { - throw new Exception("Production " + l + " for symbol " + symbol[k] + " (number " + k + ") is null"); + throw new JaccException("Production " + l + " for symbol " + symbol[k] + " (number " + k + ") is null"); } for (int m : ai) { if (m < 0 || m >= j - 1) { - throw new Exception("Out of range symbol " + m + " in production " + l + " for symbol " + + throw new JaccException("Out of range symbol " + m + " in production " + l + " for symbol " + symbol[k] + " (number " + k + ")"); } } @@ -227,7 +228,7 @@ public class Grammar { int j = 0; for (Interator interator = BitSet.interator(ai, i); interator.hasNext(); sb.append(symbols[interator.next()].getName())) { - if (j++ != 0) { + if (j++ > 0) { sb.append(", "); } } @@ -239,7 +240,7 @@ public class Grammar { */ public static class Prod { - int[] rhs; + private int[] rhs; private int seqNo; public Prod(int[] ai, int i) { diff --git a/src/main/java/org/xbib/jacc/grammar/LALRMachine.java b/src/main/java/org/xbib/jacc/grammar/LALRMachine.java index c70d751..c57f863 100644 --- a/src/main/java/org/xbib/jacc/grammar/LALRMachine.java +++ b/src/main/java/org/xbib/jacc/grammar/LALRMachine.java @@ -12,9 +12,9 @@ import java.io.Writer; */ public class LALRMachine extends LookaheadMachine { - private Nullable nullable; - private First first; - private int[][] predState; + private final Nullable nullable; + private final First first; + private final int[][] predState; private int numGotos; private int[] stateFirstGoto; private int[] gotoSource; @@ -25,13 +25,14 @@ public class LALRMachine extends LookaheadMachine { public LALRMachine(Grammar grammar) { super(grammar); - nullable = grammar.getNullable(); - first = grammar.getFirst(); - predState = SCC.invert(succState, numStates); + this.nullable = grammar.getNullable(); + this.first = grammar.getFirst(); + this.predState = SCC.invert(succState, numStates); calcGotoLA(); calcLookahead(); } + @Override public int[] getLookaheadAt(int i, int j) { return laReds[i][j]; } @@ -104,7 +105,8 @@ public class LALRMachine extends LookaheadMachine { gotoTargets[i] = intset1.toArray(); } - private LR0Items.Item calcFirsts(int[] ai, LR0Items.Item item) { + private LR0Items.Item calcFirsts(int[] ai, LR0Items.Item it) { + LR0Items.Item item = it; do { if (!item.canGoto()) { break; @@ -115,7 +117,7 @@ public class LALRMachine extends LookaheadMachine { break; } BitSet.union(ai, first.at(i)); - if (!nullable.at(i)) { + if (!nullable.isAt(i)) { break; } item = items.getItem(item.getNextItem()); @@ -126,7 +128,8 @@ public class LALRMachine extends LookaheadMachine { return item; } - private void findTargets(IntSet intset, int i, int j, int[] ai, int k) { + private void findTargets(IntSet intset, int i, int j, int[] ai, int kk) { + int k = kk; if (k == 0) { int[] ai1 = getGotosAt(i); int i1 = 0; @@ -164,7 +167,8 @@ public class LALRMachine extends LookaheadMachine { } } - private void lookBack(int[] ai, int i, int j, int[] ai1, int k) { + private void lookBack(int[] ai, int i, int j, int[] ai1, int kk) { + int k = kk; if (k == 0) { int[] ai2 = getGotosAt(i); for (int i1 = 0; i1 < ai2.length; i1++) { diff --git a/src/main/java/org/xbib/jacc/grammar/Left.java b/src/main/java/org/xbib/jacc/grammar/Left.java index aa378f0..b62b355 100644 --- a/src/main/java/org/xbib/jacc/grammar/Left.java +++ b/src/main/java/org/xbib/jacc/grammar/Left.java @@ -25,6 +25,11 @@ final class Left extends Analysis { bottomUp(); } + @Override + public boolean isAt(int i) { + return false; + } + protected boolean analyze(int i) { boolean flag = false; Grammar.Prod aprod[] = grammar.getProds(i); diff --git a/src/main/java/org/xbib/jacc/grammar/Machine.java b/src/main/java/org/xbib/jacc/grammar/Machine.java index adf1b83..6a4e956 100644 --- a/src/main/java/org/xbib/jacc/grammar/Machine.java +++ b/src/main/java/org/xbib/jacc/grammar/Machine.java @@ -127,12 +127,14 @@ public class Machine { } int[] ai1 = new int[i]; int j1 = 0; - for (int l1 = 0; j1 < i; l1++) { + int l1 = 0; + while (j1 < i) { if (aintset[l1] != null) { ai1[j1] = addState(l1, aintset[l1]); aintset[l1] = null; j1++; } + l1++; } i = 0; succState[j] = ai1; diff --git a/src/main/java/org/xbib/jacc/grammar/Nullable.java b/src/main/java/org/xbib/jacc/grammar/Nullable.java index 7296c7b..b847c52 100644 --- a/src/main/java/org/xbib/jacc/grammar/Nullable.java +++ b/src/main/java/org/xbib/jacc/grammar/Nullable.java @@ -8,38 +8,39 @@ import java.io.Writer; */ public class Nullable extends Analysis { - private boolean nullable[]; - private boolean consider[]; - private Grammar grammar; - private int numNTs; + private final boolean[] nullables; + private final boolean[] consider; + private final Grammar grammar; + private final int numNTs; Nullable(Grammar grammar) { super(grammar.getComponents()); this.grammar = grammar; numNTs = grammar.getNumNTs(); - nullable = new boolean[numNTs]; + nullables = new boolean[numNTs]; consider = new boolean[numNTs]; for (int i = 0; i < numNTs; i++) { - nullable[i] = false; + nullables[i] = false; consider[i] = true; } bottomUp(); } + @Override protected boolean analyze(int i) { boolean flag = false; if (consider[i]) { int j = 0; - Grammar.Prod aprod[] = grammar.getProds(i); - for (Grammar.Prod anAprod : aprod) { - int ai[] = anAprod.getRhs(); + Grammar.Prod[] prods = grammar.getProds(i); + for (Grammar.Prod prod : prods) { + int[] ai = prod.getRhs(); int l; l = 0; - while (l < ai.length && at(ai[l])) { + while (l < ai.length && isAt(ai[l])) { l++; } if (l >= ai.length) { - nullable[i] = true; + nullables[i] = true; consider[i] = false; flag = true; break; @@ -48,30 +49,21 @@ public class Nullable extends Analysis { j++; } } - if (j == aprod.length) { + if (j == prods.length) { consider[i] = false; } } return flag; } - public boolean at(int i) { - return grammar.isNonterminal(i) && nullable[i]; + @Override + public boolean isAt(int i) { + return grammar.isNonterminal(i) && nullables[i]; } public void display(Writer writer) throws IOException { writer.write("Nullable = {"); - int i = 0; - for (int j = 0; j < numNTs; j++) { - if (!at(j)) { - continue; - } - if (i > 0) { - writer.write(", "); - } - writer.write(grammar.getSymbol(j).getName()); - i++; - } + super.display(writer, numNTs, grammar); writer.write("}\n"); } } diff --git a/src/main/java/org/xbib/jacc/grammar/Parser.java b/src/main/java/org/xbib/jacc/grammar/Parser.java index b564f90..d19f7f8 100644 --- a/src/main/java/org/xbib/jacc/grammar/Parser.java +++ b/src/main/java/org/xbib/jacc/grammar/Parser.java @@ -14,7 +14,7 @@ public class Parser { private static final int GOTO = 3; private static final int REDUCE = 4; private Tables tables; - private int input[]; + private int[] input; private Machine machine; private Grammar grammar; private int position; @@ -23,16 +23,16 @@ public class Parser { private Stack stack; private int state; - public Parser(Tables tables, int ai[]) { - position = 0; - currSymbol = -1; - reducedNT = -1; - stack = new Stack(); - state = ACCEPT; + public Parser(Tables tables, int[] ai) { + this.position = 0; + this.currSymbol = -1; + this.reducedNT = -1; + this.stack = new Stack(); + this.state = ACCEPT; this.tables = tables; - input = ai; - machine = tables.getMachine(); - grammar = machine.getGrammar(); + this.input = ai; + this.machine = tables.getMachine(); + this.grammar = machine.getGrammar(); } public int getState() { @@ -84,6 +84,8 @@ public class Parser { case 2: reduce(ai[i]); return REDUCE; + default: + break; } return ERROR; } @@ -106,7 +108,7 @@ public class Parser { } private boolean gotoState(int i) { - int ai[] = machine.getGotosAt(state); + int[] ai = machine.getGotosAt(state); for (int anAi : ai) { if (i == machine.getEntry(anAi)) { state = anAi; @@ -122,18 +124,21 @@ public class Parser { writer.write(state); writer.write(" "); } - writer.write("_ "); + writer.write("_"); if (reducedNT >= 0) { + writer.write(" "); writer.write(grammar.getSymbol(reducedNT).toString()); writer.write(" "); } if (currSymbol >= 0) { + writer.write(" "); writer.write(grammar.getSymbol(currSymbol).toString()); if (position < input.length) { writer.write(" ..."); } } else { if (position < input.length) { + writer.write(" "); writer.write(grammar.getSymbol(input[position]).toString()); writer.write(" ..."); } diff --git a/src/main/java/org/xbib/jacc/grammar/SLRMachine.java b/src/main/java/org/xbib/jacc/grammar/SLRMachine.java index 3c2bff7..2bcd368 100644 --- a/src/main/java/org/xbib/jacc/grammar/SLRMachine.java +++ b/src/main/java/org/xbib/jacc/grammar/SLRMachine.java @@ -19,6 +19,7 @@ public class SLRMachine extends LookaheadMachine { calcLookahead(); } + @Override public int[] getLookaheadAt(int i, int j) { return laReds[i][j]; } @@ -36,6 +37,7 @@ public class SLRMachine extends LookaheadMachine { } } + @Override public void display(Writer writer) throws IOException { super.display(writer); for (int i = 0; i < numStates; i++) { diff --git a/src/main/java/org/xbib/jacc/util/BitSet.java b/src/main/java/org/xbib/jacc/util/BitSet.java index 86078a9..2f443da 100644 --- a/src/main/java/org/xbib/jacc/util/BitSet.java +++ b/src/main/java/org/xbib/jacc/util/BitSet.java @@ -37,7 +37,7 @@ public class BitSet { public static boolean addTo(int[] ai, int[] ai1) { if (ai.length < ai1.length) { - throw new Error("bitset arguments do not match"); + throw new IllegalArgumentException("bitset arguments do not match"); } int i = 0; boolean flag = false; @@ -125,45 +125,4 @@ public class BitSet { public static Interator interator(int[] ai, int i) { return new BitSetInterator(ai, i); } - - private static class BitSetInterator extends Interator { - - int[] set; - int pos; - int mask; - int num; - int bitCount; - - BitSetInterator(int[] ai, int i) { - set = ai; - num = i; - pos = 0; - mask = 1; - bitCount = 0; - } - - private void advance() { - num++; - if (++bitCount == 32) { - pos++; - bitCount = 0; - mask = 1; - } else { - mask <<= 1; - } - } - - public int next() { - int i = num; - advance(); - return i; - } - - public boolean hasNext() { - while (pos < set.length && (set[pos] & mask) == 0) { - advance(); - } - return pos < set.length; - } - } } diff --git a/src/main/java/org/xbib/jacc/util/BitSetInterator.java b/src/main/java/org/xbib/jacc/util/BitSetInterator.java new file mode 100644 index 0000000..da9156b --- /dev/null +++ b/src/main/java/org/xbib/jacc/util/BitSetInterator.java @@ -0,0 +1,44 @@ +package org.xbib.jacc.util; + +class BitSetInterator implements Interator { + + private int[] set; + private int pos; + private int mask; + private int num; + private int bitCount; + + BitSetInterator(int[] ai, int i) { + this.set = ai; + this.num = i; + this.pos = 0; + this.mask = 1; + this.bitCount = 0; + } + + private void advance() { + num++; + if (++bitCount == 32) { + pos++; + bitCount = 0; + mask = 1; + } else { + mask <<= 1; + } + } + + @Override + public int next() { + int i = num; + advance(); + return i; + } + + @Override + public boolean hasNext() { + while (pos < set.length && (set[pos] & mask) == 0) { + advance(); + } + return pos < set.length; + } +} diff --git a/src/main/java/org/xbib/jacc/util/ElemInterator.java b/src/main/java/org/xbib/jacc/util/ElemInterator.java index 719469a..315cbbf 100644 --- a/src/main/java/org/xbib/jacc/util/ElemInterator.java +++ b/src/main/java/org/xbib/jacc/util/ElemInterator.java @@ -3,7 +3,7 @@ package org.xbib.jacc.util; /** * */ -class ElemInterator extends Interator { +class ElemInterator implements Interator { private int count; private int limit; @@ -19,10 +19,12 @@ class ElemInterator extends Interator { this(ai, 0, ai.length); } + @Override public int next() { return a[count++]; } + @Override public boolean hasNext() { return count < limit; } diff --git a/src/main/java/org/xbib/jacc/util/IntSet.java b/src/main/java/org/xbib/jacc/util/IntSet.java index a8adc27..0cb65c7 100644 --- a/src/main/java/org/xbib/jacc/util/IntSet.java +++ b/src/main/java/org/xbib/jacc/util/IntSet.java @@ -115,11 +115,13 @@ public class IntSet { public void display(Writer writer) throws IOException { Interator interator1 = interator(); writer.write("{"); - for (int i = 0; interator1.hasNext(); i++) { + int i = 0; + while (interator1.hasNext()) { if (i != 0) { writer.write(", "); } writer.write(interator1.next()); + i++; } writer.write("}"); writer.write(": used = " + used + ", length = " + elems.length + "\n"); diff --git a/src/main/java/org/xbib/jacc/util/Interator.java b/src/main/java/org/xbib/jacc/util/Interator.java index 23c7f56..04a5d85 100644 --- a/src/main/java/org/xbib/jacc/util/Interator.java +++ b/src/main/java/org/xbib/jacc/util/Interator.java @@ -3,9 +3,9 @@ package org.xbib.jacc.util; /** * */ -public abstract class Interator { +public interface Interator { - public abstract int next(); + int next(); - public abstract boolean hasNext(); + boolean hasNext(); } diff --git a/src/main/java/org/xbib/jacc/util/SCC.java b/src/main/java/org/xbib/jacc/util/SCC.java index a5ba703..7a666e0 100644 --- a/src/main/java/org/xbib/jacc/util/SCC.java +++ b/src/main/java/org/xbib/jacc/util/SCC.java @@ -49,10 +49,12 @@ public class SCC { compNo = new int[i]; } + @Override void doneVisit(int i) { compNo[i] = numComps; } + @Override void doneTree() { numComps++; } @@ -76,6 +78,7 @@ public class SCC { } private static class ArrangeByFinish extends DepthFirst { + private int dfsNum; private int[] order; @@ -85,10 +88,16 @@ public class SCC { order = new int[dfsNum]; } + @Override void doneVisit(int i) { order[--dfsNum] = i; } + @Override + void doneTree() { + // do nothing + } + int[] getFinishOrder() { search(); return order; @@ -131,11 +140,9 @@ public class SCC { } } - void doneVisit(int i) { - } + abstract void doneVisit(int i); - void doneTree() { - } + abstract void doneTree(); } } diff --git a/src/main/java/org/xbib/jacc/util/SeqInterator.java b/src/main/java/org/xbib/jacc/util/SeqInterator.java index b1c3568..f460823 100644 --- a/src/main/java/org/xbib/jacc/util/SeqInterator.java +++ b/src/main/java/org/xbib/jacc/util/SeqInterator.java @@ -3,7 +3,7 @@ package org.xbib.jacc.util; /** * */ -class SeqInterator extends Interator { +class SeqInterator implements Interator { private int count; private int limit; @@ -13,10 +13,12 @@ class SeqInterator extends Interator { limit = j; } + @Override public int next() { return count++; } + @Override public boolean hasNext() { return count < limit; } diff --git a/src/site/resources/Calc.errs b/src/site/resources/Calc.errs new file mode 100644 index 0000000..ac27736 --- /dev/null +++ b/src/site/resources/Calc.errs @@ -0,0 +1,36 @@ +// This file contains some simple examples of +// errors diagnostics for Calc.jacc: + +"left operand is missing" + : '+' expr + | '-' expr + | '*' expr + | '/' expr + ; + +"unexpected closing parenthesis" + : expr ')' ; + +"unexpected opening parenthesis" + : expr '(' ; + +"right operand is missing" + : expr '+' + | expr '+' ')' + | expr '+' '+' + | expr '-' + | expr '-' ')' + | expr '*' + | expr '*' ')' + | expr '/' + | expr '/' ')' + ; + +"unnecessary semicolon after last expression (or missing expression)" + : prog ';' ; + +"empty parentheses" + : '(' ')' ; + +"missing expression" + : ';' ; diff --git a/src/site/resources/MoreCalc.errs b/src/site/resources/MoreCalc.errs new file mode 100644 index 0000000..fd73eb2 --- /dev/null +++ b/src/site/resources/MoreCalc.errs @@ -0,0 +1,7 @@ +"Unexpected opening parenthesis" + : ')' + ; + +"Missing operand" + : expr INTEGER + ; \ No newline at end of file diff --git a/src/test/java/org/xbib/jacc/JaccTest.java b/src/test/java/org/xbib/jacc/JaccTest.java new file mode 100644 index 0000000..a566260 --- /dev/null +++ b/src/test/java/org/xbib/jacc/JaccTest.java @@ -0,0 +1,73 @@ +package org.xbib.jacc; + +import org.junit.Ignore; +import org.junit.Test; +import org.xbib.jacc.helper.StreamMatcher; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + */ +public class JaccTest { + + @Test + public void calc() throws IOException { + Jacc jacc = new Jacc(); + jacc.setName("Calc"); + jacc.setInputStream(getResource("Calc.jacc")); + jacc.setErrorDiagnostics(getResource("Calc.errs")); + jacc.setDir("build/"); + jacc.setEnableVerboseMachineDescription(true); + jacc.execute(); + StreamMatcher.assertStream("CalcParser.java", + getResource("CalcParser.java"), + Files.newInputStream(Paths.get("build/CalcParser.java"))); + StreamMatcher.assertStream("CalcTokens.java", + getResource("CalcTokens.java"), + Files.newInputStream(Paths.get("build/CalcTokens.java"))); + StreamMatcher.assertStream("CalcParser.output", + getResource("CalcParser.output"), + Files.newInputStream(Paths.get("build/CalcParser.output"))); + } + + @Test + public void traceCalc() throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + Jacc jacc = new Jacc(); + jacc.setName("Calc"); + jacc.setInputStream(getResource("Calc.jacc")); + jacc.setParserInputs(getResource("example1")); + jacc.setEnableParserOutput(false); + jacc.setEnableTokenOutput(false); + jacc.setOutputStream(byteArrayOutputStream); + jacc.setDir("build/"); + jacc.execute(); + StreamMatcher.assertStream("example1.out", + getResource("example1.out"), + new ByteArrayInputStream(byteArrayOutputStream.toByteArray()) + ); + } + + @Test + public void simpleCalc() throws IOException { + Jacc jacc = new Jacc(); + jacc.setName("simpleCalc"); + jacc.setInputStream(getResource("simpleCalc.jacc")); + jacc.setMachineType(MachineType.SLR1); + jacc.setDir("build/"); + jacc.execute(); + StreamMatcher.assertStream("Calc.java", + getResource("Calc.java"), + Files.newInputStream(Paths.get("build/Calc.java"))); + } + + private InputStream getResource(String resource) throws IOException { + return getClass().getClassLoader().getResource("org/xbib/jacc/" + resource).openStream(); + } + +} diff --git a/src/test/java/org/xbib/jacc/helper/StreamMatcher.java b/src/test/java/org/xbib/jacc/helper/StreamMatcher.java new file mode 100644 index 0000000..5beb441 --- /dev/null +++ b/src/test/java/org/xbib/jacc/helper/StreamMatcher.java @@ -0,0 +1,76 @@ +/* + Copyright 2016 Jörg Prante + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ +package org.xbib.jacc.helper; + +import org.junit.Assert; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.charset.StandardCharsets; + +/** + * + */ +public class StreamMatcher extends Assert { + + public static void assertStream(String name, InputStream expected, String actual) throws IOException { + assertStream(name, expected, new ByteArrayInputStream(actual.getBytes(StandardCharsets.UTF_8))); + } + + public static void assertStream(String name, InputStream expected, InputStream actual) throws IOException { + int offset = 0; + ReadableByteChannel ch1 = Channels.newChannel(expected); + ReadableByteChannel ch2 = Channels.newChannel(actual); + ByteBuffer buf1 = ByteBuffer.allocateDirect(4096); + ByteBuffer buf2 = ByteBuffer.allocateDirect(4096); + try { + while (true) { + int n1 = ch1.read(buf1); + int n2 = ch2.read(buf2); + if (n1 == -1 || n2 == -1) { + if (n1 != n2) { + fail(name + ": stream length mismatch: " + n1 + " != " + n2 + " offset=" + offset); + } else { + return; + } + } + buf1.flip(); + buf2.flip(); + for (int i = 0; i < Math.min(n1, n2); i++) { + int b1 = buf1.get() & 0xFF; + int b2 = buf2.get() & 0xFF; + if (b1 != b2) { + fail(name + ": mismatch at offset " + (offset + i) + + " (" + Integer.toHexString(b1) + + " != " + Integer.toHexString(b2) + ")" + ); + } + } + buf1.compact(); + buf2.compact(); + offset += Math.min(n1, n2); + } + } finally { + expected.close(); + actual.close(); + } + } +} diff --git a/src/test/java/org/xbib/jacc/helper/package-info.java b/src/test/java/org/xbib/jacc/helper/package-info.java new file mode 100644 index 0000000..d19bfe8 --- /dev/null +++ b/src/test/java/org/xbib/jacc/helper/package-info.java @@ -0,0 +1,4 @@ +/** + * Helper classes for testing. + */ +package org.xbib.jacc.helper; diff --git a/src/test/java/org/xbib/jacc/package-info.java b/src/test/java/org/xbib/jacc/package-info.java new file mode 100644 index 0000000..f8f080f --- /dev/null +++ b/src/test/java/org/xbib/jacc/package-info.java @@ -0,0 +1,4 @@ +/** + * Classes for testing jacc. + */ +package org.xbib.jacc; diff --git a/src/test/resources/org/xbib/jacc/Calc.errs b/src/test/resources/org/xbib/jacc/Calc.errs new file mode 100644 index 0000000..ac27736 --- /dev/null +++ b/src/test/resources/org/xbib/jacc/Calc.errs @@ -0,0 +1,36 @@ +// This file contains some simple examples of +// errors diagnostics for Calc.jacc: + +"left operand is missing" + : '+' expr + | '-' expr + | '*' expr + | '/' expr + ; + +"unexpected closing parenthesis" + : expr ')' ; + +"unexpected opening parenthesis" + : expr '(' ; + +"right operand is missing" + : expr '+' + | expr '+' ')' + | expr '+' '+' + | expr '-' + | expr '-' ')' + | expr '*' + | expr '*' ')' + | expr '/' + | expr '/' ')' + ; + +"unnecessary semicolon after last expression (or missing expression)" + : prog ';' ; + +"empty parentheses" + : '(' ')' ; + +"missing expression" + : ';' ; diff --git a/src/test/resources/org/xbib/jacc/Calc.jacc b/src/test/resources/org/xbib/jacc/Calc.jacc new file mode 100644 index 0000000..4bcdacc --- /dev/null +++ b/src/test/resources/org/xbib/jacc/Calc.jacc @@ -0,0 +1,165 @@ +// To compile and run this program using jacc and Sun's JDK: +// +// In a directory containing only the file Calc.jacc: +// +// jacc Calc.jacc +// javac *.java +// java CalcParser +// ... enter arithmetic expressions ... hit EOF to terminate +// + + +%{ + abstract class Expr { + abstract int eval(); + } + + class IntExpr extends Expr { + private int value; + IntExpr(int value) { this.value = value; } + int eval() { return value; } + } + + abstract class BinExpr extends Expr { + protected Expr left, right; + BinExpr(Expr left, Expr right) { + this.left = left; this.right = right; + } + } + + class AddExpr extends BinExpr { + AddExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() + right.eval(); } + } + + class SubExpr extends BinExpr { + SubExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() - right.eval(); } + } + + class MulExpr extends BinExpr { + MulExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() * right.eval(); } + } + + class DivExpr extends BinExpr { + DivExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() / right.eval(); } + } + + class CalcLexer implements CalcTokens { + private int c = ' '; + + /** Read a single input character from standard input. + */ + private void nextChar() { + if (c>=0) { + try { + c = System.in.read(); + } catch (Exception e) { + c = (-1); + } + } + } + + private int token; + private IntExpr yylval; + + /** Read the next token and return the + * corresponding integer code. + */ + int nextToken() { + for (;;) { + // Skip whitespace + while (c==' ' || c=='\n' || c=='\t' || c=='\r') { + nextChar(); + } + if (c<0) { + return (token=ENDINPUT); + } + switch (c) { + case '+' : nextChar(); + return token='+'; + case '-' : nextChar(); + return token='-'; + case '*' : nextChar(); + return token='*'; + case '/' : nextChar(); + return token='/'; + case '(' : nextChar(); + return token='('; + case ')' : nextChar(); + return token=')'; + case ';' : nextChar(); + return token=';'; + default : if (Character.isDigit((char)c)) { + int n = 0; + do { + n = 10*n + (c - '0'); + nextChar(); + } while (Character.isDigit((char)c)); + yylval = new IntExpr(n); + return token=INTEGER; + } else { + Main.error("Illegal character "+c); + nextChar(); + } + } + } + } + + /** Return the token code for the current lexeme. + */ + int getToken() { + return token; + } + + /** Return the semantic value for the current lexeme. + */ + IntExpr getSemantic() { + return yylval; + } + } + + class Main { + public static void main(String[] args) { + CalcLexer lexer = new CalcLexer(); + lexer.nextToken(); + CalcParser parser = new CalcParser(lexer); + parser.parse(); + } + + static void error(String msg) { + System.out.println("ERROR: " + msg); + System.exit(1); + } + } +%} + +%semantic Expr +%token '+' '-' '*' '/' '(' ')' ';' INTEGER +%left '+' '-' +%left '*' '/' + +%% + +prog : prog ';' expr { System.out.println($3.eval()); } + | expr { System.out.println($1.eval()); } + ; +expr : expr '+' expr { $$ = new AddExpr($1, $3); } + | expr '-' expr { $$ = new SubExpr($1, $3); } + | expr '*' expr { $$ = new MulExpr($1, $3); } + | expr '/' expr { $$ = new DivExpr($1, $3); } + | '(' expr ')' { $$ = $2; } + | INTEGER { $$ = $1; } + ; + +%% + private CalcLexer lexer; + + CalcParser(CalcLexer lexer) { this.lexer = lexer; } + + private void yyerror(String msg) { + Main.error(yyerrno<0 ? msg : yyerrmsgs[yyerrno]); + } + diff --git a/src/test/resources/org/xbib/jacc/Calc.java b/src/test/resources/org/xbib/jacc/Calc.java new file mode 100644 index 0000000..958cc0d --- /dev/null +++ b/src/test/resources/org/xbib/jacc/Calc.java @@ -0,0 +1,536 @@ +// Output created by jacc 2.1.0 + +public class Calc implements CalcTokens { + private int yyss = 100; + private int yytok; + private int yysp = 0; + private int[] yyst; + protected int yyerrno = (-1); + private int[] yysv; + private int yyrv; + + public boolean parse() { + int yyn = 0; + yysp = 0; + yyst = new int[yyss]; + yysv = new int[yyss]; + yytok = (token + ); + loop: + for (;;) { + switch (yyn) { + case 0: + yyst[yysp] = 0; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 17: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 1: + yyst[yysp] = 1; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 18: + switch (yytok) { + case ENDINPUT: + yyn = 34; + continue; + case ';': + yyn = 5; + continue; + } + yyn = 37; + continue; + + case 2: + yyst[yysp] = 2; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 19: + yyn = yys2(); + continue; + + case 3: + yyst[yysp] = 3; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 20: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr8(); + continue; + + case 4: + yyst[yysp] = 4; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 21: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 5: + yyst[yysp] = 5; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 22: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 6: + yyst[yysp] = 6; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 23: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 7: + yyst[yysp] = 7; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 24: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 8: + yyst[yysp] = 8; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 25: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 9: + yyst[yysp] = 9; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 26: + switch (yytok) { + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 10: + yyst[yysp] = 10; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 27: + switch (yytok) { + case '*': + yyn = 6; + continue; + case '+': + yyn = 7; + continue; + case '-': + yyn = 8; + continue; + case '/': + yyn = 9; + continue; + case ')': + yyn = 16; + continue; + } + yyn = 37; + continue; + + case 11: + yyst[yysp] = 11; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 28: + yyn = yys11(); + continue; + + case 12: + yyst[yysp] = 12; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 29: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr5(); + continue; + + case 13: + yyst[yysp] = 13; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 30: + switch (yytok) { + case '(': + case INTEGER: + case error: + yyn = 37; + continue; + case '*': + yyn = 6; + continue; + case '/': + yyn = 9; + continue; + } + yyn = yyr3(); + continue; + + case 14: + yyst[yysp] = 14; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 31: + switch (yytok) { + case '(': + case INTEGER: + case error: + yyn = 37; + continue; + case '*': + yyn = 6; + continue; + case '/': + yyn = 9; + continue; + } + yyn = yyr4(); + continue; + + case 15: + yyst[yysp] = 15; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 32: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr6(); + continue; + + case 16: + yyst[yysp] = 16; + yysv[yysp] = (yylval + ); + yytok = (yylex() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 33: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr7(); + continue; + + case 34: + return true; + case 35: + yyerror("stack overflow"); + case 36: + return false; + case 37: + yyerror("syntax error"); + return false; + } + } + } + + protected void yyexpand() { + int[] newyyst = new int[2*yyst.length]; + int[] newyysv = new int[2*yyst.length]; + for (int i=0; i=0) { + try { + c = System.in.read(); + } catch (Exception e) { + c = (-1); + } + } + } + + int token; + int yylval; + + /** Read the next token and return the + * corresponding integer code. + */ + int yylex() { + for (;;) { + // Skip whitespace + while (c==' ' || c=='\n' || c=='\t' || c=='\r') { + nextChar(); + } + if (c<0) { + return (token=ENDINPUT); + } + switch (c) { + case '+' : nextChar(); + return token='+'; + case '-' : nextChar(); + return token='-'; + case '*' : nextChar(); + return token='*'; + case '/' : nextChar(); + return token='/'; + case '(' : nextChar(); + return token='('; + case ')' : nextChar(); + return token=')'; + case ';' : nextChar(); + return token=';'; + default : if (Character.isDigit((char)c)) { + int n = 0; + do { + n = 10*n + (c - '0'); + nextChar(); + } while (Character.isDigit((char)c)); + yylval = n; + return token=INTEGER; + } else { + yyerror("Illegal character "+c); + nextChar(); + } + } + } + } + + public static void main(String[] args) { + Calc calc = new Calc(); + calc.nextChar(); // prime the character input stream + calc.yylex(); // prime the token input stream + calc.parse(); // parse the input + } + +} diff --git a/src/test/resources/org/xbib/jacc/CalcParser.java b/src/test/resources/org/xbib/jacc/CalcParser.java new file mode 100644 index 0000000..1bdda29 --- /dev/null +++ b/src/test/resources/org/xbib/jacc/CalcParser.java @@ -0,0 +1,644 @@ +// Output created by jacc 2.1.0 + + abstract class Expr { + abstract int eval(); + } + + class IntExpr extends Expr { + private int value; + IntExpr(int value) { this.value = value; } + int eval() { return value; } + } + + abstract class BinExpr extends Expr { + protected Expr left, right; + BinExpr(Expr left, Expr right) { + this.left = left; this.right = right; + } + } + + class AddExpr extends BinExpr { + AddExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() + right.eval(); } + } + + class SubExpr extends BinExpr { + SubExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() - right.eval(); } + } + + class MulExpr extends BinExpr { + MulExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() * right.eval(); } + } + + class DivExpr extends BinExpr { + DivExpr(Expr left, Expr right) { super(left, right); } + int eval() { return left.eval() / right.eval(); } + } + + class CalcLexer implements CalcTokens { + private int c = ' '; + + /** Read a single input character from standard input. + */ + private void nextChar() { + if (c>=0) { + try { + c = System.in.read(); + } catch (Exception e) { + c = (-1); + } + } + } + + private int token; + private IntExpr yylval; + + /** Read the next token and return the + * corresponding integer code. + */ + int nextToken() { + for (;;) { + // Skip whitespace + while (c==' ' || c=='\n' || c=='\t' || c=='\r') { + nextChar(); + } + if (c<0) { + return (token=ENDINPUT); + } + switch (c) { + case '+' : nextChar(); + return token='+'; + case '-' : nextChar(); + return token='-'; + case '*' : nextChar(); + return token='*'; + case '/' : nextChar(); + return token='/'; + case '(' : nextChar(); + return token='('; + case ')' : nextChar(); + return token=')'; + case ';' : nextChar(); + return token=';'; + default : if (Character.isDigit((char)c)) { + int n = 0; + do { + n = 10*n + (c - '0'); + nextChar(); + } while (Character.isDigit((char)c)); + yylval = new IntExpr(n); + return token=INTEGER; + } else { + Main.error("Illegal character "+c); + nextChar(); + } + } + } + } + + /** Return the token code for the current lexeme. + */ + int getToken() { + return token; + } + + /** Return the semantic value for the current lexeme. + */ + IntExpr getSemantic() { + return yylval; + } + } + + class Main { + public static void main(String[] args) { + CalcLexer lexer = new CalcLexer(); + lexer.nextToken(); + CalcParser parser = new CalcParser(lexer); + parser.parse(); + } + + static void error(String msg) { + System.out.println("ERROR: " + msg); + System.exit(1); + } + } + +public class CalcParser implements CalcTokens { + private int yyss = 100; + private int yytok; + private int yysp = 0; + private int[] yyst; + protected int yyerrno = (-1); + private Expr[] yysv; + private Expr yyrv; + + public boolean parse() { + int yyn = 0; + yysp = 0; + yyst = new int[yyss]; + yyerrno = (-1); + yysv = new Expr[yyss]; + yytok = (lexer.getToken() + ); + loop: + for (;;) { + switch (yyn) { + case 0: + yyst[yysp] = 0; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 17: + yyn = yys0(); + continue; + + case 1: + yyst[yysp] = 1; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 18: + switch (yytok) { + case ENDINPUT: + yyn = 34; + continue; + case ';': + yyn = 5; + continue; + } + yyn = 37; + continue; + + case 2: + yyst[yysp] = 2; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 19: + yyn = yys2(); + continue; + + case 3: + yyst[yysp] = 3; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 20: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr8(); + continue; + + case 4: + yyst[yysp] = 4; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 21: + switch (yytok) { + case ')': + yyn = yyerr(5, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 5: + yyst[yysp] = 5; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 22: + switch (yytok) { + case ENDINPUT: + yyn = yyerr(4, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 6: + yyst[yysp] = 6; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 23: + switch (yytok) { + case ENDINPUT: + case ')': + yyn = yyerr(3, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 7: + yyst[yysp] = 7; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 24: + switch (yytok) { + case '+': + case ENDINPUT: + case ')': + yyn = yyerr(3, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 8: + yyst[yysp] = 8; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 25: + switch (yytok) { + case ENDINPUT: + case ')': + yyn = yyerr(3, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 9: + yyst[yysp] = 9; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 26: + switch (yytok) { + case ENDINPUT: + case ')': + yyn = yyerr(3, 37); + continue; + case INTEGER: + yyn = 3; + continue; + case '(': + yyn = 4; + continue; + } + yyn = 37; + continue; + + case 10: + yyst[yysp] = 10; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 27: + switch (yytok) { + case '*': + yyn = 6; + continue; + case '+': + yyn = 7; + continue; + case '-': + yyn = 8; + continue; + case '/': + yyn = 9; + continue; + case ')': + yyn = 16; + continue; + } + yyn = 37; + continue; + + case 11: + yyst[yysp] = 11; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 28: + yyn = yys11(); + continue; + + case 12: + yyst[yysp] = 12; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 29: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr5(); + continue; + + case 13: + yyst[yysp] = 13; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 30: + switch (yytok) { + case '(': + case INTEGER: + case error: + yyn = 37; + continue; + case '*': + yyn = 6; + continue; + case '/': + yyn = 9; + continue; + } + yyn = yyr3(); + continue; + + case 14: + yyst[yysp] = 14; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 31: + switch (yytok) { + case '(': + case INTEGER: + case error: + yyn = 37; + continue; + case '*': + yyn = 6; + continue; + case '/': + yyn = 9; + continue; + } + yyn = yyr4(); + continue; + + case 15: + yyst[yysp] = 15; + if (++yysp>=yyst.length) { + yyexpand(); + } + case 32: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr6(); + continue; + + case 16: + yyst[yysp] = 16; + yysv[yysp] = (lexer.getSemantic() + ); + yytok = (lexer.nextToken() + ); + if (++yysp>=yyst.length) { + yyexpand(); + } + case 33: + switch (yytok) { + case '(': + case error: + case INTEGER: + yyn = 37; + continue; + } + yyn = yyr7(); + continue; + + case 34: + return true; + case 35: + yyerror("stack overflow"); + case 36: + return false; + case 37: + yyerror("syntax error"); + return false; + } + } + } + + protected void yyexpand() { + int[] newyyst = new int[2*yyst.length]; + Expr[] newyysv = new Expr[2*yyst.length]; + for (int i=0; i=0) { + try { + c = System.in.read(); + } catch (Exception e) { + c = (-1); + } + } + } + + int token; + int yylval; + + /** Read the next token and return the + * corresponding integer code. + */ + int yylex() { + for (;;) { + // Skip whitespace + while (c==' ' || c=='\n' || c=='\t' || c=='\r') { + nextChar(); + } + if (c<0) { + return (token=ENDINPUT); + } + switch (c) { + case '+' : nextChar(); + return token='+'; + case '-' : nextChar(); + return token='-'; + case '*' : nextChar(); + return token='*'; + case '/' : nextChar(); + return token='/'; + case '(' : nextChar(); + return token='('; + case ')' : nextChar(); + return token=')'; + case ';' : nextChar(); + return token=';'; + default : if (Character.isDigit((char)c)) { + int n = 0; + do { + n = 10*n + (c - '0'); + nextChar(); + } while (Character.isDigit((char)c)); + yylval = n; + return token=INTEGER; + } else { + yyerror("Illegal character "+c); + nextChar(); + } + } + } + } + + public static void main(String[] args) { + Calc calc = new Calc(); + calc.nextChar(); // prime the character input stream + calc.yylex(); // prime the token input stream + calc.parse(); // parse the input + }