Package org.rascalmpl.parser

Source Code of org.rascalmpl.parser.StandAloneParser

package org.rascalmpl.parser;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.jar.Attributes;

public class StandAloneParser {
  private static final String BAD_JAR = "Jar file not correctly set up";
  private static final String EXPECTED_ARG = "Expected argument to option";
  private static final String NO_PARSER = "Parser not found in jar file";
  private static String rascalPath = null;
  private static String startSymbol = null;
  private static String input = null;
  /**
   * @param args
   * @throws Throwable
   */
  public static void main(String[] args) throws Throwable {
    URL resource = StandAloneParser.class.getResource("StandAloneParser.class");

    if(resource.getProtocol().equals("jar")) {
      URLConnection conn = resource.openConnection();
      if(conn instanceof JarURLConnection) {
        Attributes mainAttributes = ((JarURLConnection) conn).getMainAttributes();
        String clsName = mainAttributes.getValue("X-Rascal-Saved-Class");
        if(clsName == null)
          fatal(BAD_JAR, "No saved parser class");

        parseOptions(args);

        String classPath = System.getenv("CLASSPATH");
        String[] split = classPath != null ? classPath.split(System.getProperty("path.separator")) : new String[0];

        URL[] urls = new URL[split.length + 1 + (rascalPath != null ? 1 : 0)];
        int i = 0;

        if(rascalPath != null)
          urls[i++] = new URL("file", null, rascalPath);

        for(String path : split) {
          urls[i++] = new URL("file", null, path);
        }
        urls[i++] = ((JarURLConnection) conn).getJarFileURL();

        // System.out.println("URLs: " + Arrays.toString(urls));

        try(URLClassLoader loader = new URLClassLoader(urls, null)) {
          Class<?> clazz = loader.loadClass(clsName);

          if(startSymbol == null) {
            // attempt to guess start symbol from available classes
            for(Class<?> f : clazz.getDeclaredClasses()) {
              if(f.getSimpleName().startsWith("start__")) {
                startSymbol = f.getSimpleName();
                System.err.println("Using start symbol " + startSymbol);
                break;
              }
            }
          }
          if(startSymbol == null)
            fatal("Start symbol required", "--start STARTSYMBOL");


          Class<?> INodeFlattener = loader.loadClass("org.rascalmpl.parser.gtd.result.out.INodeFlattener");
          Class<?> INodeConstructorFactory = loader.loadClass("org.rascalmpl.parser.gtd.result.out.INodeConstructorFactory");
          Class<?> DefaultNodeFlattener = loader.loadClass("org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener");
          Class<?> UPTRNodeFactory = loader.loadClass("org.rascalmpl.parser.uptr.UPTRNodeFactory");
          Class<?> ParseError = loader.loadClass("org.rascalmpl.parser.gtd.exception.ParseError");
          Class<?> UndeclaredNonTerminalException = loader.loadClass("org.rascalmpl.parser.gtd.exception.UndeclaredNonTerminalException");
         
         
          Method method = clazz.getMethod("parse", String.class, URI.class, char[].class, INodeFlattener, INodeConstructorFactory);
          URI inputURI;
          if(input != null)
            inputURI = new URI("file", input, null);
          else
            inputURI = new URI("stdin", "//", null);

          try {
            Object invoke = method.invoke(clazz.newInstance(), startSymbol, inputURI, getInput(), DefaultNodeFlattener.newInstance(), UPTRNodeFactory.newInstance());
            System.out.println(invoke);
          }
          catch(InvocationTargetException e) {
            Throwable cause = e.getCause();
            if(ParseError.isInstance(cause)) {
              fatal(cause.toString(), null);
            }
            else if(UndeclaredNonTerminalException.isInstance(cause)) {
              fatal(cause.getMessage(), "(perhaps start symbol doesn't exist?)");
            }
            throw e.getCause();
          }
        }
        catch(NoSuchMethodException | ClassNotFoundException e) {
          fatal(NO_PARSER, e.getMessage());
        }
      }
      else {
        fatal(BAD_JAR, "Not running from a JAR file");
      }
    }
    else {
      fatal(BAD_JAR, "Not running from a JAR file");
    }

  }

  private static char[] getInput() {
    InputStream inputStream = null;
    try {
      try {
        if(input != null) {
          inputStream = new FileInputStream(input);
        }
        else {
          inputStream = System.in;
        }

        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];

        InputStreamReader reader = new InputStreamReader(inputStream);
        while(true) {
          int n = reader.read(buffer);
          if(n == -1)
            break;
          builder.append(buffer, 0, n);
        }
        return builder.toString().toCharArray();
      }
      finally {
        if(inputStream != null && inputStream != System.in)
          inputStream.close();
      }
    }
    catch (FileNotFoundException e) {
      fatal("Input file not found", input);
    }
    catch (IOException e) {
      fatal("I/O error reading input file", e.getMessage());
    }
    return null; // can't happen
  }

  private static void parseOptions(String[] args) {
    int i = 0;
    while(i < args.length) {
      switch(args[i]) {
      case "-r":
      case "--rascal":
        if(++i < args.length) {
          rascalPath = args[i++];
        }
        else {
          fatal(EXPECTED_ARG, "rascal path");
        }
        break;
      case "-s":
      case "--start":
        if(++i < args.length) {
          startSymbol = args[i++];
        }
        else {
          fatal(EXPECTED_ARG, "start symbol");
        }
        break;
      case "-h":
      case "--help":
        System.err.println("usage: java -jar parserJarFile [options] inputFile");
        System.err.println("options:");
        System.err.println("    -r, --rascal PATH       give path to Rascal installation (either jar or dir)");
        System.err.println("    -s, --start NAME        name of start symbol");
        System.err.println("    -h, --help              print help");
        System.exit(0);
        break;
      default:
        if(input != null) {
          fatal("name of input file already given", args[i]);
        }
        else {
          input = args[i++];
        }
        break;
      }
    }

  }

  private static void fatal(String msg1, String msg2) {
    if(msg2 == null)
      System.err.println(msg1);
    else
      System.err.println(msg1 + ": " + msg2);
    System.exit(1);
  }

}
TOP

Related Classes of org.rascalmpl.parser.StandAloneParser

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.