blob: 9d20029b0b461d0bc3f5fcd51a0dc9def79443cc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* https://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 Mini;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Vector;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
public class MiniC {
private static Vector<String> errors;
private static Vector<String> warnings;
private static String file;
private static int pass;
static final void addError(final int line, final int column, final String err) {
if (pass != 2) {
errors.addElement(file + ":" + fillup(line, 3) + "," + fillup(column, 2) + ": " + err);
}
}
static final void addWarning(final int line, final int column, final String err) {
warnings.addElement("Warning: " + file + ":" + fillup(line, 3) + "," + fillup(column, 3) + ": " + err);
}
static final void addWarning(final String err) {
warnings.addElement(err);
}
static final String fillup(final int n, final int len) {
final String str = Integer.toString(n);
final int diff = len - str.length();
if (diff <= 0) {
return str;
}
final char[] chs = new char[diff];
for (int i = 0; i < diff; i++) {
chs[i] = ' ';
}
return new String(chs) + str;
}
public static void main(final String[] argv) {
final String[] fileName = new String[argv.length];
int files = 0;
MiniParser parser;
String baseName;
boolean byteCode = true;
try {
/*
* Parse command line arguments.
*/
for (final String element : argv) {
if (element.charAt(0) == '-') { // command line switch
if (element.equals("-java")) {
byteCode = false;
} else if (element.equals("-bytecode")) {
byteCode = true;
} else {
throw new Exception("Unknown option: " + element);
}
} else { // add file name to list
fileName[files++] = element;
}
}
if (files == 0) {
System.err.println("Nothing to compile.");
}
for (int j = 0; j < files; j++) {
errors = new Vector<>();
warnings = new Vector<>();
pass = 0;
if (j == 0) {
// side-effects
parser = new MiniParser(new FileInputStream(fileName[0]));
Objects.requireNonNull(parser, "parser");
} else {
MiniParser.ReInit(new FileInputStream(fileName[j]));
}
int index = fileName[j].lastIndexOf('.');
if (index > 0) {
baseName = fileName[j].substring(0, index);
} else {
baseName = fileName[j];
}
if ((index = baseName.lastIndexOf(File.separatorChar)) > 0) {
baseName = baseName.substring(index + 1);
}
file = fileName[j];
System.out.println("Parsing...");
MiniParser.Program();
ASTProgram program = (ASTProgram) MiniParser.jjtree.rootNode();
System.out.println("Pass 1: Optimizing parse tree...");
pass = 1;
program = program.traverse();
// program.dump(">");
if (errors.isEmpty()) {
System.out.println("Pass 2: Type checking (I)...");
program.eval(pass = 2);
}
if (errors.isEmpty()) {
System.out.println("Pass 3: Type checking (II)...");
program.eval(pass = 3);
}
errors.forEach(System.out::println);
warnings.forEach(System.out::println);
if (errors.isEmpty()) {
if (byteCode) {
System.out.println("Pass 5: Generating byte code...");
final ClassGen classGen = new ClassGen(baseName, "java.lang.Object", fileName[j],
Const.ACC_PUBLIC | Const.ACC_FINAL | Const.ACC_SUPER, null);
final ConstantPoolGen cp = classGen.getConstantPool();
program.byte_code(classGen, cp);
final JavaClass clazz = classGen.getJavaClass();
clazz.dump(baseName + JavaClass.EXTENSION);
} else {
System.out.println("Pass 5: Generating Java code...");
try (PrintWriter out = new PrintWriter(baseName + ".java", StandardCharsets.UTF_8.name())) {
program.code(out, baseName);
}
System.out.println("Pass 6: Compiling Java code...");
final String[] args = { "javac", baseName + ".java" };
// sun.tools.javac.Main compiler = new sun.tools.javac.Main(System.err, "javac");
try {
final Process p = Runtime.getRuntime().exec(args);
p.waitFor();
} catch (final Exception e) {
System.out.println(e);
}
// compiler.compile(args);
}
}
if (!errors.isEmpty() || !warnings.isEmpty()) {
System.out.println(errors.size() + " errors and " + warnings.size() + " warnings.");
}
}
} catch (final Exception e) {
e.printStackTrace();
}
}
}