/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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.Iterator;
import java.util.List;
import java.util.ListIterator;
@SuppressWarnings({"rawtypes", "unchecked"})
public class GenAnalyses extends DepthFirstAdapter {
private MacroExpander macros;
private ResolveAstIds ast_ids;
private File pkgDir;
private String pkgName;
private List elemList;
private List altList = new TypedLinkedList(AltInfoCast.instance);
private List tokenList = new TypedLinkedList(StringCast.instance);
private String mainProduction;
ElemInfo info;
// final GenAnalyses instance = this;
public GenAnalyses(ResolveAstIds ast_ids) {
this.ast_ids = ast_ids;
try {
macros = new MacroExpander(
new InputStreamReader(
getClass().getResourceAsStream("analyses.txt")));
} catch (IOException e) {
throw new RuntimeException("unable to open analyses.txt.");
}
pkgDir = new File(ast_ids.astIds.pkgDir, "analysis");
pkgName = ast_ids.astIds.pkgName.equals("") ? "analysis" : ast_ids.astIds.pkgName + ".analysis";
if (!pkgDir.exists()) {
if (!pkgDir.mkdir()) {
throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath());
}
}
}
@Override
public void inAAstProd(AAstProd node) {
if (mainProduction == null) {
mainProduction = (String) ast_ids.ast_names.get(node);
}
}
@Override
public void inATokenDef(ATokenDef node) {
tokenList.add(ast_ids.astIds.names.get(node));
}
@Override
public void inAAstAlt(AAstAlt node) {
elemList = new TypedLinkedList(ElemInfoCast.instance);
}
@Override
public void caseAProductions(AProductions node) {
}
@Override
public void inAElem(AElem node) {
info = new ElemInfo();
info.name = (String) ast_ids.ast_names.get(node);
info.type = (String) ast_ids.ast_elemTypes.get(node);
info.operator = ElemInfo.NONE;
if (node.getUnOp() != null) {
node.getUnOp().apply(new DepthFirstAdapter() {
@Override
public void caseAStarUnOp(AStarUnOp node) {
info.operator = ElemInfo.STAR;
}
@Override
public void caseAQMarkUnOp(AQMarkUnOp node) {
info.operator = ElemInfo.QMARK;
}
@Override
public void caseAPlusUnOp(APlusUnOp node) {
info.operator = ElemInfo.PLUS;
}
}
);
}
elemList.add(info);
info = null;
}
@Override
public void outAAstAlt(AAstAlt node) {
AltInfo info = new AltInfo();
info.name = (String) ast_ids.ast_names.get(node);
info.elems.addAll(elemList);
elemList = null;
altList.add(info);
}
@Override
public void outStart(Start node) {
createAnalysis();
createAnalysisAdapter();
if (mainProduction != null) {
createDepthFirstAdapter();
createReversedDepthFirstAdapter();
}
}
public void createAnalysis() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "Analysis.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "Analysis.java").getAbsolutePath());
}
try {
macros.apply(file, "AnalysisHeader", new String[]{pkgName,
ast_ids.astIds.pkgName.equals("") ? "node" : ast_ids.astIds.pkgName + ".node"});
if (mainProduction != null) {
macros.apply(file, "AnalysisStart", null);
for (Iterator i = altList.iterator(); i.hasNext(); ) {
AltInfo info = (AltInfo) i.next();
macros.apply(file, "AnalysisBody",
new String[]{info.name});
}
file.newLine();
}
for (Iterator i = tokenList.iterator(); i.hasNext(); ) {
macros.apply(file, "AnalysisBody",
new String[]{(String) i.next()});
}
macros.apply(file, "AnalysisTail", null);
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "Analysis.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
public void createAnalysisAdapter() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "AnalysisAdapter.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "AnalysisAdapter.java").getAbsolutePath());
}
try {
macros.apply(file, "AnalysisAdapterHeader", new String[]{pkgName,
ast_ids.astIds.pkgName.equals("") ? "node" : ast_ids.astIds.pkgName + ".node"});
if (mainProduction != null) {
macros.apply(file, "AnalysisAdapterStart", null);
for (Iterator i = altList.iterator(); i.hasNext(); ) {
AltInfo info = (AltInfo) i.next();
macros.apply(file, "AnalysisAdapterBody",
new String[]{info.name});
}
}
for (Iterator i = tokenList.iterator(); i.hasNext(); ) {
macros.apply(file, "AnalysisAdapterBody",
new String[]{(String) i.next()});
}
macros.apply(file, "AnalysisAdapterTail", null);
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "AnalysisAdapter.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
public void createDepthFirstAdapter() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "DepthFirstAdapter.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "DepthFirstAdapter.java").getAbsolutePath());
}
try {
macros.apply(file, "DepthFirstAdapterHeader", new String[]{pkgName,
ast_ids.astIds.pkgName.equals("") ? "node" : ast_ids.astIds.pkgName + ".node",
mainProduction});
for (Iterator i = altList.iterator(); i.hasNext(); ) {
AltInfo info = (AltInfo) i.next();
macros.apply(file, "DepthFirstAdapterInOut",
new String[]{info.name});
macros.apply(file, "DepthFirstAdapterCaseHeader",
new String[]{info.name});
for (Iterator j = info.elems.iterator(); j.hasNext(); ) {
ElemInfo eInfo = (ElemInfo) j.next();
switch (eInfo.operator) {
case ElemInfo.QMARK:
case ElemInfo.NONE: {
macros.apply(file, "DepthFirstAdapterCaseBodyNode",
new String[]{eInfo.name});
}
break;
case ElemInfo.STAR:
case ElemInfo.PLUS: {
macros.apply(file, "DepthFirstAdapterCaseBodyList",
new String[]{eInfo.name, eInfo.type});
}
break;
}
}
macros.apply(file, "DepthFirstAdapterCaseTail",
new String[]{info.name});
}
macros.apply(file, "DepthFirstAdapterTail", null);
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "DepthFirstAdapter.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
public void createReversedDepthFirstAdapter() {
BufferedWriter file;
try {
file = new BufferedWriter(
new FileWriter(
new File(pkgDir, "ReversedDepthFirstAdapter.java")));
} catch (IOException e) {
throw new RuntimeException("Unable to create " + new File(pkgDir, "ReversedDepthFirstAdapter.java").getAbsolutePath());
}
try {
macros.apply(file, "ReversedDepthFirstAdapterHeader", new String[]{pkgName,
ast_ids.astIds.pkgName.equals("") ? "node" : ast_ids.astIds.pkgName + ".node",
mainProduction});
for (Iterator i = altList.iterator(); i.hasNext(); ) {
AltInfo info = (AltInfo) i.next();
macros.apply(file, "DepthFirstAdapterInOut",
new String[]{info.name});
macros.apply(file, "DepthFirstAdapterCaseHeader",
new String[]{info.name});
for (ListIterator j = info.elems.listIterator(info.elems.size()); j.hasPrevious(); ) {
ElemInfo eInfo = (ElemInfo) j.previous();
switch (eInfo.operator) {
case ElemInfo.QMARK:
case ElemInfo.NONE: {
macros.apply(file, "DepthFirstAdapterCaseBodyNode",
new String[]{eInfo.name});
}
break;
case ElemInfo.STAR:
case ElemInfo.PLUS: {
macros.apply(file, "ReversedDepthFirstAdapterCaseBodyList",
new String[]{eInfo.name, eInfo.type});
}
break;
}
}
macros.apply(file, "DepthFirstAdapterCaseTail",
new String[]{info.name});
}
macros.apply(file, "DepthFirstAdapterTail", null);
} catch (IOException e) {
throw new RuntimeException("An error occured while writing to " +
new File(pkgDir, "ReversedDepthFirstAdapter.java").getAbsolutePath());
}
try {
file.close();
} catch (IOException e) {
}
}
private static class ElemInfo {
final static int NONE = 0;
final static int STAR = 1;
final static int QMARK = 2;
final static int PLUS = 3;
String name;
String type;
int operator;
}
private static class ElemInfoCast implements Cast {
final static ElemInfoCast instance = new ElemInfoCast();
private ElemInfoCast() {
}
@Override
public Object cast(Object o) {
return (ElemInfo) o;
}
}
private static class AltInfo {
String name;
final List elems = new TypedLinkedList(ElemInfoCast.instance);
}
private static class AltInfoCast implements Cast {
final static AltInfoCast instance = new AltInfoCast();
private AltInfoCast() {
}
@Override
public Object cast(Object o) {
return (AltInfo) o;
}
}
}