fixes for sonarqube

This commit is contained in:
Jörg Prante 2016-10-25 22:27:05 +02:00
parent 85bcb906ed
commit a00c9708a8
61 changed files with 2838 additions and 719 deletions

View file

@ -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'

View file

@ -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'
}
}
}

View file

@ -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"

View file

@ -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();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
return;
}
writer = new OutputStreamWriter(new FileOutputStream(s), StandardCharsets.UTF_8);
try (Writer writer = new OutputStreamWriter(new FileOutputStream(s), StandardCharsets.UTF_8)) {
write(writer);
} catch (IOException ioexception) {
report(new Failure("Cannot write to file \"" + s + "\""));
}
if (writer != null) {
writer.close();
}
}

View file

@ -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 "";
}

View file

@ -52,6 +52,7 @@ class Fixity {
return obj instanceof Fixity && equalsFixity((Fixity) obj);
}
@Override
public int hashCode() {
return assoc ^ prec;
}

View file

@ -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 (jacc.getInputStream() == null) {
usage("No input file(s) specified");
} else {
jacc.execute();
}
}
if (namelist == null) {
usage("No input file(s) specified");
public void execute() throws IOException {
Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
ConsoleHandler consoleHandler = new ConsoleHandler();
if (dir == null) {
dir = ".";
}
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);
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 (simplehandler.getNumFailures() > 0) {
return;
if (consoleHandler.getNumFailures() == 0) {
if (enableParserOutput) {
(new ParserOutput(consoleHandler, job)).write(dir + jaccSettings.getClassName() + ".java");
}
if (flag) {
(new ParserOutput(simplehandler, job)).write(dir + settings.getClassName() + ".java");
if (enableTokenOutput) {
(new TokensOutput(consoleHandler, job)).write(dir + jaccSettings.getInterfaceName() + ".java");
}
if (flag1) {
(new TokensOutput(simplehandler, job)).write(dir + settings.getInterfaceName() + ".java");
if (enableVerboseMachineDescription) {
(new TextOutput(consoleHandler, job, includeCalculations)).write(dir + jaccSettings.getClassName() + ".output");
}
if (flag2) {
(new TextOutput(simplehandler, job, flag4)).write(dir + s4 + ".output");
if (parserInputs != null) {
job.readRunExample(parserInputs, includeStateNumbers);
}
final boolean showState = flag5;
NameList.visit(namelist2, new NameList.Visitor() {
public void visit(String s5) throws IOException {
job.readRunExample(s5, showState);
} 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);
}
}

View file

@ -0,0 +1,11 @@
package org.xbib.jacc;
/**
*
*/
public class JaccException extends Exception {
public JaccException(String message) {
super(message);
}
}

View file

@ -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 {

View file

@ -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,62 +171,66 @@ 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 {
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;
}
@ -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) {

View file

@ -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,14 +534,15 @@ 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 (lexer.getToken() == 3) {
if (terminals.find(s) != null) {
return null;
} else {
@ -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;

View file

@ -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());
}

View file

@ -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]);

View file

@ -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) {
switch (machineType) {
case LR0:
return new LR0Machine(grammar);
}
if (machineType == SLR1) {
case SLR1:
return new SLRMachine(grammar);
} else {
case LALR1:
return new LALRMachine(grammar);
default:
return null;
}
}

View file

@ -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();

View file

@ -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;

View file

@ -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];
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 {

View file

@ -0,0 +1,7 @@
package org.xbib.jacc;
/**
*/
public enum MachineType {
LR0, SLR1, LALR1
}

View file

@ -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];");

View file

@ -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(" : ");

View file

@ -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++) {

View file

@ -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());
}
}

View file

@ -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() {

View file

@ -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);
}
}
}

View file

@ -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();
}

View file

@ -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 {
}
}

View file

@ -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();

View file

@ -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(", ");
}

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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");

View file

@ -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");

View file

@ -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) {

View file

@ -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++) {

View file

@ -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);

View file

@ -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;

View file

@ -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");
}
}

View file

@ -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(" ...");
}

View file

@ -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++) {

View file

@ -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;
}
}
}

View 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;
}
}

View file

@ -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;
}

View file

@ -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");

View file

@ -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();
}

View file

@ -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();
}
}

View file

@ -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;
}

View 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"
: ';' ;

View file

@ -0,0 +1,7 @@
"Unexpected opening parenthesis"
: ')'
;
"Missing operand"
: expr INTEGER
;

View 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();
}
}

View 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();
}
}
}

View file

@ -0,0 +1,4 @@
/**
* Helper classes for testing.
*/
package org.xbib.jacc.helper;

View file

@ -0,0 +1,4 @@
/**
* Classes for testing jacc.
*/
package org.xbib.jacc;

View 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"
: ';' ;

View 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]);
}

View 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
}
}

View 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]);
}
}

View 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.

View 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)
}

View file

@ -0,0 +1,4 @@
INTEGER '+' INTEGER '*' INTEGER ';'
INTEGER '*' INTEGER '+' INTEGER

View 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!

View 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
}