001/* 002 * Copyright (C) 2009-2011 Mathias Doenitz 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.parboiled.parser; 018 019import org.parboiled.parserunners.ParseRunner; 020import org.parboiled.transform.ParserTransformer; 021import org.parboiled.parserunners.ParseRunner; 022 023import java.lang.reflect.Constructor; 024 025import static org.parboiled.common.Preconditions.checkArgNotNull; 026import static org.parboiled.common.Utils.findConstructor; 027 028/** 029 * Main class providing the high-level entry point into the parboiled library. 030 */ 031public class Parboiled { 032 033 protected Parboiled() {} 034 035 /** 036 * <p>Creates a parser object whose rule creation methods can then be used with one of the {@link ParseRunner} implementations.</p> 037 * <p>Since parboiled needs to extend your parser with certain extra logic (e.g. to prevent infinite recursions 038 * in recursive rule definitions) you cannot create your parser object yourself, but have to go through this method. 039 * Also your parser class has to be derived from {@link BaseParser}. If you want to use a non-default constructor 040 * you can provide its arguments to this method. Make sure your non-default constructor does not use primitive 041 * type parameters (like "int") but rather their boxed counterparts (like "Integer"), otherwise the constructor 042 * will not be found.</p> 043 * <p>Performing the rule analysis and extending the parser class is an expensive process (time-wise) and can 044 * take up to several hundred milliseconds for large grammars. However, this cost is only incurred once per 045 * parser class and class loader. Subsequent calls to this method are therefore fast once the initial extension 046 * has been performed.</p> 047 * 048 * @param parserClass the type of the parser to create 049 * @param constructorArgs optional arguments to the parser class constructor 050 * @return the ready to use parser instance 051 */ 052 @SuppressWarnings({"unchecked"}) 053 public static <P extends BaseParser<V>, V> P createParser(Class<P> parserClass, Object... constructorArgs) { 054 checkArgNotNull(parserClass, "parserClass"); 055 try { 056 Class<?> extendedClass = ParserTransformer.transformParser(parserClass); 057 Constructor constructor = findConstructor(extendedClass, constructorArgs); 058 return (P) constructor.newInstance(constructorArgs); 059 } catch (Exception e) { 060 throw new RuntimeException("Error creating extended parser class: " + e.getMessage(), e); 061 } 062 } 063 064}