ca.uqac.lif.bullwinkle.BullwinkleCli.java Source code

Java tutorial

Introduction

Here is the source code for ca.uqac.lif.bullwinkle.BullwinkleCli.java

Source

/*
  Copyright 2014 Sylvain Hall
  Laboratoire d'informatique formelle
  Universit du Qubec  Chicoutimi, Canada
    
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
    
  http://www.apache.org/licenses/LICENSE-2.0
    
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */
package ca.uqac.lif.bullwinkle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

import ca.uqac.lif.bullwinkle.BnfParser.InvalidGrammarException;
import ca.uqac.lif.bullwinkle.output.GraphvizVisitor;
import ca.uqac.lif.bullwinkle.output.IndentedTextVisitor;
import ca.uqac.lif.bullwinkle.output.OutputFormatVisitor;
import ca.uqac.lif.bullwinkle.output.XmlVisitor;

public class BullwinkleCli {

    /**
     * Return codes
     */
    public static final int ERR_OK = 0;
    public static final int ERR_PARSE = 2;
    public static final int ERR_IO = 3;
    public static final int ERR_ARGUMENTS = 4;
    public static final int ERR_RUNTIME = 6;
    public static final int ERR_GRAMMAR = 7;
    public static final int ERR_INPUT = 9;

    /**
     * Build string to identify versions
     */
    protected static final String VERSION_STRING = "1.1";
    protected static final String BUILD_STRING = "20140418";

    /**
     * @param args
     */
    public static void main(String[] args) {
        // Setup parameters
        int verbosity = 1;
        String output_format = "xml", grammar_filename = null, filename_to_parse = null;

        // Parse command line arguments
        Options options = setupOptions();
        CommandLine c_line = setupCommandLine(args, options);
        assert c_line != null;
        if (c_line.hasOption("verbosity")) {
            verbosity = Integer.parseInt(c_line.getOptionValue("verbosity"));
        }
        if (verbosity > 0) {
            showHeader();
        }
        if (c_line.hasOption("version")) {
            System.err.println("(C) 2014 Sylvain Hall et al., Universit du Qubec  Chicoutimi");
            System.err.println("This program comes with ABSOLUTELY NO WARRANTY.");
            System.err.println("This is a free software, and you are welcome to redistribute it");
            System.err.println("under certain conditions. See the file LICENSE-2.0 for details.\n");
            System.exit(ERR_OK);
        }
        if (c_line.hasOption("h")) {
            showUsage(options);
            System.exit(ERR_OK);
        }
        if (c_line.hasOption("f")) {
            output_format = c_line.getOptionValue("f");
        }
        // Get grammar file
        @SuppressWarnings("unchecked")
        List<String> remaining_args = c_line.getArgList();
        if (remaining_args.isEmpty()) {
            System.err.println("ERROR: no grammar file specified");
            System.exit(ERR_ARGUMENTS);
        }
        grammar_filename = remaining_args.get(0);
        // Get file to parse, if any
        if (remaining_args.size() >= 2) {
            filename_to_parse = remaining_args.get(1);
        }

        // Read grammar file
        BnfParser parser = null;
        try {
            parser = new BnfParser(new File(grammar_filename));
        } catch (InvalidGrammarException e) {
            System.err.println("ERROR: invalid grammar");
            System.exit(ERR_GRAMMAR);
        } catch (IOException e) {
            System.err.println("ERROR reading grammar " + grammar_filename);
            System.exit(ERR_IO);
        }
        assert parser != null;

        // Read input file
        BufferedReader bis = null;
        if (filename_to_parse == null) {
            // Read from stdin
            bis = new BufferedReader(new InputStreamReader(System.in));
        } else {
            // Read from file
            try {
                bis = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filename_to_parse))));
            } catch (FileNotFoundException e) {
                System.err.println("ERROR: file not found " + filename_to_parse);
                System.exit(ERR_IO);
            }
        }
        assert bis != null;
        String str;
        StringBuilder input_file = new StringBuilder();
        try {
            while ((str = bis.readLine()) != null) {
                input_file.append(str).append("\n");
            }
        } catch (IOException e) {
            System.err.println("ERROR reading input");
            System.exit(ERR_IO);
        }
        String file_contents = input_file.toString();

        // Parse contents of file
        ParseNode p_node = null;
        try {
            p_node = parser.parse(file_contents);
        } catch (ca.uqac.lif.bullwinkle.BnfParser.ParseException e) {
            System.err.println("ERROR parsing input\n");
            e.printStackTrace();
            System.exit(ERR_PARSE);
        }
        if (p_node == null) {
            System.err.println("ERROR parsing input\n");
            System.exit(ERR_PARSE);
        }
        assert p_node != null;

        // Output parse node to desired format
        PrintStream output = System.out;
        OutputFormatVisitor out_vis = null;
        if (output_format.compareToIgnoreCase("xml") == 0) {
            // Output to XML
            out_vis = new XmlVisitor();
        } else if (output_format.compareToIgnoreCase("dot") == 0) {
            // Output to DOT
            out_vis = new GraphvizVisitor();
        } else if (output_format.compareToIgnoreCase("txt") == 0) {
            // Output to indented plain text
            out_vis = new IndentedTextVisitor();
        } else if (output_format.compareToIgnoreCase("json") == 0) {
            // Output to JSON
        }
        if (out_vis == null) {
            System.err.println("ERROR: unknown output format " + output_format);
            System.exit(ERR_ARGUMENTS);
        }
        assert out_vis != null;
        p_node.prefixAccept(out_vis);
        output.print(out_vis.toOutputString());

        // Terminate without error
        System.exit(ERR_OK);
    }

    /**
     * Sets up the options for the command line parser
     * @return The options
     */
    @SuppressWarnings("static-access")
    private static Options setupOptions() {
        Options options = new Options();
        Option opt;
        opt = OptionBuilder.withLongOpt("help").withDescription("Display command line usage").create("h");
        options.addOption(opt);
        opt = OptionBuilder.withLongOpt("format").withArgName("x").hasArg()
                .withDescription("Output parse tree in format x (dot, xml, txt or json). Default: xml").create("f");
        options.addOption(opt);
        opt = OptionBuilder.withLongOpt("verbosity").withArgName("x").hasArg()
                .withDescription("Verbose messages with level x").create();
        options.addOption(opt);
        return options;
    }

    /**
     * Show the benchmark's usage
     * @param options The options created for the command line parser
     */
    private static void showUsage(Options options) {
        HelpFormatter hf = new HelpFormatter();
        hf.printHelp("java -jar BullwinkleParser.jar [options] grammar [inputfile]", options);
    }

    /**
     * Sets up the command line parser
     * @param args The command line arguments passed to the class' {@link main}
     * method
     * @param options The command line options to be used by the parser
     * @return The object that parsed the command line parameters
     */
    private static CommandLine setupCommandLine(String[] args, Options options) {
        CommandLineParser parser = new PosixParser();
        CommandLine c_line = null;
        try {
            // parse the command line arguments
            c_line = parser.parse(options, args);
        } catch (ParseException exp) {
            // oops, something went wrong
            System.err.println("ERROR: " + exp.getMessage() + "\n");
            //HelpFormatter hf = new HelpFormatter();
            //hf.printHelp(t_gen.getAppName() + " [options]", options);
            System.exit(ERR_ARGUMENTS);
        }
        return c_line;
    }

    private static void showHeader() {
        System.err.println("Bullwinkle, a LL(k) parser");
        System.err.println("Version " + VERSION_STRING + ", build " + BUILD_STRING);
    }

}