Package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter

Source Code of org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.ParserGenerator

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Anya Helene Bagge - anya@ii.uib.no (Univ. Bergen)
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.List;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.ISourceLocation;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.eclipse.imp.pdb.facts.type.TypeStore;
import org.rascalmpl.interpreter.Configuration;            // remove import: NO
import org.rascalmpl.interpreter.Evaluator;              // TODO: remove import: YES
import org.rascalmpl.interpreter.IRascalMonitor;          // remove import: NO
import org.rascalmpl.interpreter.control_exceptions.Throw;      // TODO: remove import: LATER
import org.rascalmpl.interpreter.env.GlobalEnvironment;        // TODO: remove import: YES
import org.rascalmpl.interpreter.env.ModuleEnvironment;        // TODO: remove import: YES
import org.rascalmpl.interpreter.load.StandardLibraryContributor;  // remove import: NO
import org.rascalmpl.interpreter.utils.JavaBridge;          // remove import: NO
import org.rascalmpl.parser.gtd.IGTD;
import org.rascalmpl.values.ValueFactoryFactory;

public class ParserGenerator {
  private final Evaluator evaluator;
  private final JavaBridge bridge;
  private final IValueFactory vf;
  private static final String packageName = "org.rascalmpl.java.parser.object";
  private static final boolean debug = false;

  public ParserGenerator(IRascalMonitor monitor, PrintWriter out, List<ClassLoader> loaders, IValueFactory factory, Configuration config) {
    GlobalEnvironment heap = new GlobalEnvironment();
    ModuleEnvironment scope = new ModuleEnvironment("___parsergenerator___", heap);
    this.evaluator = new Evaluator(ValueFactoryFactory.getValueFactory(), out, out, scope,heap);
    evaluator.addRascalSearchPathContributor(StandardLibraryContributor.getInstance());    this.evaluator.setBootstrapperProperty(true);
    this.bridge = new JavaBridge(loaders, factory, config);
    this.vf = factory;
   
    monitor.startJob("Loading parser generator", 100, 139);
    try {
      evaluator.doImport(monitor, "lang::rascal::grammar::ParserGenerator");
      evaluator.doImport(monitor, "lang::rascal::grammar::ConcreteSyntax");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Modules");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Priorities");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Regular");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Keywords");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Literals");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Parameters");
      evaluator.doImport(monitor, "lang::rascal::grammar::definition::Symbols");
      evaluator.doImport(monitor, "Ambiguity");
    }
    finally {
      monitor.endJob(true);
    }
  }
 
