Files
jpexs-decompiler/trunk/src/com/jpexs/asdec/abc/methodinfo_parser/MethodInfoParser.java
T

216 lines
9.1 KiB
Java

/*
* Copyright (C) 2011 JPEXS
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.jpexs.asdec.abc.methodinfo_parser;
import com.jpexs.asdec.abc.ABC;
import com.jpexs.asdec.abc.types.MethodInfo;
import com.jpexs.asdec.abc.types.ValueKind;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class MethodInfoParser {
public static void parse(String text, MethodInfo update,ABC abc) throws ParseException {
MethodInfoLexer lexer = new MethodInfoLexer(new ByteArrayInputStream(text.getBytes()));
List<String> paramNames=new ArrayList<String>();
List<Long> paramTypes=new ArrayList<Long>();
List<ValueKind> optionalValues=new ArrayList<ValueKind>();
boolean hasOptional=false;
boolean needsRest=false;
try {
ParsedSymbol symb;
symb = lexer.yylex();
while (symb.type != ParsedSymbol.TYPE_EOF)
{
if(symb.type==ParsedSymbol.TYPE_DOTS)
{
needsRest=true;
symb = lexer.yylex();
if(symb.type!=ParsedSymbol.TYPE_IDENTIFIER)
{
throw new ParseException("Identifier expected", lexer.yyline());
}
symb = lexer.yylex();
if(symb.type!=ParsedSymbol.TYPE_EOF)
{
throw new ParseException("End expected after rest params", lexer.yyline());
}
break;
}
if(symb.type!=ParsedSymbol.TYPE_IDENTIFIER)
{
throw new ParseException("Identifier expected", lexer.yyline());
}
paramNames.add((String)symb.value);
symb = lexer.yylex();
if(symb.type==ParsedSymbol.TYPE_COLON){
ParsedSymbol symbType=lexer.yylex();
if(symbType.type==ParsedSymbol.TYPE_STAR)
{
paramTypes.add(new Long(0));
}else if(symbType.type==ParsedSymbol.TYPE_MULTINAME){
paramTypes.add((Long)symbType.value);
}else{
throw new ParseException("Multiname or * expected", lexer.yyline());
}
ParsedSymbol symbEqual=lexer.yylex();
if(symbEqual.type==ParsedSymbol.TYPE_ASSIGN)
{
hasOptional=true;
ParsedSymbol symbValue;
String nstype="";
do{
symbValue=lexer.yylex();
if(symbValue.type>=8&&symbValue.type<=13){
nstype=nstype+symbValue.type+":";
}
}while(symbValue.type>=8&&symbValue.type<=13);
if((!nstype.equals(""))&&(symbValue.type!=ParsedSymbol.TYPE_NAMESPACE))
{
throw new ParseException("Namespace expected", lexer.yyline());
}
int id=0;
switch(symbValue.type)
{
case ParsedSymbol.TYPE_INTEGER:
optionalValues.add(new ValueKind(abc.constants.forceGetIntId((Long)symbValue.value),ValueKind.CONSTANT_Int));
break;
case ParsedSymbol.TYPE_FLOAT:
optionalValues.add(new ValueKind(abc.constants.forceGetDoubleId((Double)symbValue.value),ValueKind.CONSTANT_Double));
break;
case ParsedSymbol.TYPE_STRING:
optionalValues.add(new ValueKind(abc.constants.forceGetStringId((String)symbValue.value),ValueKind.CONSTANT_Utf8));
break;
case ParsedSymbol.TYPE_TRUE:
optionalValues.add(new ValueKind(0,ValueKind.CONSTANT_True));
break;
case ParsedSymbol.TYPE_FALSE:
optionalValues.add(new ValueKind(0,ValueKind.CONSTANT_False));
break;
case ParsedSymbol.TYPE_NULL:
optionalValues.add(new ValueKind(0,ValueKind.CONSTANT_Null));
break;
case ParsedSymbol.TYPE_UNDEFINED:
optionalValues.add(new ValueKind(0,ValueKind.CONSTANT_Undefined));
break;
case ParsedSymbol.TYPE_NAMESPACE:
if(nstype.equals("9:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_PackageNamespace));
}else
if(nstype.equals("9:10:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_PackageInternalNs));
}else
if(nstype.equals("13:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_ProtectedNamespace));
}else
if(nstype.equals("12:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_ExplicitNamespace));
}else
if(nstype.equals("11:13:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_StaticProtectedNs));
}else
if(nstype.equals("8:")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_PrivateNs));
}else if(nstype.equals("")){
optionalValues.add(new ValueKind((int)(long)(Long)symbValue.value,ValueKind.CONSTANT_Namespace));
}else{
throw new ParseException("Invalid type of namespace", lexer.yyline());
}
break;
default:
throw new ParseException("Unexpected symbol", lexer.yyline());
}
symb=lexer.yylex();
if(symb.type==ParsedSymbol.TYPE_COMMA){
}else if(symb.type==ParsedSymbol.TYPE_EOF){
break;
}
}else if(symbEqual.type==ParsedSymbol.TYPE_COMMA){
if(hasOptional)
{
throw new ParseException("Parameter must have default value", lexer.yyline());
}
}else if(symbEqual.type==ParsedSymbol.TYPE_EOF){
if(hasOptional)
{
throw new ParseException("Parameter must have default value", lexer.yyline());
}
break;
} else {
throw new ParseException("Unexpected symbol", lexer.yyline());
}
}else if(symb.type==ParsedSymbol.TYPE_COMMA){
}else if(symb.type==ParsedSymbol.TYPE_EOF){
break;
}else{
throw new ParseException("Unexpected symbol", lexer.yyline());
}
symb = lexer.yylex();
}
} catch (IOException iex) {
}
if(needsRest&&(!optionalValues.isEmpty())){
throw new ParseException("Rest parameter canot be combined with default values", lexer.yyline());
}
update.param_types=new int[paramTypes.size()];
for(int p=0;p<paramTypes.size();p++)
{
update.param_types[p]=(int)(long)paramTypes.get(p);
}
update.optional=(ValueKind[])optionalValues.toArray(new ValueKind[optionalValues.size()]);
update.unsetFlagHas_optional();
if(!optionalValues.isEmpty()){
update.setFlagHas_optional();
}
update.unsetFlagNeed_rest();
if(needsRest){
update.setFlagNeed_rest();
}
update.unsetFlagHas_paramnames();
update.paramNames=new int[]{};
boolean useParamNames=false;
for(int p=0;p<paramNames.size();p++){
if(!paramNames.get(p).equals("param"+(p+1)))
{
useParamNames=true;
}
}
if(useParamNames){
update.setFlagHas_paramnames();
update.paramNames=new int[paramNames.size()];
for(int p=0;p<paramNames.size();p++){
update.paramNames[p]=abc.constants.forceGetStringId(paramNames.get(p));
}
}
}
}