Java tutorial
/** * The GOAL Grammar Tools. Copyright (C) 2014 Koen Hindriks. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package languageTools; import goalhub.krTools.KRFactory; import java.io.File; import java.util.ArrayList; import java.util.List; import krTools.errors.exceptions.KRInitFailedException; import languageTools.analyzer.Validator; import languageTools.analyzer.agent.AgentValidator; import languageTools.analyzer.mas.MASValidator; import languageTools.analyzer.module.ModuleValidator; import languageTools.analyzer.test.TestValidator; import languageTools.utils.Extension; 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; /** * <pre> * {@code * Usage: languageTools.Analyzer [options] [[file|directory]] * -mas Analyze MAS files * -goal Analyze GOAL agent files * -module Analyze module files * -r,--recursive Recursively search directories * } * </pre> */ public class Analyzer { private static final String OPTION_LEXER = "lexer"; private static final String OPTION_PROGRAM = "program"; private static final String OPTION_MAS = "mas"; private static final String OPTION_GOAL = "goal"; private static final String OPTION_MOD2G = "module"; private static final String OPTION_RECURSIVE = "recursive"; private static final String OPTION_RECURSIVE_SHORT = "r"; private static final String OPTION_HELP = "help"; private static final String OPTION_HELP_SHORT = "h"; private static final String OPTION_LICENSE = "license"; private static final Options options = createOptions(); // Print token output generated by lexer? private static boolean lexer = false; // Print program generated by parser? private static boolean program = false; // Analyze MAS files? private static boolean masFile; // Analyze agent files? private static boolean agentFile; // Analyze module files? private static boolean moduleFile; // Recursively search directories? private static boolean recursive; /** * * @param args * @throws Exception */ public static void main(String[] args) { // Get start time. long startTime = System.nanoTime(); // Parse command line options File file; try { file = parseOptions(args); } catch (ParseException e) { System.out.println(e.getMessage()); showHelp(); return; } // Get all files that should be analyzed List<File> files = new ArrayList<File>(); if (file.isDirectory()) { // Search directory for indicated file types files = searchDirectory(file); System.out.println("Found " + files.size() + " file(s).\n"); } else { files.add(file); } // Process files found for (File filefound : files) { System.out.println("Processing file: " + filefound.getPath() + ".\n"); Validator<?, ?, ?, ?> validator = null; switch (Extension.getFileExtension(filefound)) { case GOAL: validator = new AgentValidator(filefound.getPath()); // TODO we need to set a KR interface; use default (only one) // right now. Best we can do now // is to ask user to set it. try { ((AgentValidator) validator).setKRInterface(KRFactory.getDefaultInterface()); } catch (KRInitFailedException e) { // TODO: use logger. System.out.println(e.getMessage()); } break; case MOD2G: validator = new ModuleValidator(filefound.getPath()); // TODO we need to set a KR interface; use default (only one) // right now. Best we can do now // is to ask user to set it. try { ((ModuleValidator) validator).setKRInterface(KRFactory.getDefaultInterface()); } catch (KRInitFailedException e) { // TODO: use logger. System.out.println(e.getMessage()); } break; case MAS2G: validator = new MASValidator(filefound.getPath()); break; case TEST2G: validator = new TestValidator(filefound.getPath()); break; default: // TODO: use logger. System.out.println("Expected file with extension 'goal', 'mas2g', 'mod2g', or 'test2g'"); continue; } // Validate program file validator.validate(); // Print lexer tokens if (lexer) { validator.printLexerTokens(); } // Print constructed program if (program) { System.out.println("\n\n" + validator.getProgram().toString(" ", " ")); } // Print report with warnings, and parsing and validation messages System.out.println(validator.report()); } // Get elapsed time. long elapsedTime = (System.nanoTime() - startTime) / 1000000; System.out.println("Took " + elapsedTime + " milliseconds to analyze " + files.size() + " file(s)."); } /** * Collects relevant files in a directory. * * @param directory * The directory to be searched. * @param recursive * Indicates whether directory should be searched recursively, * i.e., whether directories inside directories should also be * searched. * @return List of retrieved files. */ private static List<File> searchDirectory(File directory) { List<File> files = new ArrayList<File>(); for (File file : directory.listFiles()) { if (file.isFile()) { if (isMASFile(file) && masFile) { files.add(file); } if (isAgentFile(file) && agentFile) { files.add(file); } if (isModuleFile(file) && moduleFile) { files.add(file); } } if (file.isDirectory() && recursive) { files.addAll(searchDirectory(file)); } } return files; } /** * Checks whether file is a MAS file. * * @param file * The file to check. * @return {@code true} if extension of the file is {@link Extension#MAS}. */ public static boolean isMASFile(File file) { return Extension.getFileExtension(file) == Extension.MAS2G; } /** * Checks whether file is an agent file. * * @param file * The file to check. * @return {@code true} if extension of the file is {@link Extension#GOAL}. */ public static boolean isAgentFile(File file) { return Extension.getFileExtension(file) == Extension.GOAL; } /** * Checks whether file is a module file. * * @param file * The file to check. * @return {@code true} if extension of the file is {@link Extension#MOD2G}. */ public static boolean isModuleFile(File file) { return Extension.getFileExtension(file) == Extension.MOD2G; } /** * Checks whether file is a test file. * * @param file * The file to check. * @return {@code true} if extension of the file is {@link Extension#TEST}. */ public static boolean isTestFile(File file) { return Extension.getFileExtension(file) == Extension.TEST2G; } // ------------------------------------------------------------- // Command line options // ------------------------------------------------------------- /** * Creates the command line options. * * @return The command line options. */ private static Options createOptions() { Options options = new Options(); OptionBuilder.withDescription("Output tokens generated by lexer"); options.addOption(OptionBuilder.create(OPTION_LEXER)); OptionBuilder.withDescription("Program generated by parser"); options.addOption(OptionBuilder.create(OPTION_PROGRAM)); OptionBuilder.withDescription("Analyze MAS files"); options.addOption(OptionBuilder.create(OPTION_MAS)); OptionBuilder.withDescription("Analyze GOAL agent files"); options.addOption(OptionBuilder.create(OPTION_GOAL)); OptionBuilder.withDescription("Analyze module files"); options.addOption(OptionBuilder.create(OPTION_MOD2G)); OptionBuilder.withDescription("Recursively search directories for files"); OptionBuilder.withLongOpt(OPTION_RECURSIVE); options.addOption(OptionBuilder.create(OPTION_RECURSIVE_SHORT)); options.addOption(new Option(OPTION_HELP_SHORT, OPTION_HELP, false, "Displays this help")); OptionBuilder.withDescription("Shows the license"); OptionBuilder.withLongOpt(OPTION_LICENSE); options.addOption(OptionBuilder.create()); return options; } private static File parseOptions(String[] args) throws ParseException { CommandLineParser parser = new PosixParser(); CommandLine cmd = parser.parse(options, args); lexer = cmd.hasOption(OPTION_LEXER); program = cmd.hasOption(OPTION_PROGRAM); masFile = cmd.hasOption(OPTION_MAS); agentFile = cmd.hasOption(OPTION_GOAL); moduleFile = cmd.hasOption(OPTION_MOD2G); recursive = cmd.hasOption(OPTION_RECURSIVE); /* * Handle general options. */ if (cmd.hasOption(OPTION_HELP)) { throw new ParseException("The GOAL Grammar Tools. Copyright (C) 2014 GPLv3"); } if (cmd.hasOption(OPTION_LICENSE)) { showLicense(); throw new ParseException(""); } // Process remaining arguments if (cmd.getArgs().length == 0) { throw new ParseException("Missing file or directory"); } if (cmd.getArgs().length > 1) { throw new ParseException("Expected single file or directory name but got: " + cmd.getArgs()); } // Check existence of file File file = new File(cmd.getArgs()[0]); if (!file.exists()) { throw new ParseException("Could not find " + file); } return file; } /** * Prints help message with command line options. */ private static void showHelp() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(Analyzer.class.getCanonicalName() + " [options] [[file|directory]]", options); } /** * Print the license; required by GPL v3. */ private static void showLicense() { System.out.println("The GOAL Grammar Tools. Copyright (C) 2014 Koen Hindriks.\n\n" + "This program is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); } }