com.github.uscexp.grappa.extension.codegenerator.PegParserGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grappa.extension Show documentation
Show all versions of grappa.extension Show documentation
Extension for parboiled/grappa parser.
The newest version!
/*
* Copyright (C) 2014 - 2016 by haui - all rights reserved
*/
package com.github.uscexp.grappa.extension.codegenerator;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.github.fge.grappa.Grappa;
import com.github.fge.grappa.parsers.BaseParser;
import com.github.uscexp.grappa.extension.exception.AstInterpreterException;
import com.github.uscexp.grappa.extension.exception.PegParserGeneratorException;
import com.github.uscexp.grappa.extension.interpreter.AstInterpreter;
import com.github.uscexp.grappa.extension.interpreter.ProcessStore;
import com.github.uscexp.grappa.extension.nodes.AstTreeNode;
import com.github.uscexp.grappa.extension.parser.Parser;
import com.github.uscexp.grappa.extension.parser.peg.PegParser;
import com.google.common.base.Preconditions;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JDocComment;
/**
* The {@link PegParserGenerator} generates a {@link BaseParser} extended parser java class file, from a given Parser Expression Grammar
* (PEG) file. The allowed PEG syntax is based on Bryan Ford's definitions (http://bford.info/pub/lang/peg).
*
* @author haui
*/
public class PegParserGenerator {
private static Logger logger = Logger.getLogger(PegParserGenerator.class.getName());
public static final long CLOSE = "close".hashCode();
public static final long OPEN = "open".hashCode();
public static final String CODE_MODEL = "codeModel";
public static final String DEFINED_CLASS = "definedClass";
private File file = null;
private PegParser parser;
private AstTreeNode rootNode;
private String parserClassString;
private String genericTypeName;
private AstInterpreter astInterpreter;
public void generateParserFromFile(String parserClassString, String genericTypeName, String sourceOutputPath, String pegInputPath,
Charset encoding)
throws PegParserGeneratorException, AstInterpreterException {
String input = null;
if (encoding == null)
encoding = Charset.defaultCharset();
file = new File(pegInputPath);
if (!file.exists()) {
throw new PegParserGeneratorException(String.format("File %s does not exist!", pegInputPath));
}
try {
byte[] encoded = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
input = new String(encoded, encoding);
} catch (IOException e) {
throw new PegParserGeneratorException(String.format("File %s couldn't be read!", pegInputPath), e);
}
generateParserFromString(parserClassString, genericTypeName, sourceOutputPath, input);
}
public void generateParserFromString(String parserClassString, String genericTypeName, String sourceOutputPath, String pegInput)
throws PegParserGeneratorException, AstInterpreterException {
Preconditions.checkNotNull(pegInput);
parser = Grappa.createParser(PegParser.class);
rootNode = Parser.parseInput(PegParser.class, parser.grammar(), pegInput, true);
generateParserClassFile(parserClassString, genericTypeName, sourceOutputPath);
}
private void generateParserClassFile(String parserClassString, String genericTypeName, String sourceOutputPath)
throws AstInterpreterException, PegParserGeneratorException {
astInterpreter = new AstInterpreter<>();
Long id = new Date().getTime();
Long idOpen = id + OPEN;
try {
this.parserClassString = parserClassString;
this.genericTypeName = genericTypeName;
generateCode(sourceOutputPath, id, idOpen);
} catch (JClassAlreadyExistsException | IOException e) {
throw new PegParserGeneratorException("PEG parser generator unexpected error", e);
} finally {
astInterpreter.cleanUp(id);
astInterpreter.cleanUp(idOpen);
}
}
private void generateCode(String sourceOutputPath, Long id, Long idOpen)
throws JClassAlreadyExistsException, AstInterpreterException, IOException {
JCodeModel codeModel = new JCodeModel();
ProcessStore processStore = ProcessStore.getInstance(id);
ProcessStore