Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
m * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.strobel.assembler.metadata.signatures;
import java.lang.reflect.GenericSignatureFormatError;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public final class SignatureParser
{
private final static boolean DEBUG = Boolean.getBoolean("DEBUG");
private final static TypeArgument[] EMPTY_TYPE_ARGUMENTS = new TypeArgument[0];
private final static char EOI = ':';
private char[] input; // the input signature
private int index = 0; // index into the input
private char current; // the value of the input at the current index
private SignatureParser()
{
}
/**
* Construct a new {@link SignatureParser} instance.
*/
public static SignatureParser make()
{
return new SignatureParser();
}
/*
* API
*/
public ClassSignature parseClassSignature(final String s)
{
if (DEBUG)
{
System.out.println("Parsing class sig:" + s);
}
_init(s);
return parseClassSignature();
}
public MethodTypeSignature parseMethodSignature(final String s)
{
if (DEBUG)
{
System.out.println("Parsing method sig:" + s);
}
_init(s);
return parseMethodTypeSignature();
}
public TypeSignature parseTypeSignature(final String s)
{
if (DEBUG)
{
System.out.println("Parsing type sig:" + s);
}
_init(s);
return parseTypeSignature();
}
/*
* Internal methods
*/
private char _current()
{
assert (index <= input.length);
if (index < input.length)
{
return input[index];
}
else
{
return EOI;
}
}
private void _init(final String s)
{
input = s.toCharArray();
index = 0;
current = _current();
}
private void advance()
{
assert (index <= input.length);
index++;
current = _current();
}
private Error error(final String errorMsg)
{
if (DEBUG)
{
System.out.println("Parse error:" + errorMsg);
}
return new GenericSignatureFormatError();
}
private ClassSignature parseClassSignature()
{
assert (index == 0);
return ClassSignature.make(
parseZeroOrMoreFormalTypeParameters(),
parseClassTypeSignature(),
parseSuperInterfaces()
);
}
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters()
{
if (current == '<')
{
return parseFormalTypeParameters();
}
else
{
return new FormalTypeParameter[0];
}
}
private FormalTypeParameter[] parseFormalTypeParameters()
{
final Collection ftps = new ArrayList<>(3);
assert (current == '<');
if (current != '<')
{
throw error("expected <");
}
advance();
ftps.add(parseFormalTypeParameter());
while (current != '>')
{
ftps.add(parseFormalTypeParameter());
}
advance();
final FormalTypeParameter[] formalTypeParameters = new FormalTypeParameter[ftps.size()];
return ftps.toArray(formalTypeParameters);
}
private FormalTypeParameter parseFormalTypeParameter()
{
return FormalTypeParameter.make(
parseIdentifier(),
parseZeroOrMoreBounds()
);
}
private String parseIdentifier()
{
final StringBuilder result = new StringBuilder();
while (!Character.isWhitespace(current))
{
final char c = current;
switch (c)
{
case ';':
case '.':
case '/':
case ':':
case '>':
case '<':
return result.toString();
default:
{
result.append(c);
advance();
}
}
}
return result.toString();
}
private FieldTypeSignature parseFieldTypeSignature()
{
switch (current)
{
case 'L':
return parseClassTypeSignature();
case 'T':
return parseTypeVariableSignature();
case '[':
return parseArrayTypeSignature();
default:
throw error("Expected Field Type Signature");
}
}
private ClassTypeSignature parseClassTypeSignature()
{
assert (current == 'L');
if (current != 'L')
{
throw error("expected a class type");
}
advance();
final List typeSignatures = new ArrayList<>(5);
typeSignatures.add(parseSimpleClassTypeSignature(false));
parseClassTypeSignatureSuffix(typeSignatures);
if (current != ';')
{
throw error("expected ';' got '" + current + "'");
}
advance();
return ClassTypeSignature.make(typeSignatures);
}
private SimpleClassTypeSignature parseSimpleClassTypeSignature(final boolean dollar)
{
final String id = parseIdentifier();
final int position = index;
final char c = current;
switch (c)
{
case ';':
case '/':
case '.':
case '$':
{
return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]);
}
case '<':
{
return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
}
default:
{
throw error(position + ": expected < or ; or /");
}
}
}
private void parseClassTypeSignatureSuffix(final List typeSignatures)
{
while (current == '/' || current == '.')
{
final boolean dollar = (current == '.');
advance();
typeSignatures.add(parseSimpleClassTypeSignature(dollar));
}
}
private TypeArgument[] parseTypeArguments()
{
final Collection tas = new ArrayList<>(3);
assert (current == '<');
if (current != '<')
{
throw error("expected <");
}
advance();
tas.add(parseTypeArgument());
while (current != '>')
{
// (matches(current, '+', '-', 'L', '[', 'T', '*')) {
tas.add(parseTypeArgument());
}
advance();
final TypeArgument[] taa = new TypeArgument[tas.size()];
return tas.toArray(taa);
}
private TypeArgument parseTypeArgument()
{
final char c = current;
switch (c)
{
case '+':
{
advance();
return Wildcard.make(BottomSignature.make(), parseFieldTypeSignature());
}
case '*':
{
advance();
return Wildcard.make(
BottomSignature.make(),
SimpleClassTypeSignature.make("java.lang.Object", false, EMPTY_TYPE_ARGUMENTS)
);
}
case '-':
{
advance();
return Wildcard.make(
parseFieldTypeSignature(),
SimpleClassTypeSignature.make("java.lang.Object", false, EMPTY_TYPE_ARGUMENTS)
);
}
default:
{
return parseFieldTypeSignature();
}
}
}
// TypeVariableSignature -> T identifier
private TypeVariableSignature parseTypeVariableSignature()
{
assert (current == 'T');
if (current != 'T')
{
throw error("expected a type variable usage");
}
advance();
final TypeVariableSignature ts =
TypeVariableSignature.make(parseIdentifier());
if (current != ';')
{
throw error("; expected in signature of type variable named" +
ts.getName());
}
advance();
return ts;
}
// ArrayTypeSignature -> [ TypeSignature
private ArrayTypeSignature parseArrayTypeSignature()
{
if (current != '[')
{
throw error("expected array type signature");
}
advance();
return ArrayTypeSignature.make(parseTypeSignature());
}
// TypeSignature -> BaseType | FieldTypeSignature
private TypeSignature parseTypeSignature()
{
switch (current)
{
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
case 'V':
return parseBaseType();
default:
return parseFieldTypeSignature();
}
}
private BaseType parseBaseType()
{
switch (current)
{
case 'B':
advance();
return ByteSignature.make();
case 'C':
advance();
return CharSignature.make();
case 'D':
advance();
return DoubleSignature.make();
case 'F':
advance();
return FloatSignature.make();
case 'I':
advance();
return IntSignature.make();
case 'J':
advance();
return LongSignature.make();
case 'S':
advance();
return ShortSignature.make();
case 'Z':
advance();
return BooleanSignature.make();
case 'V':
advance();
return VoidSignature.make();
default:
{
throw error("expected primitive type");
}
}
}
private FieldTypeSignature[] parseZeroOrMoreBounds()
{
final List fts = new ArrayList<>(3);
if (current == ':')
{
advance();
switch (current)
{
case ':': // empty class bound
fts.add(BottomSignature.make());
break;
default: // parse class bound
fts.add(parseFieldTypeSignature());
break;
}
// zero or more interface bounds
while (current == ':')
{
advance();
fts.add(parseFieldTypeSignature());
}
}
return fts.toArray(new FieldTypeSignature[fts.size()]);
}
private ClassTypeSignature[] parseSuperInterfaces()
{
final Collection cts =
new ArrayList<>(5);
while (current == 'L')
{
cts.add(parseClassTypeSignature());
}
final ClassTypeSignature[] cta = new ClassTypeSignature[cts.size()];
return cts.toArray(cta);
}
// parse a method signature based on the implicit input.
private MethodTypeSignature parseMethodTypeSignature()
{
assert (index == 0);
return MethodTypeSignature.make(
parseZeroOrMoreFormalTypeParameters(),
parseFormalParameters(),
parseReturnType(),
parseZeroOrMoreThrowsSignatures()
);
}
// (TypeSignature*)
private TypeSignature[] parseFormalParameters()
{
if (current != '(')
{
throw error("expected (");
}
advance();
final TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
if (current != ')')
{
throw error("expected )");
}
advance();
return pts;
}
// TypeSignature*
private TypeSignature[] parseZeroOrMoreTypeSignatures()
{
final Collection ts = new ArrayList<>();
boolean stop = false;
while (!stop)
{
switch (current)
{
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
case 'L':
case 'T':
case '[':
{
ts.add(parseTypeSignature());
break;
}
default:
stop = true;
}
}
/*
* while( matches(current, 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 'L', 'T', '[') ) {
* ts.add(parseTypeSignature()); }
*/
final TypeSignature[] ta = new TypeSignature[ts.size()];
return ts.toArray(ta);
}
// ReturnType -> V | TypeSignature
private ReturnType parseReturnType()
{
if (current == 'V')
{
advance();
return VoidSignature.make();
}
else
{
return parseTypeSignature();
}
}
// ThrowSignature*
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures()
{
final Collection ets =
new ArrayList<>(3);
while (current == '^')
{
ets.add(parseThrowsSignature());
}
final FieldTypeSignature[] eta = new FieldTypeSignature[ets.size()];
return ets.toArray(eta);
}
// ThrowSignature -> ^ FieldTypeSignature
private FieldTypeSignature parseThrowsSignature()
{
assert (current == '^');
if (current != '^')
{
throw error("expected throws signature");
}
advance();
return parseFieldTypeSignature();
}
}