All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fge.grappa.Grappa Maven / Gradle / Ivy

/*
 * Copyright (C) 2009-2011 Mathias Doenitz
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.fge.grappa;

import com.github.fge.grappa.exceptions.InvalidGrammarException;
import com.github.fge.grappa.parsers.BaseParser;
import com.github.fge.grappa.run.ParseRunner;
import com.github.fge.grappa.transform.ParserTransformer;

import javax.annotation.Nonnull;
import java.lang.reflect.Constructor;
import java.util.Objects;

/**
 * Main class providing the high-level entry point into the parboiled library.
 */
public final class Grappa
{
    private Grappa()
    {
        throw new Error("nice try!");
    }

    /**
     * 

Creates a parser object whose rule creation methods can then be used * with one of the {@link ParseRunner} implementations.

*

Since parboiled needs to extend your parser with certain extra logic * (e.g. to prevent infinite recursions in recursive rule definitions) you * cannot create your parser object yourself, but have to go through this * method. Also your parser class has to be derived from {@link BaseParser}. * If you want to use a non-default constructor you can provide its * arguments to this method. Make sure your non-default constructor does not * use primitive type parameters (like "int") but rather their boxed * counterparts (like "Integer"), otherwise the constructor will not be * found.

*

Performing the rule analysis and extending the parser class is an * expensive process (time-wise) and can take up to several hundred * milliseconds for large grammars. However, this cost is only incurred once * per parser class and class loader. Subsequent calls to this method are * therefore fast once the initial extension has been performed.

* * @param parserClass the type of the parser to create * @param constructorArgs optional arguments to the parser class constructor * @return the ready to use parser instance */ public static

, V> P createParser( @Nonnull final Class

parserClass, final Object... constructorArgs) { Objects.requireNonNull(parserClass, "parserClass"); try { final Class extendedClass = ParserTransformer.transformParser(parserClass); final Constructor constructor = findConstructor(extendedClass, constructorArgs); @SuppressWarnings("unchecked") final P ret = (P) constructor.newInstance(constructorArgs); return ret; } catch (Exception e) { // TODO: catch better than Exception throw new RuntimeException( "Error creating extended parser class: " + e.getMessage(), e); } } /** * Generate the byte code of a transformed parser class * *

When you create a parser using {@link * #createParser(Class, Object...)}, Parboiled generates a new class which * is the one you actually use for parsing. This method allows to get the * byte code of such a generated class in a byte array.

* * @param parserClass the parser class * @param

class of the parser * @param see {@link BaseParser} * @return the byte code * * @throws RuntimeException byte code generation failure * @see ParserTransformer#getByteCode(Class) */ public static

, V> byte[] getByteCode( final Class

parserClass) { try { return ParserTransformer.getByteCode(parserClass); } catch (Exception e) { throw new RuntimeException("failed to generate byte code", e); } } private static Constructor findConstructor(final Class c, final Object[] arguments) { Class[] paramTypes; Object argument; outer: for (final Constructor constructor : c.getConstructors()) { paramTypes = constructor.getParameterTypes(); if (paramTypes.length != arguments.length) continue; for (int i = 0; i < arguments.length; i++) { argument = arguments[i]; if (argument != null && !paramTypes[i] .isAssignableFrom(argument.getClass())) continue outer; if (argument == null && paramTypes[i].isPrimitive()) continue outer; } return constructor; } throw new InvalidGrammarException("No constructor found for " + c + " and the given " + arguments.length+ " arguments"); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy