Package wyvern.tools.parsing

Source Code of wyvern.tools.parsing.CopperComposer

package wyvern.tools.parsing;

import edu.umn.cs.melt.copper.compiletime.logging.CompilerLogger;
import edu.umn.cs.melt.copper.compiletime.logging.PrintCompilerLogHandler;
import edu.umn.cs.melt.copper.compiletime.skins.cup.CupSkinParser;
import edu.umn.cs.melt.copper.compiletime.skins.xml.XMLSkinParser;
import edu.umn.cs.melt.copper.compiletime.spec.grammarbeans.*;
import edu.umn.cs.melt.copper.compiletime.spec.grammarbeans.visitors.ParserSpecProcessor;
import edu.umn.cs.melt.copper.main.CopperIOType;
import edu.umn.cs.melt.copper.main.ParserCompiler;
import edu.umn.cs.melt.copper.main.ParserCompilerParameters;
import edu.umn.cs.melt.copper.runtime.auxiliary.Pair;
import edu.umn.cs.melt.copper.runtime.logging.CopperException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CopperComposer extends Task {
  private File hostGrammar;
  private String hostGrammarName;
  private File extensionGrammar;
  private File output;
  private Pattern terminalRegexp = Pattern.compile("Terminals\\.([a-zA-Z0-9_]+)");

  public void setExtensiongrammar(File extensionGrammar) {
    this.extensionGrammar = extensionGrammar;
  }

  public void setHostgrammar(File hostGrammar) {
    this.hostGrammar = hostGrammar;
  }

  public void setHostgrammarname(String hostGrammarName) {
    this.hostGrammarName = hostGrammarName;
  }

  public void setOutput(File output) { this.output = output; }

  public static void main(String[] args) {

  }
  private class NullOutputStream extends OutputStream {
    @Override
    public void write(int b) throws IOException {
    }
  }
  @Override
  public void execute() throws BuildException {
    ParserBean host;
    try (InputStream is = new FileInputStream(hostGrammar)) {
      host = new CupSkinParser().parse(new InputStreamReader(is), hostGrammar.getName());
    } catch (Exception e) {
      throw new BuildException(e);
    }

    ParserBean extension;
    try (InputStream is = new FileInputStream(extensionGrammar)) {
      ArrayList<Pair<String,Reader>> files = new ArrayList<>();
      files.add(new Pair<String, Reader>(extensionGrammar.getName(), new InputStreamReader(is)));
      XMLSkinParser xmlSkinParser = new XMLSkinParser(files,
          new CompilerLogger(new PrintCompilerLogHandler(new PrintStream(new OutputStream() {
            public void write(int b) {
              //Nothing - suppress all messages
            }
          }))));
      xmlSkinParser.parse();
      Field parserField = xmlSkinParser.getClass().getDeclaredField("currentParser");
      parserField.setAccessible(true);
      extension = (ParserBean)parserField.get(xmlSkinParser);
    } catch (Exception e) {
      throw new BuildException(e);
    }

    try {
      CopperElementName grammarName = CopperElementName.newName("_" + hostGrammarName);
      ((ExtendedParserBean)extension).setHostGrammar(host.getGrammar(grammarName));
      Field grammarField = extension.getClass().getSuperclass().getDeclaredField("grammars");
      grammarField.setAccessible(true);
      Hashtable<CopperElementName,Grammar> grammars =
          (Hashtable<CopperElementName, Grammar>) grammarField.get(extension);
      grammars.put(grammarName,host.getGrammar(grammarName));
    } catch (Exception e) {
      throw new BuildException(e);
    }

    extension.setParserClassAuxCode(host.getParserClassAuxCode());
    extension.setParserInitCode(host.getParserInitCode());

    Function<CopperElementReference, String> nameGetter = cen -> cen.getGrammarName() +"$"+cen.getName();

    Stream<Stream<GrammarElement>> elements = host.getGrammars().stream().map(host::getGrammar)
        .map(grammar -> grammar.getGrammarElements().stream().map(grammar::getGrammarElement));

    List<DisambiguationFunction> dfl = elements
        .map(ielements -> ielements.filter(el -> el instanceof DisambiguationFunction))
        .flatMap(e->e.map(el->(DisambiguationFunction)el)).collect(Collectors.toList());
    dfl.stream().forEach(df ->
        df.setCode(df.getMembers().stream()
            .map(cen -> "\t\t\tfinal int " + cen.getName() + " = " + nameGetter.apply(cen) + ";")
            .reduce((l, r) -> l + "\n" + r).orElseGet(() -> "") + "\n" + df.getCode()));



    host.getGrammars().stream().map(host::getGrammar)
        .map(grammar -> grammar.getGrammarElements().stream().map(grammar::getGrammarElement))
        .flatMap(els -> els.filter(el -> el instanceof Production).map(el -> (Production) el))
        .forEach(this::rewriteTerminals);

    host.getGrammars().stream().map(host::getGrammar)
        .map(grammar -> grammar.getGrammarElements().stream().map(grammar::getGrammarElement))
        .flatMap(els -> els.filter(el -> el instanceof Terminal).map(el -> (Terminal) el))
        .forEach(this::rewriteTerminals);
    try {
      CompilerLogger logger = new CompilerLogger(new PrintCompilerLogHandler(System.out));
      ParserSpecProcessor.normalizeParser(extension, logger);
    } catch (CopperException e) {
      throw new BuildException(e);
    }
    ParserCompilerParameters pcp = new ParserCompilerParameters();

    ByteArrayOutputStream target = new ByteArrayOutputStream();
    pcp.setOutputStream(new PrintStream(target));
    pcp.setOutputType(CopperIOType.STREAM);


    try {
      ParserCompiler.compile(extension, pcp);
    } catch (CopperException e) {
      throw new BuildException(e);
    }

    try (FileOutputStream fos = new FileOutputStream(output)) {
      fos.write(target.toByteArray());
    } catch (Exception e) {
      throw new BuildException(e);
    }
  }

  private void rewriteTerminals(Production prod) {
    if (prod.getCode() == null)
      return;
    Matcher m = terminalRegexp.matcher(prod.getCode());
    StringBuffer ob = new StringBuffer();
    while (m.find())
      m.appendReplacement(ob, "Terminals._"+hostGrammarName+"\\$$1");
    m.appendTail(ob);
    prod.setCode(ob.toString());
  }

  private void rewriteTerminals(Terminal term) {
    if (term.getCode() == null)
      return;
    Matcher m = terminalRegexp.matcher(term.getCode());
    StringBuffer ob = new StringBuffer();
    while (m.find())
      m.appendReplacement(ob, "Terminals._"+hostGrammarName+"\\$$1");
    m.appendTail(ob);
    term.setCode(ob.toString());
  }

}
TOP

Related Classes of wyvern.tools.parsing.CopperComposer

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.