/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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.util.LinkedList; import java.util.Map; /* * ResolveProdTransformIds * * This class computes semantic verifications for production transformations * in Production section. It makes sure that all transformations specified * for a production(prod {-> prod_transform1 prod_transform2 prod_transform3...}) * are defined as production in the section Abstract Syntax Tree. */ @SuppressWarnings({"rawtypes", "unchecked"}) public class ResolveProdTransformIds extends DepthFirstAdapter { private ResolveAstIds transformIds; private LinkedList listElems; private String prod_name; public LinkedList listProdTransformList = new LinkedList(); private LinkedList listProdTransformContainsList; //Map of production transformation element type. The key of this map //is the node of this element in the AST. public final Map prodTransformElemTypes = new TypedHashMap( NoCast.instance, StringCast.instance); //This map contains the same information as the other one just above. //But the keys for this map are String ("ProdName.ElemTransformationName") public final Map prodTransformElemTypesString = new TypedHashMap( StringCast.instance, StringCast.instance); //Map of Productions which transformations contains list elements. public Map mapProdTransformContainsList = new TypedTreeMap( StringComparator.instance, StringCast.instance, ListCast.instance); //Map of all Production transformations elements. public final Map prod_transforms = new TypedTreeMap( StringComparator.instance, StringCast.instance, NoCast.instance); public ResolveProdTransformIds(ResolveAstIds ids) { transformIds = ids; } @Override public void caseAProd(final AProd production) { prod_name = (String) transformIds.astIds.names.get(production); AElem temp[] = (AElem[]) production.getProdTransform().toArray(new AElem[0]); listProdTransformContainsList = new LinkedList(); listElems = new LinkedList(); if (temp.length > 1) { listProdTransformList.add(prod_name); } for (int i = 0; i < temp.length; i++) { ((PElem) temp[i]).apply(new DepthFirstAdapter() { @Override public void caseAElem(AElem node) { String rname = node.getId().getText(); String name = ResolveIds.name(rname); String elemName = null; if (node.getElemName() != null) { elemName = node.getElemName().getText(); if (listElems.contains(elemName)) { error(node.getElemName(), elemName); } listElems.add(elemName); } else { if (listElems.contains(rname)) { error(node.getId(), rname); } listElems.add(rname); } if ((node.getUnOp() != null) && ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof APlusUnOp))) { listProdTransformList.add(prod_name); if (node.getElemName() != null) { listProdTransformContainsList.add(elemName); } else { listProdTransformContainsList.add(node.getId().getText()); } } if (node.getSpecifier() != null) { if (node.getSpecifier() instanceof ATokenSpecifier) { if (transformIds.astIds.tokens.get("T" + name) == null) { error2(node.getId(), "T" + name); } if (transformIds.astIds.ignTokens.get("T" + name) != null) { error3(node.getId(), "T" + name); } /*****************************************************/ String type_name = name; if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof AQMarkUnOp)) { type_name += "?"; } if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof APlusUnOp)) { prodTransformElemTypes.put(node, "LT" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "LT" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "LT" + type_name); } } else { prodTransformElemTypes.put(node, "T" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "T" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "T" + type_name); } } } else { if (transformIds.ast_prods.get("P" + name) == null) { error5(node.getId(), "P" + name); } /*****************************************************/ String type_name = name; if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof AQMarkUnOp)) { type_name += "?"; } if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof APlusUnOp)) { prodTransformElemTypes.put(node, "LP" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "LP" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "LP" + type_name); } } else { prodTransformElemTypes.put(node, "P" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "P" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "P" + type_name); } } } } else { Object token = transformIds.astIds.tokens.get("T" + name); // Object ignToken = transformIds.astIds.ignTokens.get("T" + name); Object production = transformIds.astIds.prods.get("P" + name); Object ast_production = transformIds.ast_prods.get("P" + name); if ((token == null) && (ast_production == null) && (production == null)) { error2(node.getId(), "P" + name + " and T" + name); } //it seems to be a token if (token != null) { // boolean bast_production = false; //if it's also a ast_production if (ast_production != null) { error4(node.getId(), "P" + name + " and T" + name); } /*****************************************************/ String type_name = name; if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof AQMarkUnOp)) { type_name += "?"; } if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof APlusUnOp)) { prodTransformElemTypes.put(node, "LT" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "LT" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "LT" + type_name); } } else { prodTransformElemTypes.put(node, "T" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "T" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "T" + type_name); } } } // The element is supposed to be a Production in section AST else { if (ast_production == null) { error5(node.getId(), node.getId().getText()); } /*****************************************************/ String type_name = name; if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof AQMarkUnOp)) { type_name += "?"; } if ((node.getUnOp() instanceof AStarUnOp) || (node.getUnOp() instanceof APlusUnOp)) { prodTransformElemTypes.put(node, "LP" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "LP" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "LP" + type_name); } } else { prodTransformElemTypes.put(node, "P" + type_name); if (elemName != null) { prodTransformElemTypesString.put(prod_name + "." + elemName, "P" + type_name); } else { prodTransformElemTypesString.put(prod_name + "." + rname, "P" + type_name); } } } } } } ); } prod_transforms.put(prod_name, listElems); mapProdTransformContainsList.put(prod_name, listProdTransformContainsList); } private static void error(Token token, String name) { throw new RuntimeException( "[" + token.getLine() + "," + token.getPos() + "] " + "Redefinition of " + name + "."); } private static void error2(Token token, String name) { throw new RuntimeException( "[" + token.getLine() + "," + token.getPos() + "] " + name + " undefined."); } private static void error3(Token token, String name) { throw new RuntimeException( "[" + token.getLine() + "," + token.getPos() + "] " + name + " is ignored."); } private static void error4(Token token, String name) { throw new RuntimeException( "[" + token.getLine() + "," + token.getPos() + "] " + "ambiguous " + name + "."); } private static void error5(Token token, String name) { throw new RuntimeException( "[" + token.getLine() + "," + token.getPos() + "] " + name + " must be a production defined in section AST."); } }