/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.java.util;
import java.lang.reflect.Array;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.whole.lang.parsers.*;
import org.whole.lang.parsers.Lexer.Memento;
import org.whole.lang.util.StringUtils;
/**
* @generator Whole
*
* Modified to make it grammar independent
*/
public class JavaSignaturesPredictiveParser {
protected Lexer lexer;
protected ClassLoader loader;
protected boolean isVarArgs;
private static final String WHITESPACE = "\\p{javaWhitespace}";
private static final String IDENTIFIER_START = "\\p{javaJavaIdentifierStart}";
private static final String IDENTIFIER_PART = "\\p{javaJavaIdentifierPart}";
public JavaSignaturesPredictiveParser(Lexer lexer, ClassLoader loader) {
this.lexer = lexer;
this.loader = loader;
this.lexer.withDelimiter(java.util.regex.Pattern.compile(WHITESPACE+"*"));
}
public JavaSignaturesPredictiveParser(CharSequence text, ClassLoader loader) {
this(Lexer.createLexer(text), loader);
}
/* BEGIN copied from abstract predictive parser */
protected ParseException createParseError(String errorMessage) throws ParseException {
return new ParseException(lexer, errorMessage);
}
protected String nextToken(String regExp) {
return nextToken(java.util.regex.Pattern.compile(regExp));
}
protected String nextToken(Pattern compiledPatern) {
lexer.withPattern(compiledPatern);
if (lexer.hasNext())
return lexer.next();
throw createParseError("missing terminal");
}
protected Lexer.Memento mark() {
return lexer.mark();
}
protected void reset(Lexer.Memento memento) {
lexer.reset(memento);
}
protected boolean hitEnd() {
return lexer.hitEnd();
}
protected int getHorizonPosition() {
return lexer.getHorizonPosition();
}
protected int setHorizonPosition(int position, boolean force) {
return lexer.setHorizonPosition(position, force);
}
protected int setHorizonBySize(int length) {
try {
return lexer.setHorizonBySize(length);
} catch (IndexOutOfBoundsException e) {
throw createParseError(e.getLocalizedMessage());
}
}
protected int moveHorizonByDelimiter(String regExp, int endPosition) {
return moveHorizonByDelimiter(java.util.regex.Pattern.compile(regExp), endPosition);
}
protected int moveHorizonByDelimiter(Pattern compiledPattern, int endPosition) {
try {
return lexer.moveHorizonByDelimiter(compiledPattern, endPosition);
} catch (IndexOutOfBoundsException e) {
throw createParseError(e.getLocalizedMessage());
}
}
protected int setHorizonByDelimiter(String regExp) {
return setHorizonByDelimiter(java.util.regex.Pattern.compile(regExp));
}
protected int setHorizonByDelimiter(Pattern compiledPattern) {
try {
return lexer.setHorizonByDelimiter(compiledPattern);
} catch (IndexOutOfBoundsException e) {
throw createParseError(e.getLocalizedMessage());
}
}
protected int setHorizonByLines(int lines) {
try {
return lexer.setHorizonByLines(lines);
} catch (IndexOutOfBoundsException e) {
throw createParseError(e.getLocalizedMessage());
}
}
/* END copied from abstract predictive parser */
public List<JavaReflectUtils.JavaSignature> parseSignatures() {
List<JavaReflectUtils.JavaSignature> signatures = new ArrayList<JavaReflectUtils.JavaSignature>();
int count = 0;
while (true) {
if (count == 0 && !hasSignature() || count > 0 && !hasToken())
break;
if (count > 0)
matchToken();
isVarArgs = false;
signatures.add(parseSignature());
count++;
}
return signatures;
}
public JavaReflectUtils.JavaSignature parseSignature() {
String name = parseName();
matchToken1();
int horizon1 = setHorizonByDelimiter("\\)");
List<Class<?>> types = parseTypes();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken2();
return JavaReflectUtils.create(name, types.toArray(new Class<?>[0]), isVarArgs);
}
public String parseName() {
return nextToken(IDENTIFIER_START+IDENTIFIER_PART+"*");
}
public List<Class<?>> parseTypes() {
List<Class<?>> typeList = new ArrayList<Class<?>>();
int count = 0;
while (true) {
if (count == 0 && predictType() == -1 || count > 0 && !hasToken3())
break;
if (count > 0) {
if (isVarArgs)
throw createParseError("varArgs must be the last type parameter");
matchToken3();
}
typeList.add(parseType());
count++;
}
return typeList;
}
public Class<?> parseType() {
Class<?> type;
switch (predictType()) {
case 0 :
type = parseArrayType();
break;
case 1 :
type = parseParameterizedType();
break;
case 2 :
type = parseVarArgType();
break;
case 3 :
type = parseWildcardType();
break;
case 4 :
type = parsePrimitiveType();
break;
case 5 :
type = parseQualifiedType();
break;
default :
throw createParseError("missing choose step");
}
return type;
}
public Class<?> parseWildcardType() {
matchToken4();
return WildcardType.class;
}
public Class<?> parseArrayType() {
int horizon1 = setHorizonByDelimiter("\\[");
Lexer.Memento memento;
while (true) {
memento = mark();
try {
matchType();
if (hitEnd())
break;
reset(memento);
} catch (ParseException e) {
}
moveHorizonByDelimiter("\\[", horizon1);
}
int lastHorizon;
while (true) {
lastHorizon = getHorizonPosition();
try {
moveHorizonByDelimiter("\\[", horizon1);
matchType();
} catch (ParseException e) {
break;
}
}
reset(memento);
setHorizonPosition(lastHorizon, false);
Class<?> componentType = parseType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
int dimensions = parseDimensions();
return Array.newInstance(componentType, new int[dimensions]).getClass();
}
public int parseDimensions() {
return nextToken("((\\[\\])+)").length() / 2;
}
public Class<?> parseParameterizedType() {
int horizon1 = setHorizonByDelimiter("<");
Class<?> baseType = parseType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken5();
parseTypeParameters();
matchToken6();
return baseType;
}
public Class<?> parseVarArgType() {
isVarArgs = true;
int horizon1 = setHorizonByDelimiter("\\.\\.\\.");
Class<?> componentType = parseType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken7();
return Array.newInstance(componentType, 0).getClass();
}
public List<Class<?>> parseTypeParameters() {
List<Class<?>> typeList = new ArrayList<Class<?>>();
int count = 0;
while (count < 1) {
if (count > 0)
matchToken3();
typeList.add(parseType());
count++;
}
while (true) {
if (count == 0 && predictType() == -1 || count > 0 && !hasToken3())
break;
if (count > 0)
matchToken3();
typeList.add(parseType());
count++;
}
return typeList;
}
public Class<?> parsePrimitiveType() {
return StringUtils.primitiveClass(nextToken("char|boolean|byte|short|int|long|float|double"));
}
public Class<?> parseQualifiedType() {
String qtype = nextToken("("+IDENTIFIER_START+IDENTIFIER_PART+"*(\\."+IDENTIFIER_START+IDENTIFIER_PART+"*)*)");
qtype = StringUtils.isAmbiguous(qtype) ? "java.lang."+ qtype : qtype;
try {
return JavaReflectUtils.forName(qtype, loader);
} catch (IllegalArgumentException e) {
int index = qtype.lastIndexOf('.');
try {
return JavaReflectUtils.forName(qtype.substring(0, index)+"$"+qtype.substring(index+1), loader);
} catch (IllegalArgumentException x) {
throw e;
}
}
}
public int matchSignatures() {
int prediction = 0;
while (true) {
boolean added = false;
try {
matchSignature();
prediction++;
added = true;
matchToken();
} catch (ParseException e) {
if (!added && prediction > 0)
throw createParseError("cannot apply repeat rule");
if (prediction < 0)
throw createParseError("lower bound not reached in repeat rule");
break;
}
}
return prediction;
}
public boolean hasSignature() {
Memento memento = mark();
try {
matchSignature();
return true;
} catch (Exception e) {
return false;
} finally {
reset(memento);
}
}
public int matchSignature() {
int prediction = 0;
matchName();
matchToken1();
int horizon1 = setHorizonByDelimiter("\\)");
matchTypes();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken2();
return prediction;
}
public int matchName() {
int prediction = 0;
nextToken(IDENTIFIER_START+IDENTIFIER_PART+"*");
return prediction;
}
public int matchTypes() {
int prediction = 0;
while (true) {
boolean added = false;
try {
matchType();
prediction++;
added = true;
matchToken3();
} catch (ParseException e) {
if (!added && prediction > 0)
throw createParseError("cannot apply repeat rule");
if (prediction < 0)
throw createParseError("lower bound not reached in repeat rule");
break;
}
}
return prediction;
}
public int predictType() {
Memento memento = mark();
try {
return matchType();
} catch (Exception e) {
return -1;
} finally {
reset(memento);
}
}
public int matchType() {
int prediction = 0;
Lexer.Memento memento = mark();
while (true) {
try {
matchArrayType();
prediction = 0;
break;
} catch (ParseException e) {
reset(memento);
}
try {
matchParameterizedType();
prediction = 1;
break;
} catch (ParseException e) {
reset(memento);
}
try {
matchVarArgType();
prediction = 2;
break;
} catch (ParseException e) {
reset(memento);
}
try {
matchWildcardType();
prediction = 3;
break;
} catch (ParseException e) {
reset(memento);
}
try {
matchPrimitiveType();
prediction = 4;
break;
} catch (ParseException e) {
reset(memento);
}
try {
matchQualifiedType();
prediction = 5;
break;
} catch (ParseException e) {
reset(memento);
}
throw createParseError("cannot apply choose rule");
}
return prediction;
}
public int matchWildcardType() {
int prediction = 0;
matchToken4();
return prediction;
}
public int matchArrayType() {
int prediction = 0;
int horizon1 = setHorizonByDelimiter("\\[");
Lexer.Memento memento;
while (true) {
memento = mark();
try {
matchType();
if (hitEnd())
break;
reset(memento);
} catch (ParseException e) {
}
moveHorizonByDelimiter("\\[", horizon1);
}
int lastHorizon;
while (true) {
lastHorizon = getHorizonPosition();
try {
moveHorizonByDelimiter("\\[", horizon1);
matchType();
} catch (ParseException e) {
break;
}
}
reset(memento);
setHorizonPosition(lastHorizon, false);
matchType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchDimensions();
return prediction;
}
public int matchDimensions() {
int prediction = 0;
nextToken("((\\[\\])+)");
return prediction;
}
public int matchParameterizedType() {
int prediction = 0;
int horizon1 = setHorizonByDelimiter("<");
matchType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken5();
matchTypeParameters();
matchToken6();
return prediction;
}
public int matchVarArgType() {
int prediction = 0;
int horizon1 = setHorizonByDelimiter("\\.\\.\\.");
matchType();
if (hitEnd())
setHorizonPosition(horizon1, true);
else
throw createParseError("bad horizon constraint");
matchToken7();
return prediction;
}
public int matchTypeParameters() {
int prediction = 0;
while (true) {
boolean added = false;
try {
matchType();
prediction++;
added = true;
matchToken3();
} catch (ParseException e) {
if (!added && prediction > 0)
throw createParseError("cannot apply repeat rule");
if (prediction < 1)
throw createParseError("lower bound not reached in repeat rule");
break;
}
}
return prediction;
}
public int matchPrimitiveType() {
int prediction = 0;
nextToken("char|boolean|byte|short|int|long|float|double");
return prediction;
}
public int matchQualifiedType() {
int prediction = 0;
nextToken("("+IDENTIFIER_START+IDENTIFIER_PART+"*(\\."+IDENTIFIER_START+IDENTIFIER_PART+"*)*)");
return prediction;
}
public boolean hasToken() {
Memento memento = mark();
try {
matchToken();
return true;
} catch (Exception e) {
return false;
} finally {
reset(memento);
}
}
public int matchToken() {
int prediction = 0;
nextToken(";");
return prediction;
}
public int matchToken1() {
int prediction = 0;
nextToken("\\(");
return prediction;
}
public int matchToken2() {
int prediction = 0;
nextToken("\\)");
return prediction;
}
public boolean hasToken3() {
Memento memento = mark();
try {
matchToken3();
return true;
} catch (Exception e) {
return false;
} finally {
reset(memento);
}
}
public int matchToken3() {
int prediction = 0;
nextToken(",");
return prediction;
}
public int matchToken4() {
int prediction = 0;
nextToken("\\Q?\\E");
return prediction;
}
public int matchToken5() {
int prediction = 0;
nextToken("<");
return prediction;
}
public int matchToken6() {
int prediction = 0;
nextToken(">");
return prediction;
}
public int matchToken7() {
int prediction = 0;
nextToken("\\.\\.\\.");
return prediction;
}
}