/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This file is part of SableCC. *
* See the file "LICENSE" for copyright information and the *
* terms and conditions for copying, distribution and *
* modification of SableCC. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package org.sablecc.sablecc;
import org.sablecc.sablecc.lexer.*;
import org.sablecc.sablecc.node.*;
import org.sablecc.sablecc.parser.*;
import java.io.File;
import java.io.FileReader;
import java.io.PushbackReader;
import java.util.Vector;
@SuppressWarnings({"rawtypes", "unchecked"})
public class SableCC {
private static boolean processInlining = true;
static int inliningMaxAlts = 20;
private static boolean prettyPrinting = false;
private static final String OPT_LICENSE = "--license";
private static final String OPT_D = "-d";
private static final String OPT_NO_INLINE = "--no-inline";
private static final String OPT_INLINE_MAX_ALTS = "--inline-max-alts";
private static final String OPT_PRETTY_PRINT = "--pretty-print";
private static void displayCopyright() {
System.out.println();
System.out.println("SableCC version " + Version.VERSION);
System.out.println("Copyright (C) 1997-2012 Etienne M. Gagnon <egagnon@j-meg.com> and");
System.out.println("others. All rights reserved.");
System.out.println();
System.out.println("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
System.out.println("and you are welcome to redistribute it under certain conditions.");
System.out.println();
System.out.println("Type 'sablecc -license' to view");
System.out.println("the complete copyright notice and license.");
System.out.println();
}
private static void displayUsage() {
System.out.println("Usage:");
System.out.println(" sablecc [" +
OPT_D + " destination] [" +
OPT_NO_INLINE + "] [" +
OPT_INLINE_MAX_ALTS + " number] [" +
OPT_PRETTY_PRINT + "] filename [filename]...");
System.out.println(" sablecc " + OPT_LICENSE);
}
public static void main(String[] arguments) {
String d_option = null;
Vector filename = new Vector();
if (arguments.length == 0) {
displayCopyright();
displayUsage();
System.exit(1);
}
if ((arguments.length == 1) && (arguments[0].equals(OPT_LICENSE))) {
new DisplayLicense();
System.exit(0);
}
displayCopyright();
{
int arg = 0;
while (arg < arguments.length) {
if (arguments[arg].equals(OPT_D)) {
if ((d_option == null) && (++arg < arguments.length)) {
d_option = arguments[arg];
} else {
displayUsage();
System.exit(1);
}
} else if (arguments[arg].equals(OPT_NO_INLINE)) {
processInlining = false;
}
/* A production is not inlined if it has more than
* inliningMaxAlts alternatives. The default value is 20. */
else if (arguments[arg].equals(OPT_INLINE_MAX_ALTS)) {
try {
inliningMaxAlts = Integer.parseInt(arguments[++arg]);
} catch (Exception e) {
displayUsage();
System.exit(1);
}
}
/*
if prettyprint flag is set to true, only the transformed
grammar is printed on standard output
*/
else if (arguments[arg].equals(OPT_PRETTY_PRINT)) {
prettyPrinting = true;
} else {
filename.addElement(arguments[arg]);
}
arg++;
}
if (filename.size() == 0) {
displayUsage();
System.exit(1);
}
}
try {
for (int i = 0; i < filename.size(); i++) {
processGrammar((String) filename.elementAt(i), d_option);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
/**
* The main method for processing grammar file and generating the parser/lexer.
*
* @param grammar input grammar file name
* @param destDir output directory name
*/
public static void processGrammar(String grammar, String destDir) throws Exception {
File in;
File dir;
in = new File(grammar);
in = new File(in.getAbsolutePath());
if (destDir == null) {
dir = new File(in.getParent());
} else {
dir = new File(destDir);
dir = new File(dir.getAbsolutePath());
}
processGrammar(in, dir);
}
/**
* The main method for processing grammar file and generating the parser/lexer.
*
* @param in input grammar file
* @param dir output directory
*/
public static void processGrammar(File in, File dir) throws Exception {
if (!in.exists()) {
System.out.println("ERROR: grammar file " + in.getName() + " does not exist.");
System.exit(1);
}
if (!dir.exists()) {
System.out.println("ERROR: destination directory " + dir.getName() + " does not exist.");
System.exit(1);
}
// re-initialize all static structures in the engine
LR0Collection.reinit();
Symbol.reinit();
Production.reinit();
Grammar.reinit();
System.out.println("\n -- Generating parser for " + in.getName() + " in " + dir.getPath());
FileReader temp = new FileReader(in);
// Build the AST
Start tree = new Parser(new Lexer(new PushbackReader(
temp = new FileReader(in), 1000))).parse();
temp.close();
boolean hasTransformations = false;
if (((AGrammar) tree.getPGrammar()).getAst() == null) {
System.out.println("Adding productions and alternative of section AST.");
//AddAstProductions astProductions = new AddAstProductions();
tree.apply(new AddAstProductions());
} else {
hasTransformations = true;
}
System.out.println("Verifying identifiers.");
ResolveIds ids = new ResolveIds(dir);
tree.apply(ids);
System.out.println("Verifying ast identifiers.");
ResolveAstIds ast_ids = new ResolveAstIds(ids);
tree.apply(ast_ids);
System.out.println("Adding empty productions and empty alternative transformation if necessary.");
tree.apply(new AddEventualEmptyTransformationToProductions(ids, ast_ids));
System.out.println("Adding productions and alternative transformation if necessary.");
AddProdTransformAndAltTransform adds = new AddProdTransformAndAltTransform();
tree.apply(adds);
/*
System.out.println("Replacing AST + operator by * and removing ? operator if necessary");
tree.apply( new AstTransformations() );
*/
System.out.println("computing alternative symbol table identifiers.");
ResolveAltIds alt_ids = new ResolveAltIds(ids);
tree.apply(alt_ids);
System.out.println("Verifying production transform identifiers.");
ResolveProdTransformIds ptransform_ids = new ResolveProdTransformIds(ast_ids);
tree.apply(ptransform_ids);
System.out.println("Verifying ast alternatives transform identifiers.");
ResolveTransformIds transform_ids = new ResolveTransformIds(ast_ids, alt_ids, ptransform_ids);
tree.apply(transform_ids);
System.out.println("Generating token classes.");
tree.apply(new GenTokens(ids));
System.out.println("Generating production classes.");
tree.apply(new GenProds(ast_ids));
System.out.println("Generating alternative classes.");
tree.apply(new GenAlts(ast_ids));
System.out.println("Generating analysis classes.");
tree.apply(new GenAnalyses(ast_ids));
System.out.println("Generating utility classes.");
tree.apply(new GenUtils(ast_ids));
try {
System.out.println("Generating the lexer.");
tree.apply(new GenLexer(ids));
} catch (Exception e) {
System.out.println(e.getMessage());
throw e;
}
try {
System.out.println("Generating the parser.");
tree.apply(new GenParser(ids, alt_ids, transform_ids, ast_ids.getFirstAstProduction(), processInlining, prettyPrinting, hasTransformations));
} catch (Exception e) {
System.out.println(e.getMessage());
throw e;
}
}
}