/* This file is part of SableCC ( http://sablecc.org ).
*
* See the NOTICE file distributed with this work for copyright information.
*
* 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.sablecc.sablecc.launcher;
import static org.sablecc.sablecc.launcher.Version.*;
import static org.sablecc.sablecc.util.Utils.*;
import java.io.*;
import java.util.*;
import java.util.Map.*;
import org.sablecc.exception.*;
import org.sablecc.sablecc.alphabet.*;
import org.sablecc.sablecc.automaton.*;
import org.sablecc.sablecc.automaton.State;
import org.sablecc.sablecc.codegeneration.java.macro.*;
import org.sablecc.sablecc.errormessage.*;
import org.sablecc.sablecc.exception.*;
import org.sablecc.sablecc.lrautomaton.*;
import org.sablecc.sablecc.lrautomaton.Alternative;
import org.sablecc.sablecc.lrautomaton.Element;
import org.sablecc.sablecc.lrautomaton.Production;
import org.sablecc.sablecc.lrautomaton.Token;
import org.sablecc.sablecc.structure.*;
import org.sablecc.sablecc.syntax3.lexer.*;
import org.sablecc.sablecc.syntax3.node.*;
import org.sablecc.sablecc.syntax3.parser.*;
import org.sablecc.sablecc.walker.*;
import org.sablecc.util.*;
/**
* The main class of SableCC.
*/
public class SableCC {
/** Prevents instantiation of this class. */
private SableCC() {
throw new InternalException("this class may not have instances");
}
/** Launches SableCC. */
public static void main(
String[] args) {
try {
compile(args);
}
catch (CompilerException e) {
System.err.print(e.getMessage());
System.err.flush();
System.exit(1);
}
catch (ParserException e) {
int start = e.getMessage().indexOf(' ');
System.err.print(new MSyntaxError(e.getToken().getLine() + "", e
.getToken().getPos()
+ "", e.getToken().getClass().getSimpleName().substring(1),
e.getToken().getText(), e.getMessage().substring(start)));
System.err.flush();
System.exit(1);
}
catch (LexerException e) {
int start = e.getMessage().indexOf('[') + 1;
int end = e.getMessage().indexOf(',');
String line = e.getMessage().substring(start, end);
start = e.getMessage().indexOf(',') + 1;
end = e.getMessage().indexOf(']');
String pos = e.getMessage().substring(start, end);
start = e.getMessage().indexOf(' ') + 1;
System.err.print(new MLexicalError(line, pos, e.getMessage()
.substring(start)));
System.err.flush();
System.exit(1);
}
catch (InternalException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
System.err.print(new MInternalError(sw.toString(), e.getMessage()));
System.err.flush();
System.exit(1);
}
catch (Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
String message = e.getMessage() == null ? "" : e.getMessage();
System.err.print(new MInternalError(sw.toString(), message));
System.err.flush();
System.exit(1);
}
// finish gracefully
System.exit(0);
}
/**
* Parses the provided arguments and launches grammar compilation.
*/
public static void compile(
String[] arguments)
throws ParserException, LexerException {
// default target is java
String targetLanguage = "java";
// default destination directory is current working directory
File destinationDirectory = new File(System.getProperty("user.dir"));
// default destination package is anonymous
String destinationPackage = "";
// default option values
boolean generateCode = true;
Verbosity verbosity = Verbosity.INFORMATIVE;
Strictness strictness = Strictness.STRICT;
// parse command line arguments
ArgumentCollection argumentCollection = new ArgumentCollection(
arguments);
// handle option arguments
for (OptionArgument optionArgument : argumentCollection
.getOptionArguments()) {
switch (optionArgument.getOption()) {
case LIST_TARGETS:
System.out.println("Available targets:");
System.out.println(" java (default)");
return;
case TARGET:
targetLanguage = optionArgument.getOperand();
break;
case DESTINATION:
destinationDirectory = new File(optionArgument.getOperand());
break;
case PACKAGE:
destinationPackage = optionArgument.getOperand();
break;
case GENERATE:
generateCode = true;
break;
case NO_CODE:
generateCode = false;
break;
case LENIENT:
strictness = Strictness.LENIENT;
break;
case STRICT:
strictness = Strictness.STRICT;
break;
case QUIET:
verbosity = Verbosity.QUIET;
break;
case INFORMATIVE:
verbosity = Verbosity.INFORMATIVE;
break;
case VERBOSE:
verbosity = Verbosity.VERBOSE;
break;
case VERSION:
System.out.println("SableCC version " + VERSION);
return;
case HELP:
System.out.println("Usage: sablecc "
+ Option.getShortHelpMessage() + " grammar.sablecc");
System.out.println("Options:");
System.out.println(Option.getLongHelpMessage());
return;
default:
throw new InternalException("unhandled option "
+ optionArgument.getOption());
}
}
switch (verbosity) {
case INFORMATIVE:
case VERBOSE:
System.out.println();
System.out.println("SableCC version " + VERSION);
System.out
.println("by Etienne M. Gagnon <egagnon@j-meg.com> and other contributors.");
System.out.println();
break;
}
// handle text arguments
if (argumentCollection.getTextArguments().size() == 0) {
System.out.println("Usage: sablecc " + Option.getShortHelpMessage()
+ " grammar.sablecc");
return;
}
else if (argumentCollection.getTextArguments().size() > 1) {
throw CompilerException.invalidArgumentCount();
}
// check target
if (!targetLanguage.equals("java")) {
throw CompilerException.unknownTarget(targetLanguage);
}
// check argument
TextArgument textArgument = argumentCollection.getTextArguments()
.get(0);
if (!textArgument.getText().endsWith(".sablecc")) {
throw CompilerException.invalidSuffix(textArgument.getText());
}
File grammarFile = new File(textArgument.getText());
if (!grammarFile.exists()) {
throw CompilerException.missingGrammarFile(textArgument.getText());
}
if (!grammarFile.isFile()) {
throw CompilerException.grammarNotFile(textArgument.getText());
}
compile(grammarFile, targetLanguage, destinationDirectory,
destinationPackage, generateCode, strictness, verbosity);
}
/**
* Compiles the provided grammar file.
*/
private static void compile(
File grammarFile,
String targetLanguage,
File destinationDirectory,
String destinationPackage,
boolean generateCode,
Strictness strictness,
Verbosity verbosity)
throws ParserException, LexerException {
switch (verbosity) {
case INFORMATIVE:
case VERBOSE:
System.out.println("Compiling \"" + grammarFile + "\"");
break;
}
Start ast;
try {
FileReader fr = new FileReader(grammarFile);
BufferedReader br = new BufferedReader(fr);
PushbackReader pbr = new PushbackReader(br, 1024);
switch (verbosity) {
case VERBOSE:
System.out.println(" Parsing");
break;
}
ast = new Parser(new Lexer(pbr)).parse();
pbr.close();
br.close();
fr.close();
}
catch (IOException e) {
throw CompilerException.inputError(grammarFile.toString(), e);
}
switch (verbosity) {
case VERBOSE:
System.out.println(" Verifying semantics");
break;
}
GlobalIndex globalIndex = verifySemantics(ast, strictness);
switch (verbosity) {
case VERBOSE:
System.out.println(" Computing lexer");
break;
}
Automaton lexer = computeLexer(globalIndex, verbosity);
switch (verbosity) {
case VERBOSE:
System.out.println(" Computing parser");
break;
}
LRAutomaton parser = computeParser(globalIndex, verbosity);
if (generateCode) {
switch (verbosity) {
case VERBOSE:
System.out.println(" Generating code");
break;
}
if (targetLanguage.equals("java")) {
generateJavaCode(destinationDirectory, destinationPackage,
globalIndex, lexer, parser);
}
else {
throw new InternalException("unimplemented");
}
}
switch (verbosity) {
case INFORMATIVE:
case VERBOSE:
System.out.println("Done compiling \"" + grammarFile + "\"");
break;
}
}
private static GlobalIndex verifySemantics(
Start ast,
Strictness strictness) {
GlobalIndex globalIndex = new GlobalIndex();
new SimpleLexerAndParserRestricter().visit(ast);
new GlobalDeclarationCollector(globalIndex).visit(ast);
new LexerDeclarationCollector(globalIndex).visit(ast);
new LexerPriorityCollector(globalIndex).visit(ast);
new ParserDeclarationCollector(globalIndex).visit(ast);
new ParserPriorityCollector(globalIndex).visit(ast);
new ExpressionVerifier(globalIndex).visit(ast);
new CyclicExpressionDetector(globalIndex).visit(ast);
return globalIndex;
}
private static Automaton computeLexer(
GlobalIndex globalIndex,
Verbosity verbosity) {
for (NormalExpression normalExpression : globalIndex
.getNormalNamedExpressionLinearization()) {
switch (verbosity) {
case VERBOSE:
System.out.println(" - "
+ normalExpression.getNameToken().getText());
break;
}
Automaton automaton = RegularExpressionEvaluator
.evaluateExpression(globalIndex, normalExpression
.getExpression());
normalExpression.setAutomaton(automaton);
}
switch (verbosity) {
case VERBOSE:
System.out.println(" Computing automaton");
break;
}
Context context = globalIndex.getContexts().iterator().next();
Automaton lexerAutomaton = Automaton.getEmptyAutomaton();
for (MatchedToken matchedToken : context.getMatchedTokens()) {
lexerAutomaton = lexerAutomaton.or(matchedToken.getAutomaton());
}
switch (verbosity) {
case VERBOSE:
System.out.println(" Minimizing automaton");
break;
}
lexerAutomaton = lexerAutomaton.withPriorities(context).withMarkers()
.minimal();
return lexerAutomaton;
}
private static LRAutomaton computeParser(
GlobalIndex globalIndex,
Verbosity verbosity) {
Grammar grammar = globalIndex.getGrammar();
switch (verbosity) {
case VERBOSE:
System.out.println(" Detecting useless productions");
break;
}
grammar.computeShortestLengthAndDetectUselessProductions();
return new LRAutomaton(grammar, verbosity);
}
private static void generateJavaCode(
File destinationDirectory,
String destinationPackage,
GlobalIndex globalIndex,
Automaton lexer,
LRAutomaton parser) {
String languagePackageName = "language_"
+ globalIndex.getLanguage().get_camelCaseName();
File packageDirectory;
MNode mNode = new MNode();
MToken mToken = new MToken();
MState mState = new MState();
MTransitionState mTransitionState = new MTransitionState();
MFinalState mFinalState = new MFinalState();
MSymbol mSymbol = new MSymbol();
MLexer mLexer = new MLexer();
MLexerException mLexerException = new MLexerException();
MParserException mParserException = new MParserException();
MTest mTest = new MTest();
MEnd mEnd = new MEnd();
MWalker mWalker = new MWalker();
MParser mParser = new MParser();
if (destinationPackage.equals("")) {
packageDirectory = new File(destinationDirectory,
languagePackageName);
mNode.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mToken.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mState.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mTransitionState.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mFinalState.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mSymbol.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mLexer.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mLexerException.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mParserException.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mTest.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mEnd.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mWalker.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
mParser.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
}
else {
packageDirectory = new File(destinationDirectory,
destinationPackage.replace('.', '/') + "/"
+ languagePackageName);
mNode.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mToken.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mState.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mTransitionState.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mFinalState.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mSymbol.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mLexer.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mLexerException.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mParserException.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mTest.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mEnd.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mWalker.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
mParser.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
}
packageDirectory.mkdirs();
Context context = globalIndex.getContexts().iterator().next();
for (MatchedToken matchedToken : context.getMatchedTokens()) {
if (!matchedToken.isIgnored()) {
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
mNode.newNodeTypeEnumEntry(nameToken.get_CamelCaseName());
mNode.newNodeInternalTypeEnumEntry(nameToken
.get_CamelCaseName());
mWalker.newWalkerIn(nameToken.get_CamelCaseName());
mWalker.newWalkerCase(nameToken.get_CamelCaseName());
mWalker.newWalkerOut(nameToken.get_CamelCaseName());
MCustomToken mCustomToken = new MCustomToken(nameToken
.get_CamelCaseName());
if (destinationPackage.equals("")) {
mCustomToken.newDefaultPackage(globalIndex
.getLanguage().get_camelCaseName());
}
else {
mCustomToken.newSpecifiedPackage(globalIndex
.getLanguage().get_camelCaseName(),
destinationPackage);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "N"
+ nameToken.get_CamelCaseName()
+ ".java")));
bw.write(mCustomToken.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("N"
+ nameToken.get_CamelCaseName() + ".java", e);
}
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
mNode.newNodeInternalTypeEnumEntry(""
+ anonymousToken.get_CamelCaseName());
MAnonymousToken mAnonymousToken = new MAnonymousToken(""
+ anonymousToken.get_CamelCaseName());
if (destinationPackage.equals("")) {
mAnonymousToken.newDefaultPackage(globalIndex
.getLanguage().get_camelCaseName());
}
else {
mAnonymousToken.newSpecifiedPackage(globalIndex
.getLanguage().get_camelCaseName(),
destinationPackage);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "N"
+ anonymousToken.get_CamelCaseName()
+ ".java")));
bw.write(mAnonymousToken.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("N"
+ anonymousToken.get_CamelCaseName() + ".java",
e);
}
}
}
}
for (Symbol symbol : lexer.getAlphabet().getSymbols()) {
mSymbol.newSymbolDeclaration(symbol.getSimpleName());
}
for (Map.Entry<Interval, Symbol> entry : lexer.getAlphabet()
.getIntervalToSymbolMap().entrySet()) {
Interval interval = entry.getKey();
Symbol symbol = entry.getValue();
if (interval.getLowerBound() == Bound.MIN) {
if (interval.getUpperBound() == Bound.MAX) {
mSymbol.newOpenInterval(symbol.getSimpleName());
}
else {
mSymbol.newOpenLeftInterval(interval.getUpperBound()
.getValue().toString(), symbol.getSimpleName());
}
}
else if (interval.getUpperBound() == Bound.MAX) {
mSymbol.newOpenRightInterval(interval.getLowerBound()
.getValue().toString(), symbol.getSimpleName());
}
else if (interval.getLowerBound().equals(interval.getUpperBound())) {
mSymbol.newSingleChar(interval.getLowerBound().getValue()
.toString(), symbol.getSimpleName());
}
else {
mSymbol.newInterval(interval.getLowerBound().getValue()
.toString(), interval.getUpperBound().getValue()
.toString(), symbol.getSimpleName());
}
}
for (State state : lexer.getStates()) {
if (state.isAcceptState()) {
Acceptation acceptation = state.getAcceptations().first();
MFinalStateSingleton mFinalStateSingleton = new MFinalStateSingleton(
"" + state.getId(), "" + acceptation.getBackCount());
if (destinationPackage.equals("")) {
mFinalStateSingleton.newDefaultPackage(globalIndex
.getLanguage().get_camelCaseName());
}
else {
mFinalStateSingleton.newSpecifiedPackage(globalIndex
.getLanguage().get_camelCaseName(),
destinationPackage);
}
Marker marker = acceptation.getMarker();
if (marker == null) {
mFinalStateSingleton.newAcceptTokenNoMarker();
}
else {
mFinalStateSingleton.newAcceptTokenWithMarker(marker
.getName());
}
MatchedToken matchedToken = context.getMatchedToken(acceptation
.getName());
if (matchedToken.isIgnored()) {
mFinalStateSingleton.newAcceptIgnoredToken();
}
else {
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
mFinalStateSingleton.newAcceptNormalToken(nameToken
.get_CamelCaseName());
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
mFinalStateSingleton.newAcceptNormalToken(""
+ anonymousToken.get_CamelCaseName());
}
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "S_" + state.getId()
+ ".java")));
bw.write(mFinalStateSingleton.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("S_" + state.getId()
+ ".java", e);
}
}
else {
MTransitionStateSingleton mTransitionStateSingleton = new MTransitionStateSingleton(
"" + state.getId());
if (destinationPackage.equals("")) {
mTransitionStateSingleton.newDefaultPackage(globalIndex
.getLanguage().get_camelCaseName());
}
else {
mTransitionStateSingleton.newSpecifiedPackage(globalIndex
.getLanguage().get_camelCaseName(),
destinationPackage);
}
Marker marker = state.getMarker();
if (marker == null) {
mTransitionStateSingleton.newNoMarker();
}
else {
mTransitionStateSingleton.newSetMarker(marker.getName());
}
for (Entry<RichSymbol, SortedSet<State>> entry : state
.getTransitions().entrySet()) {
RichSymbol richSymbol = entry.getKey();
State target = state.getSingleTarget(richSymbol);
String symbolName = richSymbol == RichSymbol.END ? "end"
: richSymbol.getSymbol().getSimpleName();
mTransitionStateSingleton.newTransitionTarget(symbolName,
"" + target.getId());
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "S_" + state.getId()
+ ".java")));
bw.write(mTransitionStateSingleton.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("S_" + state.getId()
+ ".java", e);
}
}
}
for (Marker marker : lexer.getMarkers()) {
mLexer.newMarkerDeclaration(marker.getName());
mLexer.newSetMarkerDeclaration(marker.getName());
mLexer.newAcceptMarkerDeclaration(marker.getName());
}
for (Production production : parser.getGrammar().getProductions()) {
String production_CamelCaseName = to_CamelCase(production.getName());
mNode.newNodeProductionTypeEnumEntry(production_CamelCaseName);
// if production is not a single anonymous alternative
if (production.getAlternatives().size() > 1
|| !production.getAlternatives().iterator().next()
.getName().equals("")) {
MProduction mProduction = new MProduction(
production_CamelCaseName);
if (destinationPackage.equals("")) {
mProduction.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
}
else {
mProduction.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
}
if (production_CamelCaseName.indexOf('$') == -1) {
mProduction.newNamedProductionHeader();
}
else {
mProduction.newAnonymousProductionHeader();
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "N"
+ production_CamelCaseName + ".java")));
bw.write(mProduction.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("N"
+ production_CamelCaseName + ".java", e);
}
}
for (Alternative alternative : production.getAlternatives()) {
String alt_CamelCaseName = to_CamelCase(alternative.getName());
String alt_CamelCaseFullName = production_CamelCaseName
+ (alt_CamelCaseName.equals("") ? "" : "_"
+ alt_CamelCaseName);
boolean altIsPublic = alt_CamelCaseFullName.indexOf('$') == -1;
boolean altExtendsNode = alt_CamelCaseFullName.indexOf('_') == -1;
MAlternative mAlternative = new MAlternative(
alt_CamelCaseFullName);
mAlternative.newAltProdType(production_CamelCaseName);
if (altIsPublic) {
mWalker.newWalkerIn(alt_CamelCaseFullName);
mWalker.newWalkerCase(alt_CamelCaseFullName);
mWalker.newWalkerOut(alt_CamelCaseFullName);
mAlternative.newAltNormalApply();
}
else {
mAlternative.newAltAnonymousApply();
}
if (destinationPackage.equals("")) {
mAlternative.newDefaultPackage(globalIndex.getLanguage()
.get_camelCaseName());
}
else {
mAlternative.newSpecifiedPackage(globalIndex.getLanguage()
.get_camelCaseName(), destinationPackage);
}
mNode.newNodeInternalTypeEnumEntry(alt_CamelCaseFullName);
if (altIsPublic) {
mNode.newNodeTypeEnumEntry(alt_CamelCaseFullName);
mAlternative.newPublic();
mAlternative.newNamedAltType();
}
else {
mAlternative.newAnonymousAltType();
}
if (altExtendsNode) {
mAlternative.newAlternativeNodeParent();
}
else {
mAlternative
.newAlternativeNamedParent(production_CamelCaseName);
}
boolean altHasPublicConstructor = true;
for (Element element : alternative.getElements()) {
String element_CamelCaseName = to_CamelCase(element
.getName());
String element_CamelCaseType = null;
boolean elementIsEndToken;
boolean elementIsPublicReadable;
boolean elementIsPublicWritable;
if (element instanceof TokenElement) {
TokenElement tokenElement = (TokenElement) element;
if (tokenElement.getToken().getName().equals("$end")) {
elementIsEndToken = true;
elementIsPublicReadable = false;
elementIsPublicWritable = false;
}
else {
MatchedToken matchedToken = context
.getMatchedToken(tokenElement.getToken()
.getName());
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
element_CamelCaseType = nameToken
.get_CamelCaseName();
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
element_CamelCaseType = ""
+ anonymousToken.get_CamelCaseName();
}
elementIsEndToken = false;
elementIsPublicReadable = altIsPublic
&& element_CamelCaseName.indexOf('$') == -1;
elementIsPublicWritable = elementIsPublicReadable
&& element_CamelCaseType.indexOf('$') == -1;
}
}
else {
ProductionElement productionElement = (ProductionElement) element;
element_CamelCaseType = to_CamelCase(productionElement
.getProduction().getName());
elementIsEndToken = false;
elementIsPublicReadable = altIsPublic
&& element_CamelCaseName.indexOf('$') == -1;
elementIsPublicWritable = elementIsPublicReadable
&& element_CamelCaseType.indexOf('$') == -1;
}
if (!elementIsPublicWritable) {
altHasPublicConstructor = false;
}
if (elementIsEndToken) {
mAlternative.newEndConstructorParameter();
mAlternative.newEndContructorInitialization();
mAlternative.newEndElementDeclaration();
mAlternative.newEndElementAccessor();
mAlternative.newEndChildApply();
}
else {
mAlternative.newNormalConstructorParameter(
element_CamelCaseType, element_CamelCaseName);
mAlternative
.newNormalContructorInitialization(element_CamelCaseName);
mAlternative.newNormalElementDeclaration(
element_CamelCaseType, element_CamelCaseName);
mAlternative.newNormalElementAccessor(
element_CamelCaseType, element_CamelCaseName);
mAlternative.newNormalChildApply(element_CamelCaseName);
if (elementIsPublicReadable) {
MPublicElementAccessor publicElementAccessor = mAlternative
.newPublicElementAccessor(element_CamelCaseName);
if (elementIsPublicWritable) {
publicElementAccessor
.newPublicElementType(element_CamelCaseType);
}
else {
publicElementAccessor.newTokenElementType();
}
}
}
}
if (altHasPublicConstructor) {
mAlternative.newPublicConstructor();
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
new File(packageDirectory, "N"
+ alt_CamelCaseFullName + ".java")));
bw.write(mAlternative.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("N"
+ alt_CamelCaseFullName + ".java", e);
}
}
}
for (LRState state : parser.getStates()) {
MLrStateSingleton mLrStateSingleton = mParser
.newLrStateSingleton(state.getName());
for (Entry<Token, LRState> entry : state.getTokenTransitions()
.entrySet()) {
Token token = entry.getKey();
LRState target = entry.getValue();
if (token.getName().equals("$end")) {
mLrStateSingleton.newEndTokenLrTransitionTarget(target
.getName());
}
else {
MatchedToken matchedToken = context.getMatchedToken(token
.getName());
String element_CamelCaseType;
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
element_CamelCaseType = nameToken.get_CamelCaseName();
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
element_CamelCaseType = ""
+ anonymousToken.get_CamelCaseName();
}
mLrStateSingleton.newNormalTokenLrTransitionTarget(
element_CamelCaseType, target.getName());
}
}
for (Entry<Production, LRState> entry : state
.getProductionTransitions().entrySet()) {
Production production = entry.getKey();
LRState target = entry.getValue();
String production_CamelCaseName = to_CamelCase(production
.getName());
mLrStateSingleton.newProductionLrTransitionTarget(
production_CamelCaseName, target.getName());
}
Map<Integer, MDistance> distanceMap = new LinkedHashMap<Integer, MDistance>();
boolean isLr1OrMore = false;
for (Action action : state.getActions()) {
int maxLookahead = action.getMaxLookahead();
while (maxLookahead > distanceMap.size() - 1) {
int distance = distanceMap.size();
distanceMap.put(distance, mLrStateSingleton.newDistance(""
+ distance));
}
MDistance mDistance = distanceMap.get(maxLookahead);
MAction mAction = mDistance.newAction();
if (maxLookahead > 0) {
isLr1OrMore = true;
for (Entry<Integer, Set<Item>> entry : action
.getDistanceToItemSetMap().entrySet()) {
String ahead = "" + entry.getKey();
Set<Item> items = entry.getValue();
Set<Token> tokens = new LinkedHashSet<Token>();
for (Item item : items) {
tokens.add(item.getTokenElement().getToken());
}
if (tokens.size() == 0) {
mAction.newFalseGroup();
}
else {
MNormalGroup mNormalGroup = mAction
.newNormalGroup();
for (Token token : tokens) {
if (token.getName().equals("$end")) {
mNormalGroup.newEndCondition(ahead);
}
else {
MatchedToken matchedToken = context
.getMatchedToken(token.getName());
String element_CamelCaseType;
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
element_CamelCaseType = nameToken
.get_CamelCaseName();
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
element_CamelCaseType = ""
+ anonymousToken
.get_CamelCaseName();
}
mNormalGroup.newNormalCondition(ahead,
element_CamelCaseType);
}
}
}
}
}
if (action.getType() == ActionType.SHIFT) {
mAction.newShift();
}
else {
ReduceAction reduceAction = (ReduceAction) action;
Alternative alternative = reduceAction.getAlternative();
Production production = alternative.getProduction();
String production_CamelCaseName = to_CamelCase(production
.getName());
String alt_CamelCaseName = to_CamelCase(alternative
.getName());
String alt_CamelCaseFullName = production_CamelCaseName
+ (alt_CamelCaseName.equals("") ? "" : "_"
+ alt_CamelCaseName);
MReduce mReduce = mAction.newReduce(alt_CamelCaseFullName);
ArrayList<Element> elements = alternative.getElements();
int elementCount = elements.size();
for (int i = elementCount - 1; i >= 0; i--) {
Element element = elements.get(i);
String element_CamelCaseName = to_CamelCase(element
.getName());
String element_CamelCaseType = null;
boolean elementIsEndToken;
if (element instanceof TokenElement) {
TokenElement tokenElement = (TokenElement) element;
if (tokenElement.getToken().getName()
.equals("$end")) {
elementIsEndToken = true;
}
else {
MatchedToken matchedToken = context
.getMatchedToken(tokenElement
.getToken().getName());
if (matchedToken instanceof NameToken) {
NameToken nameToken = (NameToken) matchedToken;
element_CamelCaseType = nameToken
.get_CamelCaseName();
}
else {
AnonymousToken anonymousToken = (AnonymousToken) matchedToken;
element_CamelCaseType = ""
+ anonymousToken
.get_CamelCaseName();
}
elementIsEndToken = false;
}
}
else {
ProductionElement productionElement = (ProductionElement) element;
element_CamelCaseType = to_CamelCase(productionElement
.getProduction().getName());
elementIsEndToken = false;
}
if (elementIsEndToken) {
mReduce.newReduceEndPop();
}
else {
mReduce.newReduceNormalPop(element_CamelCaseType,
element_CamelCaseName);
}
}
if (alt_CamelCaseFullName.equals("$Start")) {
mReduce.newAcceptDecision(to_CamelCase(elements.get(0)
.getName()));
}
else {
MReduceDecision mReduceDecision = mReduce
.newReduceDecision();
for (Element element : elements) {
String element_CamelCaseName = to_CamelCase(element
.getName());
boolean elementIsEndToken;
if (element instanceof TokenElement) {
TokenElement tokenElement = (TokenElement) element;
if (tokenElement.getToken().getName().equals(
"$end")) {
elementIsEndToken = true;
}
else {
elementIsEndToken = false;
}
}
else {
elementIsEndToken = false;
}
if (elementIsEndToken) {
mReduceDecision.newEndParameter();
}
else {
mReduceDecision
.newNormalParameter(element_CamelCaseName);
}
}
}
}
}
if (isLr1OrMore) {
mLrStateSingleton.newLr1OrMore();
}
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Node.java")));
bw.write(mNode.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Node.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Token.java")));
bw.write(mToken.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Token.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "State.java")));
bw.write(mState.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("State.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "TransitionState.java")));
bw.write(mTransitionState.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("TransitionState.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "FinalState.java")));
bw.write(mFinalState.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("FinalState.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Symbol.java")));
bw.write(mSymbol.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Symbol.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Lexer.java")));
bw.write(mLexer.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Lexer.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "LexerException.java")));
bw.write(mLexerException.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("LexerException.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "ParserException.java")));
bw.write(mParserException.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("ParserException.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Test.java")));
bw.write(mTest.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Test.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "End.java")));
bw.write(mEnd.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("End.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Walker.java")));
bw.write(mWalker.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Walker.java", e);
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
packageDirectory, "Parser.java")));
bw.write(mParser.toString());
bw.close();
}
catch (IOException e) {
throw CompilerException.outputError("Parser.java", e);
}
}
}