Package printer

Source Code of printer.PrintClangCsvPlugin$CallWriteCsvForEntity

package printer;

import java.io.BufferedWriter;
import java.util.Iterator;
import speclistener.SpecBaseListener;
import symboltable.ASTNode;
import symboltable.Constructor;
import symboltable.ContainsProperties;
import symboltable.Entity;
import symboltable.EntityProperty;
import symboltable.EnumProperty;
import symboltable.Enumeration;
import symboltable.ExistentialProperty;
import symboltable.ExprForASTElement;
import symboltable.IntProperty;
import symboltable.NodeProperty;
import symboltable.Property;
import symboltable.StringProperty;
import symboltable.SymbolTable;
import static util.PrintUtil.writeToFile;
import static util.PrintUtil.quote;
import visitor.forContainsProperties.ContainsPropertiesVisitorRv;

//TODO: handle uniformly identetion calls and code gen calls

/**
*
* @author kostasferles
*/
public class PrintClangCsvPlugin extends SpecBaseListener{

    private BufferedWriter output;
   
    private int ident = 0;
   
    private String identStr = "";
   
    private  SymbolTable table = SymbolTable.getInstance();
   
    /*
     * REVIEW: Is there a way to parameterize these strings?
     */
    private final String targetConsName = "getConstructorProperties";
   
    private final String consListArg = "vector<string>&";
   
    private final String consListArgName = "l";
   
    private final String aggrListName = "aggr";
   
    private final String relationListName = "rel";
   
    private final String writerName = "writer";
   
    private final String callToWriteLine = "writeLine";
   
    private final String csvWriteMethoForEntities = "writeCsvFor";
   
    /*
     * TODO: If any of these methods are more useful for other classes, move them to PrintUtility
     */
    private String identMethodDecl(String s){
        return this.identStr + s;
    }
   
    private void insertIndentation(){
        for(int i = 0 ; i < this.ident ; i++)
            writeToFile(this.output, "  ");
    }
   
    private void increaseIdent(){
        this.ident++;
        this.identStr += "  ";
    }
   
    private void decreaseIdent(){
        this.ident--;
        if(this.ident > 0)
            this.identStr = this.identStr.substring(0, this.identStr.length() - 2);
    }
   
    private StringBuilder identMethodDeclAndField(StringBuilder in){
        return in.append(identStr);
    }
   
    private StringBuilder identMethodBody(StringBuilder in){
        return in.append(identStr).append("  ");
    }
   
    private String identMethodBody(String s){
        return this.identStr + "  " + s;
    }
   
    private String callToString(ExprForASTElement elem){
        return "toString(" + elem.getCodeForElement() + ")";
    }
   
    private String callToString(String elem){
        return "toString(" + elem + ")";
    }
   
    private StringBuilder getParameters(StringBuilder in, String... params){
        in.append("(");
        if(params.length > 0){
            in.append(params[0]);
            for(int i = 1 ; i < params.length ; ++i){
                in = in.append(", ").append(params[i]);
            }
        }
        in.append(")");
       
        return in;
    }
   
    private StringBuilder getMethodDeclHead(StringBuilder in, String rv, String methodName, String... params){
        in = in.append(identMethodDecl(rv)).append(" ").append(methodName);
       
        in = getParameters(in, params);
        in.append("{\n");
        return in;
    }
   
    private StringBuilder getMethodCall(StringBuilder in, String receiver, String operator, String methodName, String... params){
        in = in.append(receiver).append(operator).append(methodName);
       
        in = getParameters(in, params);
        in.append(";\n");
        return in;
    }
   
    private StringBuilder getMethodFooter(StringBuilder in){
        return in.append(identMethodDecl("}\n"));
    }
   
    private class CallWriteCsvForEntity implements ContainsPropertiesVisitorRv<Boolean>{

        @Override
        public Boolean visit(ASTNode n) {
            return false;
        }

        @Override
        public Boolean visit(Entity en) {
            return true;
        }
       
    }
   
    private CallWriteCsvForEntity condVis = new CallWriteCsvForEntity();
   
