codemate.Fortran.FortranProcessor.java Source code

Java tutorial

Introduction

Here is the source code for codemate.Fortran.FortranProcessor.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Li Dong.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Li Dong - initial API and implementation
 ******************************************************************************/
package codemate.Fortran;

/**
 * FortranProcessor
 *
 * This program is used to process Fortran codes with augmented template
 * mechanism. By using visitor model, the nodes in the parse tree will be
 * visited, during which the code will be rewrited and the templates will be
 * expanded.
 *
 * @author      Li Dong <dongli@lasg.iap.ac.cn>
 */

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

import codemate.project.*;
import codemate.ui.*;

import java.io.*;

public class FortranProcessor {
    /**
     * process
     * 
     * This method processes the given project by calling 'callParser',
     * 'callTemplater' and 'callRewriter'.
     * 
     * @param      project         The project to be processed
     * 
     * @author       Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static void process(Project project) {
        FortranTemplater.load(project);
        for (CodeEntity entity : project.entities) {
            UI.notice("codemate", "Process code " + entity.getPath() + ".");
            try {
                callParser(entity);
            } catch (Exception e) {
                UI.error("codemate", "Encounter error while parsing " + entity.getPath() + "!");
            }
            if (callTemplater(entity)) {
                entity.addProcess(CodeEntity.Process.TEMPLATE);
                callRewriter(entity, project);
            }
            callModuleDepend(entity, project);
        }
    }

    /**
     * process
     * 
     * This method only processes a single Fortran file.
     * 
     * @param file
     * 
     * @author Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static void process(File file) {
        // find the project stuffs (that is .codemate directory) and load
        // compiled templates if there are
        File dir = Project.findProject(file);
        if (dir != null) {
            File compiledTemplatesRoot = new File(dir.getAbsolutePath() + "/.codemate/compiled_templates");
            FortranTemplater.loadCompiledTemplates(compiledTemplatesRoot);
        }
        CodeEntity entity = new CodeEntity(file.getPath());
        try {
            callParser(entity);
        } catch (Exception e) {
            e.printStackTrace();
            UI.error("codemate", "Encounter error while parsing " + entity.getPath() + "!");
        }
        callTemplater(entity);
        callRewriter(entity);
    }

    /**
     * callParser
     *
     * This method parses the given input stream from root 'file' rule.
     *
     * @param       entity           The code entity to be parsed
     *
     * @author      Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static void callParser(CodeEntity entity) throws Exception {
        InputStream inputStream = new FileInputStream(entity.getPath());
        ANTLRInputStream input = new ANTLRInputStream(inputStream);
        FortranLexer lexer = new FortranLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        FortranParser parser = new FortranParser(tokens);
        parser.removeErrorListeners();
        parser.addErrorListener(new FortranErrorListener());
        entity.setParseTree(parser.file());
    }

    /**
     * callParser
     *
     * This method parses pieces of Fortran code. It is called by
     * FortranTemplater.
     *
     * @param       type           The starting parser rule.
     * @param       source          A input string for parsing.
     * @return                      The parse tree.
     *
     * @author      Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static ParseTree callParser(int ruleIndex, String source) throws Exception {
        ANTLRInputStream input = new ANTLRInputStream(source);
        FortranLexer lexer = new FortranLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        FortranParser parser = new FortranParser(tokens);
        ParseTree tree = null;
        // NOTE: We set the rules that can be used.
        if (ruleIndex == FortranParser.RULE_declarationStatements) {
            tree = parser.declarationStatements();
        } else if (ruleIndex == FortranParser.RULE_executableStatements) {
            tree = parser.executableStatements();
        } else if (ruleIndex == FortranParser.RULE_typeDeclarationStatement) {
            tree = parser.typeDeclarationStatement();
        } else if (ruleIndex == FortranParser.RULE_containedProcedures) {
            tree = parser.containedProcedures();
        } else if (ruleIndex == FortranParser.RULE_derivedTypeName) {
            tree = parser.derivedTypeName();
        } else if (ruleIndex == FortranParser.RULE_expression) {
            tree = parser.expression_();
        } else if (ruleIndex == FortranParser.RULE_accessibilityStatements) {
            tree = parser.accessibilityStatements();
        } else {
            UI.error("codemate", "Unimplemented parser rule!");
        }
        return tree;
    }

    /**
     * callTemplater 
     *
     * This method calls FortranTemplater class to process the template
     * instances in the Fortran codes.
     * 
     * @param       entity      The code entity to be processed for template
     * @return      boolean     Return true if encounter template instance.
     *
     * @author      Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static boolean callTemplater(CodeEntity entity) {
        FortranTemplater templater = new FortranTemplater();
        return templater.instantiate(entity.getParseTree());
    }

    /**
     * callRewriter 
     *
     * This method calls FortranRewriter class to rewrite the Fortran codes.
     *
     * @param      entity    The code entity to be rewritten
     * 
     * @author      Li Dong <dongli@lasg.iap.ac.cn>
     */
    public static void callRewriter(CodeEntity entity) {
        FortranRewriter rewriter = new FortranRewriter();
        rewriter.rewrite(entity.getParseTree());
        // write new code into error channel, then user can redirect it
        System.err.println(rewriter.getNewCode());
    }

    /**
     * callRewriter
     * 
     * This method rewrites the given entity in a project to a new location that
     * is <project root>/.codemate/processed_codes.
     * 
     * @param      entity    The code entity to be rewritten
     * @param      project   The project
     * 
     * @author Li Dong <dongli@lasg.iap.ac.cn>
     */
    private static void callRewriter(CodeEntity entity, Project project) {
        File dir = new File(project.getRoot() + "/.codemate/processed_codes");
        if (!dir.isDirectory())
            if (!dir.mkdirs())
                UI.error("codemate",
                        "Couldn't create directory " + dir.getPath() + " for storing processed codes!");
        FortranRewriter rewriter = new FortranRewriter();
        rewriter.rewrite(entity.getParseTree());
        String fileName = dir.getPath() + "/" + entity.getName() + ".t.F90";
        UI.notice("codemate", "Processed code is written to " + fileName + ".");
        try {
            PrintWriter out = new PrintWriter(new FileWriter(fileName));
            out.print(rewriter.getNewCode());
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void callModuleDepend(CodeEntity entity, Project project) {
        FortranDepend moduleDepend = new FortranDepend();
        moduleDepend.extract(entity, project);
    }
}