/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.analysis.*;
import org.sablecc.sablecc.node.*;
import java.io.*;
import java.util.*;
@SuppressWarnings({"rawtypes", "unchecked"})
public class GenLexer extends AnalysisAdapter {
private MacroExpander macros;
private ResolveIds ids;
private File pkgDir;
private String pkgName;
private AcceptStates[] acceptStatesArray;
private Transitions transitions;
public GenLexer(ResolveIds ids) {
this.ids = ids;
try {
macros = new MacroExpander(
new InputStreamReader(
getClass().getResourceAsStream("lexer.txt")));
} catch (IOException e) {
throw new RuntimeException("unable to open lexer.txt.");
}
pkgDir = new File(ids.pkgDir, "lexer");
pkgName = ids.pkgName.equals("") ? "lexer" : ids.pkgName + ".lexer";
if (!pkgDir.exists()) {
if (!pkgDir.mkdir()) {
throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath());
}
}
}
@Override
public void caseStart(Start tree) {
String[] names;
int numStates = Math.max(1, ids.stateList.size());
acceptStatesArray = new AcceptStates[numStates];
names = new String[numStates];
if (ids.stateList.size() == 0) {
names[0] = "INITIAL";
} else {
Iterator iter = ids.stateList.iterator();
for (int i = 0; i < numStates; i++) {
names[i] = (String) iter.next();
}
}
for (int i = 0; i < numStates; i++) {
System.out.println(" State: " + names[i]);
System.out.println(" - Constructing NFA.");
ConstructNFA nfaConstructor = new ConstructNFA(ids, names[i]);
tree.apply(nfaConstructor);
System.out.println();
NFA nfa = (NFA) nfaConstructor.getOut(tree);
nfaConstructor = null;
System.out.println(" - Constructing DFA.");
DFA dfa = new DFA(nfa);
System.out.println();
System.out.println(" - resolving ACCEPT states.");
acceptStatesArray[i] = new AcceptStates(dfa, ids, names[i]);
tree.apply(acceptStatesArray[i]);
}
transitions = new Transitions();
tree.apply(transitions);
createLexerException();
createIPushbackReader();
createLexer();
}
private void createLexerException() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "LexerException.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "LexerException.java").getAbsolutePath());
}
try {
macros.apply(file, "LexerException", new String[]{pkgName,
ids.pkgName.equals("") ? "node" : ids.pkgName + ".node"});
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "LexerException.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
private void createIPushbackReader() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "IPushbackReader.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "IPushbackReader.java").getAbsolutePath());
}
try {
macros.apply(file, "IPushbackReader", new String[]{pkgName});
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "IPushbackReader.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
private void createLexer() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "Lexer.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "Lexer.java").getAbsolutePath());
}
try {
String startState = "INITIAL";
if (ids.stateList.size() > 0) {
startState = (String) ids.stateList.getFirst();
}
macros.apply(file, "LexerHeader", new String[]{pkgName,
ids.pkgName.equals("") ? "node" : ids.pkgName + ".node",
startState});
for (ListIterator i = ids.tokenList.listIterator(); i.hasNext(); ) {
String name = (String) i.next();
Node node = (Node) ids.tokens.get(name);
boolean fixed = ((Boolean) ids.fixedTokens.get(node))
.booleanValue();
if (fixed) {
macros.apply(file, "LexerFixedToken",
new String[]{"" + i.previousIndex(), name});
} else {
macros.apply(file, "LexerVariableToken",
new String[]{"" + i.previousIndex(), name});
}
Map map = (Map) transitions.tokenStates.get(node);
if (map.size() > 0) {
macros.apply(file, "TokenSwitchHeader", null);
for (Iterator j = map.entrySet().iterator(); j.hasNext(); ) {
Map.Entry entry = (Map.Entry) j.next();
macros.apply(file, "TokenCase",
new String[]{ids.stateList.indexOf((String) entry.getKey()) + "",
(String) entry.getValue()});
}
macros.apply(file, "TokenSwitchTail", null);
}
macros.apply(file, "LexerTokenTail", null);
}
macros.apply(file, "LexerBody1");
for (ListIterator i = ids.tokenList.listIterator(); i.hasNext(); ) {
String name = (String) i.next();
Node node = (Node) ids.tokens.get(name);
boolean fixed = ((Boolean) ids.fixedTokens.get(node))
.booleanValue();
if (fixed) {
macros.apply(file, "LexerNewFixedToken",
new String[]{"" + i.previousIndex(), name});
} else {
macros.apply(file, "LexerNewVariableToken",
new String[]{"" + i.previousIndex(), name});
}
}
macros.apply(file, "LexerBody2");
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(
new File(pkgDir, "lexer.dat"))));
out.writeInt(acceptStatesArray.length);
for (int accSt = 0; accSt < acceptStatesArray.length; accSt++) {
DFA dfa = acceptStatesArray[accSt].dfa;
file.write(" { // " + acceptStatesArray[accSt].stateName + System.getProperty("line.separator"));
Vector outerArray = new Vector();
for (int i = 0; i < dfa.states.size(); i++) {
Vector innerArray = new Vector();
DFA.State state = (DFA.State) dfa.states.elementAt(i);
file.write(" {");
for (int j = 0; j < state.transitions.size(); j++) {
DFA.Transition transition =
(DFA.Transition) state.transitions.elementAt(j);
file.write("{" + ((int) transition.interval().start) + ", " +
((int) transition.interval().end) + ", " +
transition.destination + "}, ");
innerArray.addElement(new int[]{
((int) transition.interval().start),
((int) transition.interval().end),
transition.destination});
}
file.write("}," + System.getProperty("line.separator"));
outerArray.addElement(innerArray);
}
file.write(" }" + System.getProperty("line.separator"));
out.writeInt(outerArray.size());
for (Enumeration e = outerArray.elements(); e.hasMoreElements(); ) {
Vector innerArray = (Vector) e.nextElement();
out.writeInt(innerArray.size());
for (Enumeration n = innerArray.elements(); n.hasMoreElements(); ) {
int[] array = (int[]) n.nextElement();
for (int i = 0; i < 3; i++) {
out.writeInt(array[i]);
}
}
}
}
macros.apply(file, "LexerAcceptHeader");
final int stateNumber = acceptStatesArray.length;
Vector outerArray = new Vector();
for (int i = 0; i < stateNumber; i++) {
DFA dfa = acceptStatesArray[i].dfa;
Vector innerArray = new Vector();
file.write(" // " + acceptStatesArray[i].stateName + System.getProperty("line.separator"));
file.write(" {");
for (int j = 0; j < dfa.states.size(); j++) {
DFA.State state = (DFA.State) dfa.states.elementAt(j);
file.write(state.accept + ", ");
innerArray.addElement(new Integer(state.accept));
}
file.write("}," + System.getProperty("line.separator"));
outerArray.addElement(innerArray);
}
out.writeInt(outerArray.size());
for (Enumeration e = outerArray.elements(); e.hasMoreElements(); ) {
Vector innerArray = (Vector) e.nextElement();
out.writeInt(innerArray.size());
for (Enumeration n = innerArray.elements(); n.hasMoreElements(); ) {
Integer i = (Integer) n.nextElement();
out.writeInt(i.intValue());
}
}
out.close();
file.write(System.getProperty("line.separator"));
macros.apply(file, "LexerAcceptTail");
macros.apply(file, "LexerStateHeader");
if (ids.stateList.size() > 0) {
for (ListIterator i = ids.stateList.listIterator(); i.hasNext(); ) {
String s = (String) i.next();
macros.apply(file, "LexerStateBody",
new String[]{s, "" + i.previousIndex()});
}
} else {
macros.apply(file, "LexerStateBody",
new String[]{"INITIAL", "" + 0});
}
macros.apply(file, "LexerStateTail");
macros.apply(file, "LexerTail");
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "Lexer.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
}