/* * 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 paramNames=new ArrayList(); List paramTypes=new ArrayList(); List optionalValues=new ArrayList(); 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