    private String generateCodeForProperty(Property p, boolean callWriteCsv4Entity){
        StringBuilder rv = new StringBuilder();
        Property.Type t = p.getType();
        ContainsProperties elem = p.getParent();

        Constructor cons = elem.getConstructor();
        boolean consProperty = !p.isOptional() && cons.getParent() == elem && cons.containsProperty(p);
        String nodeName = elem.getName();
        String propertyName = p.getName();
        String lbPropertyName = nodeName + ':' + propertyName;
       
        switch(t){
            case OneToOne:
            case ManyToOne:
               
                ExprForASTElement expr = p.getExprForValue();
                if(callWriteCsv4Entity && !p.isOptional()){
                    identMethodBody(rv);
                    rv = getMethodCall(rv, "this", "->", csvWriteMethoForEntities, expr.getCodeForElement());
                }
               
                if(!consProperty){
                    if(!p.isOptional()){
                        rv = identMethodBody(rv);
                        rv = getMethodCall(rv, aggrListName, ".", "push_back", callToString(expr));
                    }
                    else{
                        identMethodBody(rv).
                        append("if(").append(p.getCond()).append("){\n");
                       
                        //TODO: make a method for this group of calls
                        getMethodCall(identMethodBody(rv).append("  "), relationListName, ".", "push_back", callToString(expr));
                        getMethodCall(identMethodBody(rv).append("  "), writerName, "->", callToWriteLine, quote(lbPropertyName), "&"+relationListName);
                        getMethodCall(identMethodBody(rv).append("  "), relationListName, ".", "pop_back");
                        if(callWriteCsv4Entity){
                            getMethodCall(identMethodBody(rv).append("  "), "this", "->", csvWriteMethoForEntities, expr.getCodeForElement());
                        }
                        identMethodBody(rv).append("}\n");
                    }
                }
                break;
            case OneToMany:
            case ManyToMany:
                assert !consProperty;
                boolean isOptional = p.isOptional();
                if(isOptional){
                    identMethodBody(rv).append("if(").
                                        append(p.getCond()).
                                        append("){\n");
                }
                if(p.hasIterators()){
                    String valName = p.getValueName();
                    String iterHead = nodeName + '_' + propertyName + '_' + valName;
                    String iteratorStart = iterHead + "_start";
                    String iteratorEnd = iterHead + "_end";
                    String index = iterHead + "_index";
                    //TODO: if target language type is missing throw exception
                    String targetLangType = p.getTargetLangType();
                   
                    if(p.isOrdered()){
                        identMethodBody(rv.append(isOptional ? "  " : "")).
                        append("int ").append(index).append(" = 0;\n");
                    }
                   
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).
                         append(targetLangType).
                         append(" ").
                         append(iteratorEnd).
                         append(" = ").
                         append(p.getExprEnd().getCodeForElement()).
                         append(";\n");

                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).
                         append("for(").
                         append(targetLangType).
                         append(" ").
                         append(iteratorStart).
                         append(" = ").
                         append(p.getExprStart().getCodeForElement()).
                         append(" ;\n");
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).
                         append("    ").
                         append(iteratorStart).
                         append(" != ").
                         append(iteratorEnd).
                         append(" ;\n");
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).
                         append("    ").
                         append(iteratorStart).
                         append("++) {\n");

                    String commandForIt = (p.needsDeref() ? "*" : "") + iteratorStart;

                    if(callWriteCsv4Entity){
                        identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                        getMethodCall(rv, "this", "->", csvWriteMethoForEntities, commandForIt);
                    }


                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                    rv = getMethodCall(rv, relationListName, ".", "push_back", callToString(commandForIt));
                    if(p.isOrdered()){
                        identMethodBody(rv.append(isOptional ? " " : "")).append("  ");
                        getMethodCall(rv, relationListName, ".", "push_back", callToString(index));
                        identMethodBody(rv.append(isOptional ? " " : "")).append("  ");
                        rv.append(index).append("++;\n");
                    }
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                    rv = getMethodCall(rv, writerName, "->", callToWriteLine, quote(lbPropertyName), "&"+relationListName);
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                    rv = getMethodCall(rv, relationListName, ".", "pop_back");

                     if(p.isOrdered()){
                        rv = identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                        rv = getMethodCall(rv, relationListName, ".", "pop_back");
                     }
                   
                    rv = identMethodBody(rv.append(isOptional ? "  " : "")).append("}\n");
                }
                else{
                    String commandForVal = p.getExprForValue().getCodeForElement();
                    if(callWriteCsv4Entity){
                        identMethodBody(rv.append(isOptional ? "  " : "")).append("  ");
                        getMethodCall(rv, "this", "->", csvWriteMethoForEntities, commandForVal);
                    }
                    getMethodCall(identMethodBody(rv.append(isOptional ? "  " : "")), relationListName, ".", "push_back", callToString(commandForVal));
                    getMethodCall(identMethodBody(rv.append(isOptional ? "  " : "")), writerName, "->", callToWriteLine, quote(lbPropertyName), "&" + relationListName);
                    getMethodCall(identMethodBody(rv.append(isOptional ? "  " : "")), relationListName, ".", "pop_back");
                }
               
                if(isOptional)
                        identMethodBody(rv).append("}");
                rv.append("\n");
                break;
            case Existential:
                assert !consProperty;
                identMethodBody(rv).append("if(").append(p.getExprForValue().getCodeForElement()).append(")\n");
                identMethodBody(rv).append("  ");
                getMethodCall(rv, writerName, "->", callToWriteLine, quote(lbPropertyName), "&" + relationListName);
                rv.append("\n");
                break;
            default:
                assert false;
        }
        return rv.toString();
    }
   
    private void generateCodeForConstructor(Constructor cons){
        StringBuilder conStr = new StringBuilder();

        ContainsProperties conParentNode = cons.getParent();
        String consThisName = conParentNode.getThisName();
        String consTargetType = conParentNode.getTargetLangType();
        conStr = getMethodDeclHead(conStr, "void", targetConsName, consTargetType + " " + consThisName, consListArg + consListArgName);

        Iterator<Property> it = cons.getProperties();


        while(it.hasNext()){

            Property pr = it.next();

            ExprForASTElement expr = pr.getExprForValue();
            conStr = conStr.append(identMethodBody(consListArgName)).
                            append(".push_back(").
                            append(callToString(expr)).
                            append(");\n");
        }

        conStr = getMethodFooter(conStr);
        conStr.append("\n");
        conStr = getMethodDeclHead(conStr, "string", "toString", consTargetType + " " + consThisName);
        identMethodBody(conStr).append("const string delim = ").append(writerName).append("->getDelim();\n");
        identMethodBody(conStr).append("ostringstream rv;\n");
        it = cons.getProperties();

        Property pr = it.next();
        assert pr.getExprForValue() != null;
        conStr = identMethodBody(conStr).append("rv << ").append(callToString(pr.getExprForValue()));


        while(it.hasNext()){
            assert pr.getExprForValue() != null;
            pr = it.next();
            ExprForASTElement expr = pr.getExprForValue();
            conStr = identMethodBody(conStr.append("\n")).append("      ");
            conStr = conStr.append(" << delim <<").append(callToString(expr));
        }

        conStr.append(";\n");
        identMethodBody(conStr).append("return rv.str();\n");
        conStr = getMethodFooter(conStr).append("\n");
        writeToFile(this.output, conStr.toString());
    }
   
    public PrintClangCsvPlugin(BufferedWriter output){
        this.output = output;
    }
   
    @Override
    public void enter(){
        String header = this.table.getHeader();
        String members = this.table.getMembers();
       
        if(header != null){
            writeToFile(this.output, header);
            writeToFile(this.output, "\n");
        }
       
        String clangSpecName = this.table.getClangSpecName();
       
        writeToFile(this.output, "namespace {\n");
        this.increaseIdent();
        this.insertIndentation();
        writeToFile(this.output, "class ");
        writeToFile(this.output, clangSpecName);
        writeToFile(this.output, " : public RecursiveASTVisitor<");
        writeToFile(this.output, clangSpecName);
        writeToFile(this.output, "> {\n");
        this.insertIndentation();
        writeToFile(this.output, "public:\n");
        this.increaseIdent();
        if(members != null){
            this.insertIndentation();
            members = members.replaceAll("\n", "\n" + identStr);
            writeToFile(this.output, members);
            writeToFile(this.output, "\n");
        }
    }
   
    @Override
    public void enterEnumNode(Enumeration e){
        StringBuilder enumStr = new StringBuilder();
        String paramName = "enumeration";
        String prefix = e.getPrefix();
        String enumName = e.getName();
        String enumType = prefix != null ? prefix + "::" + enumName : enumName;
        enumStr = getMethodDeclHead(enumStr, "string", "toString", enumType + " " + paramName);

        enumStr = identMethodBody(enumStr).
                  append("switch(").append(paramName).append("){\n");

        Iterator<String> enumerators = e.getEnumerators();

        int i = 0;
        while(enumerators.hasNext()){
            String enumerator = enumerators.next();
            enumerator = prefix != null ? prefix + "::" + enumerator : enumerator ;
            enumStr = identMethodBody(enumStr).
                      append("case ").append(enumerator).append(":\n");
            enumStr = identMethodBody(enumStr).
                      append("  return ").append(quote(Integer.toString(i++))).append(";\n");
        }
        enumStr = identMethodBody(enumStr).append("}\n");
        enumStr = identMethodBody(enumStr).append("return \"\";\n");
        enumStr = identMethodDeclAndField(enumStr).append("}\n");
        writeToFile(this.output, enumStr.toString());
        writeToFile(this.output, "\n");
    }
    //TODO: error message if there is no targetLangType for both ASTNodes and Entities
    //TODO: group the code generation code for caching nodes and entities
    @Override
    public void enterAstNode(ASTNode n){
       
        Constructor cons = n.getConstructor();
       
        if(cons.getParent() == n){
            generateCodeForConstructor(cons);
        }
       
        StringBuilder nodeHeadStr = new StringBuilder();
        String nodeName = n.getName();
        String paramName = n.getThisName();
        String setNodeName = "alreadyVisited" + nodeName;
       
        if(n.needsCache())
            identMethodDeclAndField(nodeHeadStr).append("boost::unordered_set<string> ").append(setNodeName).append(";\n\n");
       
        nodeHeadStr = getMethodDeclHead(nodeHeadStr, "bool", "Visit" + nodeName, n.getTargetLangType() + " " + paramName);
       
        if(n.needsCache()){
            identMethodBody(nodeHeadStr).append("string consS = ").
                                         append(callToString(paramName)).
                                         append(";\n");
           
            identMethodBody(nodeHeadStr).append("if(").
                                         append(setNodeName).
                                         append(".find(consS) != ").
                                         append(setNodeName).
                                         append(".end())\n");
           
            identMethodBody(nodeHeadStr).append("  return true;\n\n");
            getMethodCall(identMethodBody(nodeHeadStr), setNodeName, ".", "insert", "consS");
        }
       
        nodeHeadStr = identMethodBody(nodeHeadStr);
        nodeHeadStr = nodeHeadStr.append("vector<string> ").
                                  append(aggrListName).
                                  append(";\n");

        nodeHeadStr = identMethodBody(nodeHeadStr);
        nodeHeadStr = getMethodCall(nodeHeadStr, "this", "->", targetConsName, paramName, aggrListName);

        nodeHeadStr = identMethodBody(nodeHeadStr).
                      append("vector<string> ").
                      append(relationListName).
                      append(" = ").
                      append(aggrListName).
                      append(";\n");
       
        writeToFile(this.output, nodeHeadStr.toString());
    }

    @Override
    public void enterEntity(Entity e){
        Constructor cons = e.getConstructor();
       
        if(cons.getParent() == e){
            generateCodeForConstructor(cons);
        }
       
        StringBuilder entityHeadStr = new StringBuilder();
       
        String entityName = e.getName();
        String paramName = e.getThisName();
        String targetLangType = e.getTargetLangType();
        String setFieldName = "alreadyVisited" + entityName;
       
        identMethodDeclAndField(entityHeadStr).append("boost::unordered_set<string> ").append(setFieldName).append(";\n\n");
        entityHeadStr = getMethodDeclHead(entityHeadStr, "void", csvWriteMethoForEntities, targetLangType + " " + paramName);
       
        identMethodBody(entityHeadStr).append("string consS = ").
                                       append(callToString(paramName)).
                                       append(";\n");
       
        identMethodBody(entityHeadStr).append("if(").
                                       append(setFieldName).
                                       append(".find(consS) != ").
                                       append(setFieldName).
                                       append(".end())\n");
       
        identMethodBody(entityHeadStr).append("  return ;\n\n");
       
        identMethodBody(entityHeadStr).append("vector<string> ").
                                       append(aggrListName).
                                       append(";\n");
       
        identMethodBody(entityHeadStr);
        entityHeadStr = getMethodCall(entityHeadStr, "this", "->", targetConsName, paramName, aggrListName);

        identMethodBody(entityHeadStr).append("vector<string> ").
                                       append(relationListName).
                                       append(" = ").
                                       append(aggrListName).
                                       append(";\n");
       
        getMethodCall(identMethodBody(entityHeadStr), setFieldName, ".", "insert", "consS");
       
        getMethodCall(identMethodBody(entityHeadStr), "this", "->", csvWriteMethoForEntities, e.getThisName());
       
        writeToFile(output, entityHeadStr.toString());
    }
   
   
    @Override
    public void enterStringProperty(StringProperty sp){
        String propStr = generateCodeForProperty(sp, false);
        writeToFile(output, propStr);
    }
   
    @Override
    public void enterIntProperty(IntProperty ip){
        String propStr = generateCodeForProperty(ip, false);
        writeToFile(output, propStr);
    }
   
    @Override
    public void enterEnumProperty(EnumProperty ep){
        String propStr = generateCodeForProperty(ep, false);
        writeToFile(output, propStr);
    }

    @Override
    public void enterNodeProperty(NodeProperty np){
        String propStr = generateCodeForProperty(np, false);
        writeToFile(output, propStr);
    }
   
    @Override
    public void enterEntityProperty(EntityProperty ep){
        String propStr = generateCodeForProperty(ep, true);
        writeToFile(output, propStr);
    }
   
    @Override
    public void enterExistentialProperty(ExistentialProperty ep){
        String propStr = generateCodeForProperty(ep, ep.getParent().accept(condVis));
        writeToFile(output, propStr);
    }

    @Override
    public void exitAstNode(ASTNode n){
        StringBuilder nodeFooterStr = new StringBuilder();
        nodeFooterStr = identMethodBody(nodeFooterStr);
        nodeFooterStr = getMethodCall(nodeFooterStr, writerName, "->", callToWriteLine, quote(n.getName()), "&"+aggrListName);
        nodeFooterStr = identMethodBody(nodeFooterStr).append("return true;\n");

        nodeFooterStr = getMethodFooter(nodeFooterStr);
        writeToFile(this.output, nodeFooterStr.toString());
        writeToFile(this.output, "\n");
    }
   
    @Override
    public void exitEntity(Entity n){
        StringBuilder entityFooterStr = new StringBuilder();
        identMethodBody(entityFooterStr);
        getMethodCall(entityFooterStr, writerName, "->", callToWriteLine, quote(n.getName()), "&"+aggrListName);
        getMethodFooter(entityFooterStr);
        writeToFile(output, entityFooterStr.toString());
        writeToFile(output, "\n");
    }
   
    @Override
    public void exitAstNodes(){
        this.decreaseIdent();
    }

    @Override
    public void exit(){
        this.insertIndentation();
        writeToFile(this.output, "}; //class\n");
        this.decreaseIdent();
        writeToFile(this.output, "} //namespace\n");
        assert this.ident == 0;
    }
   
}
TOP

Related Classes of printer.PrintClangCsvPlugin$CallWriteCsvForEntity

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.