/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Last Modification date : October, the 11th 2003 * Goal of the modification : addition of specifier to * the generated production($prod) to handle list of element. * * */ package org.sablecc.sablecc; import org.sablecc.sablecc.analysis.*; import org.sablecc.sablecc.node.*; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @SuppressWarnings({"rawtypes", "unchecked"}) public class InternalTransformationsToGrammar extends DepthFirstAdapter { private ResolveIds ids; private ResolveAltIds altIds; private ResolveTransformIds transformIds; private String currentProd; // private int currentAlt; private String currentAltName; private boolean processingAst; // private boolean processingProdTransform; static final int NONE = 0; static final int STAR = 1; static final int QMARK = 2; static final int PLUS = 3; int count; int elem; private LinkedList listSimpleTermTransform; public final Map simpleTermTransform; Map mapProductionTransformations; Map simpleTermOrsimpleListTermTypes; private Map isElementIsAlist = new TypedTreeMap( StringComparator.instance, StringCast.instance, StringCast.instance); private LinkedList listProd; public InternalTransformationsToGrammar(ResolveIds ids, ResolveAltIds altIds, ResolveTransformIds transformIds, LinkedList listSimpleTermTransform, Map simpleTermTransform, Map mapProductionTransformations, Map simpleTermOrsimpleListTermTypes) { this.ids = ids; this.altIds = altIds; this.transformIds = transformIds; this.listSimpleTermTransform = listSimpleTermTransform; this.simpleTermTransform = simpleTermTransform; this.mapProductionTransformations = mapProductionTransformations; this.simpleTermOrsimpleListTermTypes = simpleTermOrsimpleListTermTypes; } @Override public void inAProductions(AProductions node) { listProd = node.getProds(); } private LinkedList listOfAlts; @Override public void inAAst(AAst node) { processingAst = true; } @Override public void outAAst(AAst node) { processingAst = false; } @Override public void caseAProd(AProd node) { currentProd = (String) ids.names.get(node); listOfAlts = new LinkedList(); Object[] list_alt = (Object[]) node.getAlts().toArray(); for (int i = 0; i < list_alt.length; i++) { ((PAlt) list_alt[i]).apply(this); } node.setAlts(listOfAlts); } private LinkedList listElems; private AAlt aParsedAlt; private LinkedList listElemsAltTransform; private String currentNewAltName; boolean countElementNecessary; LinkedList listOfAlternativeElemsWHaveName; @Override public void caseAAlt(AAlt node) { count = 1; currentAltName = (String) ids.names.get(node); AAltTransform currentAltTransform = (AAltTransform) node.getAltTransform(); listOfAlternativeElemsWHaveName = new LinkedList(); node.apply(new DepthFirstAdapter() { @Override public void inAElem(AElem node) { InternalTransformationsToGrammar.this.setOut(node, new Integer(NONE)); } @Override public void caseAStarUnOp(AStarUnOp node) { count *= 2; InternalTransformationsToGrammar.this.setOut(node.parent(), new Integer(STAR)); } @Override public void caseAQMarkUnOp(AQMarkUnOp node) { count *= 2; InternalTransformationsToGrammar.this.setOut(node.parent(), new Integer(QMARK)); } @Override public void caseAPlusUnOp(APlusUnOp node) { InternalTransformationsToGrammar.this.setOut(node.parent(), new Integer(PLUS)); } } ); if (count == 1) { listElems = new LinkedList(); listElemsAltTransform = new LinkedList(); countElementNecessary = false; Object temp[] = node.getElems().toArray(); for (int i = 0; i < temp.length; i++) { Object obj = temp[i]; if (((AElem) obj).getUnOp() != null && (((AElem) obj).getUnOp() instanceof AQMarkUnOp || ((AElem) obj).getUnOp() instanceof AStarUnOp) ) { if (!countElementNecessary) { countElementNecessary = true; } } } for (int i = 0; i < temp.length; i++) { ((PElem) temp[i]).apply(this); } TId nameOfAlt = null; if (node.getAltName() != null) { nameOfAlt = (TId) node.getAltName().clone(); } currentNewAltName = currentProd + "." + currentAltName.toLowerCase(); altIds.alts_elems.put(currentNewAltName, listElemsAltTransform); altIds.alts_elems_list_elemName.put(currentNewAltName, listOfAlternativeElemsWHaveName); AAltTransform altTransform = (AAltTransform) currentAltTransform.clone(); AltTransformAdapter altTransformAdapter = new AltTransformAdapter(simpleTermTransform, listSimpleTermTransform, currentNewAltName, altIds, isElementIsAlist, simpleTermOrsimpleListTermTypes); altTransform.apply(altTransformAdapter); aParsedAlt = new AAlt(nameOfAlt, listElems, altTransform); ids.names.put(aParsedAlt, ids.names.get(node)); listOfAlts.add(aParsedAlt); } else { int max = count; AAltTransform altTransform; for (count = 0; count < max; count++) { listElems = new LinkedList(); listElemsAltTransform = new LinkedList(); elem = 0; currentNewAltName = currentProd + "." + currentAltName.toLowerCase() + (count + 1); countElementNecessary = false; Object temp[] = node.getElems().toArray(); for (int i = 0; i < temp.length; i++) { Object obj = temp[i]; if (((AElem) obj).getUnOp() != null && (((AElem) obj).getUnOp() instanceof AQMarkUnOp || ((AElem) obj).getUnOp() instanceof AStarUnOp) ) { if (!countElementNecessary) { countElementNecessary = true; } } } for (int i = 0; i < temp.length; i++) { ((PElem) temp[i]).apply(this); } altIds.alts_elems.put(currentNewAltName, listElemsAltTransform); altIds.alts_elems_list_elemName.put(currentNewAltName, listOfAlternativeElemsWHaveName); altTransform = (AAltTransform) currentAltTransform.clone(); AltTransformAdapter altTransformAdapter = new AltTransformAdapter(simpleTermTransform, listSimpleTermTransform, currentNewAltName, altIds, isElementIsAlist, simpleTermOrsimpleListTermTypes); altTransform.apply(altTransformAdapter); aParsedAlt = new AAlt(new TId(currentAltName.toLowerCase() + (count + 1)), listElems, altTransform); String currentAltInlining; currentAltInlining = "A" + ResolveIds.name(aParsedAlt.getAltName().getText()) + currentProd; ids.names.put(aParsedAlt, currentAltInlining); listOfAlts.add(aParsedAlt); } } } LinkedList checkCreationOfXElem = new TypedLinkedList(StringCast.instance); //It's also available for Ignored alternatives @Override public void caseAElem(AElem node) { if (!processingAst) { int op = ((Integer) getOut(node)).intValue(); String name = (String) ids.elemTypes.get(node); String numero = (countElementNecessary == true ? "" + (count + 1) : ""); String qMarkOrPlusElemType; String elemNameOfElem = null; TId aElemName = null; PSpecifier specifier = null; if (node.getElemName() != null) { elemNameOfElem = node.getElemName().getText(); aElemName = new TId(elemNameOfElem); } if (node.getSpecifier() != null) { if (node.getSpecifier() instanceof ATokenSpecifier) { specifier = new ATokenSpecifier(); } else { specifier = new AProductionSpecifier(); } } AElem aElem = null; String elemName = node.getId().getText(); boolean ok = false; boolean oklist = false; switch (op) { case NONE: { aElem = new AElem(aElemName, specifier, new TId(elemName), null); if (elemNameOfElem != null) { ids.names.put(aElem, ResolveIds.name(elemNameOfElem)); } else { ids.names.put(aElem, ResolveIds.name(elemName)); } ok = true; } break; case STAR: { if ((count & (1 << elem)) != 0) { qMarkOrPlusElemType = (String) ids.elemTypes.get(node); LinkedList tmpProdTransform = (LinkedList) mapProductionTransformations.get(qMarkOrPlusElemType); if (!checkCreationOfXElem.contains("$" + elemName)) { checkCreationOfXElem.add("$" + elemName); listProd.add(createXelemProduction("$" + elemName, qMarkOrPlusElemType, name, tmpProdTransform)); } elemName = "$" + elemName; aElem = new AElem(aElemName, new AProductionSpecifier(), new TId(elemName), null); if (elemNameOfElem != null) { ids.names.put(aElem, ResolveIds.name(elemNameOfElem)); } else { ids.names.put(aElem, ResolveIds.name(elemName)); } ok = true; oklist = true; } elem++; } break; case QMARK: { if ((count & (1 << elem)) != 0) { aElem = new AElem(aElemName, specifier, new TId(elemName), null); if (elemNameOfElem != null) { ids.names.put(aElem, ResolveIds.name(elemNameOfElem)); } else { ids.names.put(aElem, ResolveIds.name(elemName)); } ok = true; } elem++; } break; case PLUS: { qMarkOrPlusElemType = (String) ids.elemTypes.get(node); LinkedList tmpProdTransform = (LinkedList) mapProductionTransformations.get(qMarkOrPlusElemType); if (!checkCreationOfXElem.contains("$" + elemName)) { checkCreationOfXElem.add("$" + elemName); listProd.add(createXelemProduction("$" + elemName, qMarkOrPlusElemType, name, tmpProdTransform)); } elemName = "$" + elemName; aElem = new AElem(aElemName, new AProductionSpecifier(), new TId(elemName), null); if (elemNameOfElem != null) { ids.names.put(aElem, ResolveIds.name(elemNameOfElem)); } else { ids.names.put(aElem, ResolveIds.name(elemName)); } ok = true; oklist = true; } break; } if (ok) { if (aElemName != null) { listElemsAltTransform.add(aElemName.getText()); if (oklist) { if (elemNameOfElem != null) { listOfAlternativeElemsWHaveName.add(elemNameOfElem); } isElementIsAlist.put(currentProd + "." + currentAltName.toLowerCase() + numero + aElemName.getText(), node.getId().getText()); } } else { listElemsAltTransform.add(elemName); if (oklist) { if (elemNameOfElem != null) { listOfAlternativeElemsWHaveName.add(elemNameOfElem); } isElementIsAlist.put(currentProd + "." + currentAltName.toLowerCase() + numero + node.getId().getText(), node.getId().getText()); } } } if (aElem != null) { listElems.add(aElem); } } } /* This method creates the production for star(*) and plus(+) substitution in the grammar elem* -> $elem | elem This creates the production :: $elem {-> elem* } = {nonTerminal} $elem elem {-> [$elem.elem elem] } | {terminal} elem {-> [elem] } ; */ public AProd createXelemProduction(final String name, final String elemTypeName, String XproductionName, LinkedList nodeProdTransform) { final String rname = name.substring(1); LinkedList listOfAltsXelem = new LinkedList(); if (nodeProdTransform != null) { nodeProdTransform = (LinkedList) cloneList(nodeProdTransform); //Creation of the production transformation for Xelem //if the production transformation is introduced by the software if (nodeProdTransform.size() == 1) { AElem elem = (AElem) nodeProdTransform.get(0); if (elem.getUnOp() == null && elem.getId().getText().equals(rname)) { LinkedList elemsProdTransform = new LinkedList(); elemsProdTransform.add(new AElem(null, new AProductionSpecifier(), new TId(rname), new AStarUnOp())); nodeProdTransform = elemsProdTransform; } } } //That means elem is token type else { // String name_resolved = ResolveIds.name(name); LinkedList elemsProdTransform = new LinkedList(); elemsProdTransform.add(new AElem(null, new ATokenSpecifier(), new TId(rname), new AStarUnOp())); nodeProdTransform = elemsProdTransform; } final LinkedList listProdTransformationOfXelem = new LinkedList(); AElem[] temp_listProdTransform = (AElem[]) nodeProdTransform.toArray(new AElem[0]); for (int i = 0; i < temp_listProdTransform.length; i++) { temp_listProdTransform[i].apply(new DepthFirstAdapter() { @Override public void caseAElem(AElem node) { //The production transformation needs to have a star operator. node.setUnOp(new AStarUnOp(new TStar())); if (node.getElemName() != null) { listProdTransformationOfXelem.add(node.getElemName().getText()); } else { listProdTransformationOfXelem.add(node.getId().getText()); } } } ); } //creation of the first AltTransform node AElem[] prodTransformElems = (AElem[]) nodeProdTransform.toArray(new AElem[0]); final LinkedList listTerms_first = new LinkedList(); for (int i = 0; i < prodTransformElems.length; i++) { prodTransformElems[i].apply(new AnalysisAdapter() { @Override public void caseAElem(AElem node) { String tmpNodeName = ((node.getElemName() == null) ? node.getId().getText() : node.getElemName().getText()); LinkedList listAListTerm_first = new LinkedList(); if (elemTypeName.startsWith("T")) { listAListTerm_first.add(new ASimpleListTerm(new ATokenSpecifier(), new TId(rname), null)); } else { listAListTerm_first.add(new ASimpleListTerm(new AProductionSpecifier(), new TId(rname), new TId(tmpNodeName))); } listTerms_first.add(new AListTerm(new TLBkt(), listAListTerm_first)); } } ); } AAltTransform aAltTransform = new AAltTransform(new TLBrace(), listTerms_first, new TRBrace()); //create the first list of elems of an alternative LinkedList elems = new LinkedList(); AElem aElemFirstTobeAdded; //the elem is a token if (elemTypeName.startsWith("T")) { aElemFirstTobeAdded = new AElem(null, new ATokenSpecifier(), new TId(rname), null); } else { aElemFirstTobeAdded = new AElem(null, new AProductionSpecifier(), new TId(rname), null); } elems.add(aElemFirstTobeAdded); //creation of the first alternative AAlt aParsedAlt = new AAlt(new TId("terminal"), elems, aAltTransform); // String terminal_altName = "ATerminal" + ResolveIds.name(name); listOfAltsXelem.add(aParsedAlt); //create the second AltTransform node prodTransformElems = (AElem[]) nodeProdTransform.toArray(new AElem[0]); final LinkedList listTerms_second = new LinkedList(); for (int i = 0; i < prodTransformElems.length; i++) { prodTransformElems[i].apply(new AnalysisAdapter() { @Override public void caseAElem(AElem node) { String tmpNodeName = ((node.getElemName() == null) ? node.getId().getText() : node.getElemName().getText()); LinkedList listAListTerm_second = new LinkedList(); listAListTerm_second.add(new ASimpleListTerm(null, new TId(name), new TId(tmpNodeName))); if (elemTypeName.startsWith("T")) { listAListTerm_second.add(new ASimpleListTerm(new ATokenSpecifier(), new TId(rname), null)); } else { listAListTerm_second.add(new ASimpleListTerm(new AProductionSpecifier(), new TId(rname), new TId(tmpNodeName))); } listTerms_second.add(new AListTerm(new TLBkt(), listAListTerm_second)); } } ); } aAltTransform = new AAltTransform(new TLBrace(), listTerms_second, new TRBrace()); //creation of the second list of elems of an alternative :: two elems elems = new LinkedList(); //first elem AElem aElemSecondTobeAdded = new AElem(null, new AProductionSpecifier(), new TId(name), null); elems.add(aElemSecondTobeAdded); //second elem if (elemTypeName.startsWith("T")) { aElemSecondTobeAdded = new AElem(null, new ATokenSpecifier(), new TId(rname), null); } else { aElemSecondTobeAdded = new AElem(null, new AProductionSpecifier(), new TId(rname), null); } elems.add(aElemSecondTobeAdded); aParsedAlt = new AAlt(new TId("non_terminal"), elems, aAltTransform); // String nonTerminal_altName = "ANonTerminal" + ResolveIds.name(name); listOfAltsXelem.add(aParsedAlt); AProd prodToReturn = new AProd(new TId(name), new TArrow(), nodeProdTransform, listOfAltsXelem); prodToReturn.apply(ids); prodToReturn.apply(transformIds.getProdTransformIds()); return prodToReturn; } private List cloneList(List list) { List clone = new LinkedList(); for (Iterator i = list.iterator(); i.hasNext(); ) { clone.add(((Node) i.next()).clone()); } return clone; } /* private String xproductionType(String name) { return "P$" + name.substring(1).toLowerCase(); } */ }