//  public IValue diagnoseAmbiguity(IConstructor parseForest) {
//    return evaluator.call("diagnose", parseForest);
//  }
 
  /**
   * Generate a parser from a Rascal syntax definition (a set of production rules).
   *
   * @param monitor a progress monitor; this method will contribute 100 work units
   * @param loc     a location for error reporting
   * @param name    the name of the parser for use in code generation and for later reference
   * @param imports a set of syntax definitions (which are imports in the Rascal grammar)
   * @return
   */
  @SuppressWarnings("unchecked")
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getParser(IRascalMonitor monitor, URI loc, String name, IMap definition) {
    monitor.startJob("Generating parser:" + name, 100, 90);

    try {
      monitor.event("Importing and normalizing grammar:" + name, 30);
      IConstructor grammar = convertMapToGrammar(definition);
      debugOutput(grammar.toString(), System.getProperty("java.io.tmpdir") + "/grammar.trm");
      String normName = name.replaceAll("::", "_");
      monitor.event("Generating java source code for parser: " + name,30);
      IString classString = (IString) evaluator.call(monitor, "generateObjectParser", vf.string(packageName), vf.string(normName), grammar);
      debugOutput(classString.getValue(), System.getProperty("java.io.tmpdir") + "/parser.java");
      monitor.event("Compiling generated java code: " + name, 30);
      Class<IGTD<IConstructor, IConstructor, ISourceLocation>> p = bridge.compileJava(loc, packageName + "." + normName, getClass(), classString.getValue());

      String className = normName;
      Class<?> clazz;
      for (ClassLoader cl: evaluator.getClassLoaders()) {
        try {
          clazz = cl.loadClass(className);
          return (Class<IGTD<IConstructor, IConstructor, ISourceLocation>>) clazz.newInstance();

        } catch (ClassNotFoundException e) {
          continue;
        } catch (InstantiationException e) {
          throw new CompilerError("could not instantiate " + className + " to valid IGTD parser: " + e.getMessage());
        } catch (IllegalAccessException e) {
          throw new CompilerError("not allowed to instantiate " + className + " to valid IGTD parser: " + e.getMessage());
        }
      }
      throw new CompilerError("class for cached parser " + className + " could not be found");

    catch (ClassCastException e) {
      throw new CompilerError("parser generator:" + e.getMessage() + ", " + e);
    } catch (Throw e) {
      throw new CompilerError("parser generator: " + e.getMessage() + e.getTrace());
    } finally {
      monitor.endJob(true);
    }
  }

  /**
   * Uses the user defined syntax definitions to generate a parser for Rascal that can deal
   * with embedded concrete syntax fragments
   *
   * Note that this method works under the assumption that a normal parser was generated before!
   * The class that this parser generates will inherit from that previously generated parser.
   */
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getRascalParser(IRascalMonitor monitor, URI loc, String name, IMap definition, IGTD<IConstructor, IConstructor, ISourceLocation> objectParser) {
    try {
      monitor.event("Importing and normalizing grammar: " + name, 10);
      IConstructor grammar = convertMapToGrammar(definition);
      String normName = name.replaceAll("::", "_");
      monitor.event("Generating java source code for Rascal parser:" + name, 10);
      IString classString = (IString) evaluator.call(monitor, "generateMetaParser", vf.string(packageName), vf.string("$Rascal_" + normName), vf.string(packageName + "." + normName), grammar);
      debugOutput(classString.getValue(), System.getProperty("java.io.tmpdir") + "/metaParser.java");
      monitor.event("compiling generated java code: " + name, 10);
      return bridge.compileJava(loc, packageName + ".$Rascal_" + normName, objectParser.getClass(), classString.getValue());
    catch (ClassCastException e) {
      throw new CompilerError("meta parser generator:" + e.getMessage() + e);
    } catch (Throw e) {
      throw new CompilerError("meta parser generator: " + e.getMessage() + e.getTrace());
    }
  }

  private void debugOutput(String classString, String file) {
    if (debug) {
      FileOutputStream s = null;
      try {
        s = new FileOutputStream(file);
        s.write(classString.getBytes());
        s.flush();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        if (s != null) {
          try {
            s.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
 
  public IConstructor convertMapToGrammar(IMap definition) {
    TypeFactory TF = TypeFactory.getInstance();
    TypeStore TS = new TypeStore();
    Type Grammar = TF.abstractDataType(TS, "Grammar");
    Type Symbol = TF.abstractDataType(TS, "Symbol");
    Type Production = TF.abstractDataType(TS, "Production");
    Type grammar = TF.constructor(TS, Grammar, "grammar", TF.setType(Symbol), "starts", TF.mapType(Symbol, Production), "rules");

    return vf.constructor(grammar, vf.set(), definition);
  }
 
//  public IConstructor getExpandedGrammar(IRascalMonitor monitor, String main, IMap definition) {
//    IConstructor g = convertMapToGrammar(definition);
//   
//    monitor.event("Expanding keywords", 10);
//    g = (IConstructor) evaluator.call(monitor, "expandKeywords", g);
//    monitor.event("Adding regular productions",10);
//    g = (IConstructor) evaluator.call(monitor, "makeRegularStubs", g);
//    monitor.event("Expanding regulars", 10);
//    g = (IConstructor) evaluator.call(monitor, "expandRegularSymbols", g);
//    monitor.event("Expanding parametrized symbols");
//    g = (IConstructor) evaluator.call(monitor, "expandParameterizedSymbols", g);
//    monitor.event("Defining literals");
//    g = (IConstructor) evaluator.call(monitor, "literals", g);
//    return g;
//  }

//  public ISet getNestingRestrictions(IRascalMonitor monitor,
//      IConstructor g) {
//    return (ISet) evaluator.call(monitor, "doNotNest", g);
//  }

  /**
   * Produces the name generated by the parser generator for a parse method for the given symbol
   */
  public String getParserMethodName(IConstructor symbol) {
    return ((IString) evaluator.call((IRascalMonitor) null, "getParserMethodName", symbol)).getValue();
  }
 
//  /**
//   * Converts the parse tree of a symbol to a UPTR symbol
//   */
//  public IConstructor symbolTreeToSymbol(IConstructor symbol) {
//    return (IConstructor) evaluator.call((IRascalMonitor) null,"sym2symbol", symbol);
//  }
 
  /**
   * Generate a parser from a Rascal syntax definition (a set of production rules).
   *
   * @param monitor a progress monitor; this method will contribute 100 work units
   * @param loc     a location for error reporting
   * @param name    the name of the parser for use in code generation and for later reference
   * @param definition a map of syntax definitions (which are imports in the Rascal grammar)
   * @return A parser class, ready for instantiation
   */
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getNewParser(IRascalMonitor monitor, URI loc, String name, IMap definition) {
      return getNewParser(monitor, loc, name,  convertMapToGrammar(definition));
  }

  /**
   * Generate a parser from a Rascal grammar.
   *
   * @param monitor a progress monitor; this method will contribute 100 work units
   * @param loc     a location for error reporting
   * @param name    the name of the parser for use in code generation and for later reference
   * @param grammar a grammar
   * @return A parser class, ready for instantiation
   */
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getNewParser(IRascalMonitor monitor, URI loc, String name, IConstructor grammar) {
    monitor.startJob("Generating parser:" + name, 100, 60);
    try {

      String normName = name.replaceAll("::", "_").replaceAll("\\\\", "_");
      monitor.event("Generating java source code for parser: " + name,30);
      IString classString = (IString) evaluator.call(monitor, "newGenerate", vf.string(packageName), vf.string(normName), grammar);
      debugOutput(classString.getValue(), System.getProperty("java.io.tmpdir") + "/parser.java");
      monitor.event("Compiling generated java code: " + name, 30);
      return bridge.compileJava(loc, packageName + "." + normName, this.getClass(), classString.getValue());
    catch (ClassCastException e) {
      throw new CompilerError("parser generator:" + e.getMessage() + e);
    } catch (Throw e) {
      throw new CompilerError("parser generator: " + e.getMessage() + e.getTrace());
    } finally {
      monitor.endJob(true);
    }
  }

//  /**
//   * Save a generated parser class to a jar file
//   *
//   * @param parserClass The parser class
//   * @param outStream An output stream
//   * @throws IOException on IO error
//   */
//  public void saveToJar(Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parserClass, OutputStream outStream) throws IOException {
//    bridge.saveToJar("", parserClass, StandAloneParser.class, outStream, false);
//  }

  public String createHole(IConstructor part, int size) {
    return ((IString) evaluator.call("createHole", part, vf.integer(size))).getValue();
  }
}
TOP

Related Classes of org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.ParserGenerator

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.