fixes for sonarqube
This commit is contained in:
parent
85bcb906ed
commit
a00c9708a8
61 changed files with 2838 additions and 719 deletions
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ class Fixity {
|
|||
return obj instanceof Fixity && equalsFixity((Fixity) obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return assoc ^ prec;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
11
src/main/java/org/xbib/jacc/JaccException.java
Normal file
11
src/main/java/org/xbib/jacc/JaccException.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package org.xbib.jacc;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JaccException extends Exception {
|
||||
|
||||
public JaccException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
7
src/main/java/org/xbib/jacc/MachineType.java
Normal file
7
src/main/java/org/xbib/jacc/MachineType.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package org.xbib.jacc;
|
||||
|
||||
/**
|
||||
*/
|
||||
public enum MachineType {
|
||||
LR0, SLR1, LALR1
|
||||
}
|
|
@ -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<yyst.length; i++) {",
|
||||
" newyyst[i] = yyst[i];",
|
||||
|
@ -198,7 +202,7 @@ class ParserOutput extends Output {
|
|||
indent(writer, i, "}");
|
||||
writer.write("\n");
|
||||
indent(writer, i, "public void yyclearin() {");
|
||||
indent(writer, i + 1, "yytok = (" + settings.getNextToken());
|
||||
indent(writer, i + 1, "yytok = (" + jaccSettings.getNextToken());
|
||||
indent(writer, i + 1, " );");
|
||||
indent(writer, i, "}");
|
||||
writer.write("\n");
|
||||
|
@ -216,8 +220,8 @@ class ParserOutput extends Output {
|
|||
if (errMsgs) {
|
||||
indent(writer, i + 1, "yyerrno = (-1);");
|
||||
}
|
||||
indent(writer, i + 1, "yysv = new " + settings.getTypeName() + "[yyss];");
|
||||
indent(writer, i + 1, "yytok = (" + settings.getGetToken());
|
||||
indent(writer, i + 1, "yysv = new " + jaccSettings.getTypeName() + "[yyss];");
|
||||
indent(writer, i + 1, "yytok = (" + jaccSettings.getGetToken());
|
||||
indent(writer, i + 1, " );");
|
||||
indent(writer, i, new String[]{
|
||||
"loop:", " for (;;) {", " switch (yyn) {"
|
||||
|
@ -243,9 +247,9 @@ class ParserOutput extends Output {
|
|||
indent(writer, i, "case " + j + ":");
|
||||
indent(writer, i + 1, "yyst[yysp] = " + j + ";");
|
||||
if (grammar.isTerminal(machine.getEntry(j))) {
|
||||
indent(writer, i + 1, "yysv[yysp] = (" + settings.getGetSemantic());
|
||||
indent(writer, i + 1, "yysv[yysp] = (" + jaccSettings.getGetSemantic());
|
||||
indent(writer, i + 1, " );");
|
||||
indent(writer, i + 1, "yytok = (" + settings.getNextToken());
|
||||
indent(writer, i + 1, "yytok = (" + jaccSettings.getNextToken());
|
||||
indent(writer, i + 1, " );");
|
||||
if (errUsed) {
|
||||
indent(writer, i + 1, "yyerrstatus++;");
|
||||
|
@ -287,7 +291,7 @@ class ParserOutput extends Output {
|
|||
int k = tables.getDefaultRowAt(j);
|
||||
if (stNumSwitches[j] > 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];");
|
||||
|
|
|
@ -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(" : ");
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(", ");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(" ...");
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
44
src/main/java/org/xbib/jacc/util/BitSetInterator.java
Normal file
44
src/main/java/org/xbib/jacc/util/BitSetInterator.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
36
src/site/resources/Calc.errs
Normal file
36
src/site/resources/Calc.errs
Normal file
|
@ -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"
|
||||
: ';' ;
|
7
src/site/resources/MoreCalc.errs
Normal file
7
src/site/resources/MoreCalc.errs
Normal file
|
@ -0,0 +1,7 @@
|
|||
"Unexpected opening parenthesis"
|
||||
: ')'
|
||||
;
|
||||
|
||||
"Missing operand"
|
||||
: expr INTEGER
|
||||
;
|
73
src/test/java/org/xbib/jacc/JaccTest.java
Normal file
73
src/test/java/org/xbib/jacc/JaccTest.java
Normal file
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
76
src/test/java/org/xbib/jacc/helper/StreamMatcher.java
Normal file
76
src/test/java/org/xbib/jacc/helper/StreamMatcher.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
4
src/test/java/org/xbib/jacc/helper/package-info.java
Normal file
4
src/test/java/org/xbib/jacc/helper/package-info.java
Normal file
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Helper classes for testing.
|
||||
*/
|
||||
package org.xbib.jacc.helper;
|
4
src/test/java/org/xbib/jacc/package-info.java
Normal file
4
src/test/java/org/xbib/jacc/package-info.java
Normal file
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Classes for testing jacc.
|
||||
*/
|
||||
package org.xbib.jacc;
|
36
src/test/resources/org/xbib/jacc/Calc.errs
Normal file
36
src/test/resources/org/xbib/jacc/Calc.errs
Normal file
|
@ -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"
|
||||
: ';' ;
|
165
src/test/resources/org/xbib/jacc/Calc.jacc
Normal file
165
src/test/resources/org/xbib/jacc/Calc.jacc
Normal file
|
@ -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]);
|
||||
}
|
||||
|
536
src/test/resources/org/xbib/jacc/Calc.java
Normal file
536
src/test/resources/org/xbib/jacc/Calc.java
Normal file
|
@ -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<yyst.length; i++) {
|
||||
newyyst[i] = yyst[i];
|
||||
newyysv[i] = yysv[i];
|
||||
}
|
||||
yyst = newyyst;
|
||||
yysv = newyysv;
|
||||
}
|
||||
|
||||
private int yys2() {
|
||||
switch (yytok) {
|
||||
case '*':
|
||||
return 6;
|
||||
case '+':
|
||||
return 7;
|
||||
case '-':
|
||||
return 8;
|
||||
case '/':
|
||||
return 9;
|
||||
case ENDINPUT:
|
||||
case ';':
|
||||
return yyr2();
|
||||
}
|
||||
return 37;
|
||||
}
|
||||
|
||||
private int yys11() {
|
||||
switch (yytok) {
|
||||
case '*':
|
||||
return 6;
|
||||
case '+':
|
||||
return 7;
|
||||
case '-':
|
||||
return 8;
|
||||
case '/':
|
||||
return 9;
|
||||
case ENDINPUT:
|
||||
case ';':
|
||||
return yyr1();
|
||||
}
|
||||
return 37;
|
||||
}
|
||||
|
||||
private int yyr1() { // prog : prog ';' expr
|
||||
{ System.out.println(yysv[yysp-1]); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int yyr2() { // prog : expr
|
||||
{ System.out.println(yysv[yysp-1]); }
|
||||
yysv[yysp-=1] = yyrv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int yyr3() { // expr : expr '+' expr
|
||||
{ yyrv = yysv[yysp-3] + yysv[yysp-1]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr4() { // expr : expr '-' expr
|
||||
{ yyrv = yysv[yysp-3] - yysv[yysp-1]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr5() { // expr : expr '*' expr
|
||||
{ yyrv = yysv[yysp-3] * yysv[yysp-1]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr6() { // expr : expr '/' expr
|
||||
{ yyrv = yysv[yysp-3] / yysv[yysp-1]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr7() { // expr : '(' expr ')'
|
||||
{ yyrv = yysv[yysp-2]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr8() { // expr : INTEGER
|
||||
{ yyrv = yysv[yysp-1]; }
|
||||
yysv[yysp-=1] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yypexpr() {
|
||||
switch (yyst[yysp-1]) {
|
||||
case 8: return 14;
|
||||
case 7: return 13;
|
||||
case 6: return 12;
|
||||
case 5: return 11;
|
||||
case 4: return 10;
|
||||
case 0: return 2;
|
||||
default: return 15;
|
||||
}
|
||||
}
|
||||
|
||||
protected String[] yyerrmsgs = {
|
||||
};
|
||||
|
||||
|
||||
private void yyerror(String msg) {
|
||||
System.out.println("ERROR: " + msg);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
644
src/test/resources/org/xbib/jacc/CalcParser.java
Normal file
644
src/test/resources/org/xbib/jacc/CalcParser.java
Normal file
|
@ -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<yyst.length; i++) {
|
||||
newyyst[i] = yyst[i];
|
||||
newyysv[i] = yysv[i];
|
||||
}
|
||||
yyst = newyyst;
|
||||
yysv = newyysv;
|
||||
}
|
||||
|
||||
private int yys0() {
|
||||
switch (yytok) {
|
||||
case ENDINPUT:
|
||||
case error:
|
||||
case ')':
|
||||
return 37;
|
||||
case ';':
|
||||
return yyerr(6, 37);
|
||||
case INTEGER:
|
||||
return 3;
|
||||
case '(':
|
||||
return 4;
|
||||
}
|
||||
return yyerr(0, 37);
|
||||
}
|
||||
|
||||
private int yys2() {
|
||||
switch (yytok) {
|
||||
case ')':
|
||||
return yyerr(1, 37);
|
||||
case '(':
|
||||
return yyerr(2, 37);
|
||||
case '*':
|
||||
return 6;
|
||||
case '+':
|
||||
return 7;
|
||||
case '-':
|
||||
return 8;
|
||||
case '/':
|
||||
return 9;
|
||||
case ENDINPUT:
|
||||
case ';':
|
||||
return yyr2();
|
||||
}
|
||||
return 37;
|
||||
}
|
||||
|
||||
private int yys11() {
|
||||
switch (yytok) {
|
||||
case '*':
|
||||
return 6;
|
||||
case '+':
|
||||
return 7;
|
||||
case '-':
|
||||
return 8;
|
||||
case '/':
|
||||
return 9;
|
||||
case ENDINPUT:
|
||||
case ';':
|
||||
return yyr1();
|
||||
}
|
||||
return 37;
|
||||
}
|
||||
|
||||
private int yyr1() { // prog : prog ';' expr
|
||||
{ System.out.println(yysv[yysp-1].eval()); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int yyr2() { // prog : expr
|
||||
{ System.out.println(yysv[yysp-1].eval()); }
|
||||
yysv[yysp-=1] = yyrv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int yyr3() { // expr : expr '+' expr
|
||||
{ yyrv = new AddExpr(yysv[yysp-3], yysv[yysp-1]); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr4() { // expr : expr '-' expr
|
||||
{ yyrv = new SubExpr(yysv[yysp-3], yysv[yysp-1]); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr5() { // expr : expr '*' expr
|
||||
{ yyrv = new MulExpr(yysv[yysp-3], yysv[yysp-1]); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr6() { // expr : expr '/' expr
|
||||
{ yyrv = new DivExpr(yysv[yysp-3], yysv[yysp-1]); }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr7() { // expr : '(' expr ')'
|
||||
{ yyrv = yysv[yysp-2]; }
|
||||
yysv[yysp-=3] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yyr8() { // expr : INTEGER
|
||||
{ yyrv = yysv[yysp-1]; }
|
||||
yysv[yysp-=1] = yyrv;
|
||||
return yypexpr();
|
||||
}
|
||||
|
||||
private int yypexpr() {
|
||||
switch (yyst[yysp-1]) {
|
||||
case 8: return 14;
|
||||
case 7: return 13;
|
||||
case 6: return 12;
|
||||
case 5: return 11;
|
||||
case 4: return 10;
|
||||
case 0: return 2;
|
||||
default: return 15;
|
||||
}
|
||||
}
|
||||
|
||||
private int yyerr(int e, int n) {
|
||||
yyerrno = e;
|
||||
return n;
|
||||
}
|
||||
protected String[] yyerrmsgs = {
|
||||
"left operand is missing",
|
||||
"unexpected closing parenthesis",
|
||||
"unexpected opening parenthesis",
|
||||
"right operand is missing",
|
||||
"unnecessary semicolon after last expression (or missing expression)",
|
||||
"empty parentheses",
|
||||
"missing expression"
|
||||
};
|
||||
|
||||
private CalcLexer lexer;
|
||||
|
||||
CalcParser(CalcLexer lexer) { this.lexer = lexer; }
|
||||
|
||||
private void yyerror(String msg) {
|
||||
Main.error(yyerrno<0 ? msg : yyerrmsgs[yyerrno]);
|
||||
}
|
||||
|
||||
|
||||
}
|
203
src/test/resources/org/xbib/jacc/CalcParser.output
Normal file
203
src/test/resources/org/xbib/jacc/CalcParser.output
Normal file
|
@ -0,0 +1,203 @@
|
|||
// Output created by jacc 2.1.0
|
||||
state 0 (entry on prog)
|
||||
$accept : _prog $end
|
||||
|
||||
$end error
|
||||
error error
|
||||
')' error
|
||||
';' error "missing expression"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error "left operand is missing"
|
||||
|
||||
prog goto 1
|
||||
expr goto 2
|
||||
|
||||
state 1 (entry on prog)
|
||||
$accept : prog_$end
|
||||
prog : prog_';' expr (1)
|
||||
|
||||
$end accept
|
||||
';' shift 5
|
||||
. error
|
||||
|
||||
state 2 (entry on expr)
|
||||
prog : expr_ (2)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
|
||||
')' error "unexpected closing parenthesis"
|
||||
'(' error "unexpected opening parenthesis"
|
||||
'*' shift 6
|
||||
'+' shift 7
|
||||
'-' shift 8
|
||||
'/' shift 9
|
||||
$end reduce 2
|
||||
';' reduce 2
|
||||
. error
|
||||
|
||||
state 3 (entry on INTEGER)
|
||||
expr : INTEGER_ (8)
|
||||
|
||||
'(' error
|
||||
error error
|
||||
INTEGER error
|
||||
. reduce 8
|
||||
|
||||
state 4 (entry on '(')
|
||||
expr : '('_expr ')' (7)
|
||||
|
||||
')' error "empty parentheses"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 10
|
||||
|
||||
state 5 (entry on ';')
|
||||
prog : prog ';'_expr (1)
|
||||
|
||||
$end error "unnecessary semicolon after last expression (or missing expression)"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 11
|
||||
|
||||
state 6 (entry on '*')
|
||||
expr : expr '*'_expr (5)
|
||||
|
||||
$end error "right operand is missing"
|
||||
')' error "right operand is missing"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 12
|
||||
|
||||
state 7 (entry on '+')
|
||||
expr : expr '+'_expr (3)
|
||||
|
||||
'+' error "right operand is missing"
|
||||
$end error "right operand is missing"
|
||||
')' error "right operand is missing"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 13
|
||||
|
||||
state 8 (entry on '-')
|
||||
expr : expr '-'_expr (4)
|
||||
|
||||
$end error "right operand is missing"
|
||||
')' error "right operand is missing"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 14
|
||||
|
||||
state 9 (entry on '/')
|
||||
expr : expr '/'_expr (6)
|
||||
|
||||
$end error "right operand is missing"
|
||||
')' error "right operand is missing"
|
||||
INTEGER shift 3
|
||||
'(' shift 4
|
||||
. error
|
||||
|
||||
expr goto 15
|
||||
|
||||
state 10 (entry on expr)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
expr : '(' expr_')' (7)
|
||||
|
||||
'*' shift 6
|
||||
'+' shift 7
|
||||
'-' shift 8
|
||||
'/' shift 9
|
||||
')' shift 16
|
||||
. error
|
||||
|
||||
state 11 (entry on expr)
|
||||
prog : prog ';' expr_ (1)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
|
||||
'*' shift 6
|
||||
'+' shift 7
|
||||
'-' shift 8
|
||||
'/' shift 9
|
||||
$end reduce 1
|
||||
';' reduce 1
|
||||
. error
|
||||
|
||||
state 12 (entry on expr)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr '*' expr_ (5)
|
||||
expr : expr_'/' expr (6)
|
||||
|
||||
'(' error
|
||||
error error
|
||||
INTEGER error
|
||||
. reduce 5
|
||||
|
||||
state 13 (entry on expr)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr '+' expr_ (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
|
||||
'(' error
|
||||
INTEGER error
|
||||
error error
|
||||
'*' shift 6
|
||||
'/' shift 9
|
||||
. reduce 3
|
||||
|
||||
state 14 (entry on expr)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr '-' expr_ (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
|
||||
'(' error
|
||||
INTEGER error
|
||||
error error
|
||||
'*' shift 6
|
||||
'/' shift 9
|
||||
. reduce 4
|
||||
|
||||
state 15 (entry on expr)
|
||||
expr : expr_'+' expr (3)
|
||||
expr : expr_'-' expr (4)
|
||||
expr : expr_'*' expr (5)
|
||||
expr : expr_'/' expr (6)
|
||||
expr : expr '/' expr_ (6)
|
||||
|
||||
'(' error
|
||||
error error
|
||||
INTEGER error
|
||||
. reduce 6
|
||||
|
||||
state 16 (entry on ')')
|
||||
expr : '(' expr ')'_ (7)
|
||||
|
||||
'(' error
|
||||
error error
|
||||
INTEGER error
|
||||
. reduce 7
|
||||
|
||||
10 terminals, 2 nonterminals;8 grammar rules, 17 states;0 shift/reduce and 0 reduce/reduce conflicts reported.
|
13
src/test/resources/org/xbib/jacc/CalcTokens.java
Normal file
13
src/test/resources/org/xbib/jacc/CalcTokens.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Output created by jacc 2.1.0
|
||||
interface CalcTokens {
|
||||
int ENDINPUT = 0;
|
||||
int INTEGER = 1;
|
||||
int error = 2;
|
||||
// '(' (code=40)
|
||||
// ')' (code=41)
|
||||
// '*' (code=42)
|
||||
// '+' (code=43)
|
||||
// '-' (code=45)
|
||||
// '/' (code=47)
|
||||
// ';' (code=59)
|
||||
}
|
4
src/test/resources/org/xbib/jacc/example1
Normal file
4
src/test/resources/org/xbib/jacc/example1
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
INTEGER '+' INTEGER '*' INTEGER ';'
|
||||
INTEGER '*' INTEGER '+' INTEGER
|
||||
|
38
src/test/resources/org/xbib/jacc/example1.out
Normal file
38
src/test/resources/org/xbib/jacc/example1.out
Normal file
|
@ -0,0 +1,38 @@
|
|||
Running example from input stream
|
||||
start : _ INTEGER ...
|
||||
shift : INTEGER _ '+' ...
|
||||
reduce : _ expr '+' ...
|
||||
goto : expr _ '+' ...
|
||||
shift : expr '+' _ INTEGER ...
|
||||
shift : expr '+' INTEGER _ '*' ...
|
||||
reduce : expr '+' _ expr '*' ...
|
||||
goto : expr '+' expr _ '*' ...
|
||||
shift : expr '+' expr '*' _ INTEGER ...
|
||||
shift : expr '+' expr '*' INTEGER _ ';' ...
|
||||
reduce : expr '+' expr '*' _ expr ';' ...
|
||||
goto : expr '+' expr '*' expr _ ';' ...
|
||||
reduce : expr '+' _ expr ';' ...
|
||||
goto : expr '+' expr _ ';' ...
|
||||
reduce : _ expr ';' ...
|
||||
goto : expr _ ';' ...
|
||||
reduce : _ prog ';' ...
|
||||
goto : prog _ ';' ...
|
||||
shift : prog ';' _ INTEGER ...
|
||||
shift : prog ';' INTEGER _ '*' ...
|
||||
reduce : prog ';' _ expr '*' ...
|
||||
goto : prog ';' expr _ '*' ...
|
||||
shift : prog ';' expr '*' _ INTEGER ...
|
||||
shift : prog ';' expr '*' INTEGER _ '+' ...
|
||||
reduce : prog ';' expr '*' _ expr '+' ...
|
||||
goto : prog ';' expr '*' expr _ '+' ...
|
||||
reduce : prog ';' _ expr '+' ...
|
||||
goto : prog ';' expr _ '+' ...
|
||||
shift : prog ';' expr '+' _ INTEGER ...
|
||||
shift : prog ';' expr '+' INTEGER _
|
||||
reduce : prog ';' expr '+' _ expr $end
|
||||
goto : prog ';' expr '+' expr _ $end
|
||||
reduce : prog ';' _ expr $end
|
||||
goto : prog ';' expr _ $end
|
||||
reduce : _ prog $end
|
||||
goto : prog _ $end
|
||||
Accept!
|
104
src/test/resources/org/xbib/jacc/simpleCalc.jacc
Normal file
104
src/test/resources/org/xbib/jacc/simpleCalc.jacc
Normal file
|
@ -0,0 +1,104 @@
|
|||
// To compile and run this program using jacc and Sun's JDK:
|
||||
//
|
||||
// jacc simpleCalc.jacc
|
||||
// javac Calc.java CalcTokens.java
|
||||
// java Calc
|
||||
// ... enter arithmetic expressions ... hit EOF to terminate
|
||||
//
|
||||
|
||||
%class Calc
|
||||
%interface CalcTokens
|
||||
%semantic int : yylval
|
||||
%get token
|
||||
%next yylex()
|
||||
|
||||
%token '+' '-' '*' '/' '(' ')' ';' INTEGER
|
||||
%left '+' '-'
|
||||
%left '*' '/'
|
||||
|
||||
%%
|
||||
|
||||
prog : prog ';' expr { System.out.println($3); }
|
||||
| expr { System.out.println($1); }
|
||||
;
|
||||
expr : expr '+' expr { $$ = $1 + $3; }
|
||||
| expr '-' expr { $$ = $1 - $3; }
|
||||
| expr '*' expr { $$ = $1 * $3; }
|
||||
| expr '/' expr { $$ = $1 / $3; }
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
| INTEGER { $$ = $1; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
private void yyerror(String msg) {
|
||||
System.out.println("ERROR: " + msg);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
Loading…
Reference in a new issue