/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; @SuppressWarnings({"rawtypes", "unchecked"}) public class GenAlts extends DepthFirstAdapter { private MacroExpander macros; private ResolveAstIds ast_ids; private File pkgDir; private String pkgName; private List elemList; private String currentProd; ElemInfo info; // final GenAlts instance = this; public GenAlts(ResolveAstIds ast_ids) { this.ast_ids = ast_ids; try { macros = new MacroExpander( new InputStreamReader( getClass().getResourceAsStream("alternatives.txt"))); } catch (IOException e) { throw new RuntimeException("unable to open alternatives.txt."); } pkgDir = new File(ast_ids.astIds.pkgDir, "node"); pkgName = ast_ids.astIds.pkgName.equals("") ? "node" : ast_ids.astIds.pkgName + ".node"; if (!pkgDir.exists()) { if (!pkgDir.mkdir()) { throw new RuntimeException("Unable to create " + pkgDir.getAbsolutePath()); } } } @Override public void inAAstProd(AAstProd node) { currentProd = (String) ast_ids.ast_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) { String name = (String) ast_ids.ast_names.get(node); BufferedWriter file; try { file = new BufferedWriter( new FileWriter( new File(pkgDir, name + ".java"))); } catch (IOException e) { throw new RuntimeException("Unable to create " + new File(pkgDir, name + ".java").getAbsolutePath()); } try { // boolean hasOperator = false; boolean hasList = false; for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.STAR: case ElemInfo.PLUS: { hasList = true; } break; } } macros.apply(file, "AlternativeHeader1", new String[]{pkgName}); if (hasList) { macros.apply(file, "AlternativeHeaderList", new String[]{}); } macros.apply(file, "AlternativeHeader2", new String[]{ ast_ids.astIds.pkgName.equals("") ? "analysis" : ast_ids.astIds.pkgName + ".analysis", name, currentProd}); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "NodeElement", new String[]{info.type, nodeName(info.name)}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { // hasOperator = true; macros.apply(file, "ListElement", new String[]{info.type, nodeName(info.name)}); } break; } } macros.apply(file, "ConstructorHeader", new String[]{name}); macros.apply(file, "ConstructorBodyHeader", null); macros.apply(file, "ConstructorBodyTail", null); if (elemList.size() > 0) { macros.apply(file, "ConstructorHeader", new String[]{name}); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "ConstructorHeaderDeclNode", new String[]{info.type, nodeName(info.name), i.hasNext() ? "," : ""}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "ConstructorHeaderDeclList", new String[]{info.type, nodeName(info.name), i.hasNext() ? "," : ""}); } break; } } macros.apply(file, "ConstructorBodyHeader", null); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "ConstructorBodyNode", new String[]{info.name, nodeName(info.name)}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "ConstructorBodyList", new String[]{info.name, nodeName(info.name)}); } break; } } macros.apply(file, "ConstructorBodyTail", null); } //**************** macros.apply(file, "CloneHeader", new String[]{name}); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "CloneBodyNode", new String[]{info.type, nodeName(info.name), i.hasNext() ? "," : ""}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "CloneBodyList", new String[]{nodeName(info.name), i.hasNext() ? "," : ""}); } break; } } macros.apply(file, "CloneTail", null); macros.apply(file, "Apply", new String[]{name}); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "GetSetNode", new String[]{info.type, info.name, nodeName(info.name)}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "GetSetList", new String[]{info.name, nodeName(info.name), info.type}); } break; } } macros.apply(file, "ToStringHeader", null); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "ToStringBodyNode", new String[]{nodeName(info.name)}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "ToStringBodyList", new String[]{nodeName(info.name)}); } break; } } macros.apply(file, "ToStringTail", null); macros.apply(file, "RemoveChildHeader", null); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "RemoveChildNode", new String[]{nodeName(info.name)}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "RemoveChildList", new String[]{nodeName(info.name)}); } break; } } macros.apply(file, "RemoveChildTail", null); macros.apply(file, "ReplaceChildHeader", null); for (Iterator i = elemList.iterator(); i.hasNext(); ) { ElemInfo info = (ElemInfo) i.next(); if (info != null) switch (info.operator) { case ElemInfo.QMARK: case ElemInfo.NONE: { macros.apply(file, "ReplaceChildNode", new String[]{nodeName(info.name), info.name, info.type}); } break; case ElemInfo.STAR: case ElemInfo.PLUS: { macros.apply(file, "ReplaceChildList", new String[]{nodeName(info.name), info.type}); } break; } } macros.apply(file, "ReplaceChildTail", null); macros.apply(file, "AlternativeTail", null); } catch (IOException e) { throw new RuntimeException("An error occured while writing to " + new File(pkgDir, name + ".java").getAbsolutePath()); } try { file.close(); } catch (IOException e) { } elemList = null; } public static String nodeName(String s) { StringBuffer result = new StringBuffer(s); if (result.length() > 0) { result.setCharAt(0, Character.toLowerCase(result.charAt(0))); } return result.toString(); } 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 { public final static ElemInfoCast instance = new ElemInfoCast(); private ElemInfoCast() { } @Override public Object cast(Object o) { return (ElemInfo) o; } } }