diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index 16d20e1f5..c7c9b09c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -176,6 +176,9 @@ public class ActionScriptParser { } private GraphTargetItem memberOrCall(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + if(debugMode){ + System.out.println("memberOrCall:"); + } ParsedSymbol s = lex(); GraphTargetItem ret = newcmds; while (s.isType(SymbolType.DOT, SymbolType.PARENT_OPEN, SymbolType.BRACKET_OPEN, SymbolType.TYPENAME, SymbolType.FILTER)) { @@ -214,6 +217,10 @@ public class ActionScriptParser { } lexer.pushback(s); + + if(debugMode){ + System.out.println("/memberOrCall"); + } return ret; } @@ -245,6 +252,9 @@ public class ActionScriptParser { } private GraphTargetItem member(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, GraphTargetItem obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables) throws IOException, AVM2ParseException { + if(debugMode){ + System.out.println("member:"); + } GraphTargetItem ret = obj; ParsedSymbol s = lex(); while (s.isType(SymbolType.DOT, SymbolType.BRACKET_OPEN, SymbolType.TYPENAME)) { @@ -301,7 +311,15 @@ public class ActionScriptParser { s = lex(); } } - lexer.pushback(s); + if(s.type.getPrecedence() == GraphTargetItem.PRECEDENCE_ASSIGMENT){ + ret = expression1(ret, s.type.getPrecedence(), thisType, pkg, needsActivation, importedClasses, openedNamespaces, inMethod, registerVars, inFunction, inMethod, false, variables); + }else{ + lexer.pushback(s); + } + + if(debugMode){ + System.out.println("/member"); + } return ret; } @@ -1376,7 +1394,7 @@ public class ActionScriptParser { if (firstCommand instanceof NameAVM2Item) { NameAVM2Item nai = (NameAVM2Item) firstCommand; if (nai.isDefinition() && nai.getAssignedValue() == null) { //??? WUT - //firstCommand = expressionRemainder(thisType, pkg, needsActivation, openedNamespaces, firstCommand, registerVars, inFunction, inMethod, true, variables, importedClasses); + firstCommand = expression1(firstCommand,firstCommand.getPrecedence(),thisType, pkg, needsActivation, importedClasses,openedNamespaces,true, registerVars, inFunction, inMethod, true, variables); } } InAVM2Item inexpr = null; @@ -1773,6 +1791,9 @@ public class ActionScriptParser { private GraphTargetItem expression(TypeItem thisType, String pkg, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, AVM2ParseException { GraphTargetItem prim = expressionPrimary(thisType, pkg, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables); + if(prim==null){ + return null; + } return expression1(prim, GraphTargetItem.NOPRECEDENCE, thisType, pkg, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables); } @@ -2133,6 +2154,7 @@ public class ActionScriptParser { } needsActivation.setVal(true); ret = function(pkg, false, needsActivation, importedClasses, 0/*?*/, thisType, openedNamespaces, fname, false, variables); + ret = memberOrCall(thisType, pkg, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, variables); break; case NAN: ret = new NanAVM2Item(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java index 33772783b..2db4a120a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptParser.java @@ -146,6 +146,7 @@ import com.jpexs.decompiler.graph.model.WhileItem; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -253,6 +254,13 @@ public class ActionScriptParser { s = lex(); } lexer.pushback(s); + if (s.type.getPrecedence() == GraphTargetItem.PRECEDENCE_ASSIGMENT) { + ret = expression1(ret, s.type.getPrecedence(), registerVars, inFunction, inMethod, inMethod, variables); + } + + if (debugMode) { + System.out.println("/member"); + } return ret; } @@ -469,6 +477,9 @@ public class ActionScriptParser { } private GraphTargetItem expressionCommands(ParsedSymbol s, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, ActionParseException { + if (debugMode) { + System.out.println("expressionCommands:"); + } GraphTargetItem ret = null; switch (s.type) { case GETVERSION: @@ -581,6 +592,9 @@ public class ActionScriptParser { default: return null; } + if (debugMode) { + System.out.println("/expressionCommands"); + } return ret; } @@ -1153,7 +1167,7 @@ public class ActionScriptParser { ret = new ContinueItem(null, 0); //? There is no more than 1 level continue/break in AS1/2 break; case RETURN: - GraphTargetItem retexpr = expression(true, registerVars, inFunction, inMethod, true, variables); + GraphTargetItem retexpr = expression(registerVars, inFunction, inMethod, true, variables); if (retexpr == null) { retexpr = new DirectValueActionItem(null, 0, new Undefined(), new ArrayList()); } @@ -1195,20 +1209,19 @@ public class ActionScriptParser { case THROW: ret = new ThrowActionItem(null, expression(registerVars, inFunction, inMethod, true, variables)); break; + case SEMICOLON: //empty command + if (debugMode) { + System.out.println("/command"); + } + return null; default: GraphTargetItem valcmd = expressionCommands(s, registerVars, inFunction, inMethod, forinlevel, variables); if (valcmd != null) { ret = valcmd; break; } - if (s.type == SymbolType.SEMICOLON) { - return null; - } lexer.pushback(s); ret = expression(registerVars, inFunction, inMethod, true, variables); - if (debugMode) { - System.out.println("/command"); - } } if (debugMode) { System.out.println("/command"); @@ -1228,239 +1241,299 @@ public class ActionScriptParser { } private GraphTargetItem expression(HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, ActionParseException { - return expression(false, registerVars, inFunction, inMethod, allowRemainder, variables); - } - - private GraphTargetItem fixPrecedence(GraphTargetItem expr) { - GraphTargetItem ret = expr; - if (expr instanceof BinaryOp) { - BinaryOp bo = (BinaryOp) expr; - GraphTargetItem left = bo.getLeftSide(); - //GraphTargetItem right=bo.getRightSide(); - if (left.getPrecedence() > bo.getPrecedence()) { - if (left instanceof BinaryOp) { - BinaryOp leftBo = (BinaryOp) left; - bo.setLeftSide(leftBo.getRightSide()); - leftBo.setRightSide(expr); - return left; - } - } + if (debugMode) { + System.out.println("expression:"); + } + GraphTargetItem prim = expressionPrimary(false, registerVars, inFunction, inMethod, allowRemainder, variables); + if (prim == null) { + return null; + } + GraphTargetItem ret = expression1(prim, GraphTargetItem.NOPRECEDENCE, registerVars, inFunction, inMethod, allowRemainder, variables); + if (debugMode) { + System.out.println("/expression"); } return ret; } - private GraphTargetItem expressionRemainder(GraphTargetItem expr, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, ActionParseException { - GraphTargetItem ret = null; - ParsedSymbol s = lex(); - switch (s.type) { - case TERNAR: - GraphTargetItem terOnTrue = expression(registerVars, inFunction, inMethod, true, variables); + private ParsedSymbol peekLex() throws IOException, ActionParseException { + ParsedSymbol lookahead = lex(); + lexer.pushback(lookahead); + return lookahead; + } + + private static final String[] operatorIdentifiers = new String[]{"add", "eq", "ne", "lt", "ge", "gt", "le"}; + + private boolean isBinaryOperator(ParsedSymbol s) { + if (s.type == SymbolType.IDENTIFIER && Arrays.asList(operatorIdentifiers).contains(s.value.toString())) { + return true; + } + return s.type.isBinary(); + } + + private int getSymbPrecedence(ParsedSymbol s) { + if (s.type == SymbolType.IDENTIFIER && Arrays.asList(operatorIdentifiers).contains(s.value.toString())) { + switch (s.value.toString()) { + case "add": + return GraphTargetItem.PRECEDENCE_ADDITIVE; + case "eq": + case "ne": + return GraphTargetItem.PRECEDENCE_EQUALITY; + case "lt": + case "ge": + case "gt": + case "le": + return GraphTargetItem.PRECEDENCE_RELATIONAL; + } + } + return s.type.getPrecedence(); + } + + private GraphTargetItem expression1(GraphTargetItem lhs, int min_precedence, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, ActionParseException { + ParsedSymbol op; + GraphTargetItem rhs; + GraphTargetItem mhs = null; + ParsedSymbol lookahead = peekLex(); + if (debugMode) { + System.out.println("expression1:"); + } + //Note: algorithm from http://en.wikipedia.org/wiki/Operator-precedence_parser + //with relation operators reversed as we have precedence in reverse order + while (isBinaryOperator(lookahead) && getSymbPrecedence(lookahead) <= /* >= on wiki */ min_precedence) { + op = lookahead; + lex(); + + //Note: Handle ternar operator as Binary + //http://stackoverflow.com/questions/13681293/how-can-i-incorporate-ternary-operators-into-a-precedence-climbing-algorithm + if (op.type == SymbolType.TERNAR) { + if (debugMode) { + System.out.println("ternar-middle:"); + } + mhs = expression(registerVars, inFunction, inMethod, allowRemainder, variables); expectedType(SymbolType.COLON); - GraphTargetItem terOnFalse = expression(registerVars, inFunction, inMethod, true, variables); - ret = new TernarOpItem(null, expr, terOnTrue, terOnFalse); - break; - case SHIFT_LEFT: - ret = new LShiftActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case SHIFT_RIGHT: - ret = new RShiftActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case USHIFT_RIGHT: - ret = new URShiftActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case BITAND: - ret = new BitAndActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case BITOR: - ret = new BitOrActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case DIVIDE: - ret = new DivideActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case MODULO: - ret = new ModuloActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case EQUALS: - ret = new EqActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables), true/*FIXME SWF version?*/); - break; - case STRICT_EQUALS: - ret = new StrictEqActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case NOT_EQUAL: - ret = new NeqActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables), true/*FIXME SWF version?*/); - break; - case STRICT_NOT_EQUAL: - ret = new StrictNeqActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case LOWER_THAN: - ret = new LtActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables), true/*FIXME SWF version?*/); - break; - case LOWER_EQUAL: - ret = new LeActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case GREATER_THAN: - ret = new GtActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case GREATER_EQUAL: - ret = new GeActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables), true/*FIXME SWF version?*/); - break; - case AND: - ret = new AndItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case OR: - ret = new OrItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case FULLAND: - ret = new AndActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case FULLOR: - ret = new OrActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case MINUS: - ret = new SubtractActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case MULTIPLY: - ret = new MultiplyActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case PLUS: - ret = new AddActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables), true); - break; - case XOR: - ret = new BitXorActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case AS: - - break; - case INSTANCEOF: - ret = new InstanceOfActionItem(null, expr, expression(registerVars, inFunction, inMethod, false, variables)); - break; - case IS: - - break; - - case ASSIGN: - case ASSIGN_BITAND: - case ASSIGN_BITOR: - case ASSIGN_DIVIDE: - case ASSIGN_MINUS: - case ASSIGN_MODULO: - case ASSIGN_MULTIPLY: - case ASSIGN_PLUS: - case ASSIGN_SHIFT_LEFT: - case ASSIGN_SHIFT_RIGHT: - case ASSIGN_USHIFT_RIGHT: - case ASSIGN_XOR: - GraphTargetItem assigned = expression(registerVars, inFunction, inMethod, true, variables); - switch (s.type) { - case ASSIGN: - //assigned = assigned; - break; - case ASSIGN_BITAND: - assigned = new BitAndActionItem(null, expr, assigned); - break; - case ASSIGN_BITOR: - assigned = new BitOrActionItem(null, expr, assigned); - break; - case ASSIGN_DIVIDE: - assigned = new DivideActionItem(null, expr, assigned); - break; - case ASSIGN_MINUS: - assigned = new SubtractActionItem(null, expr, assigned); - break; - case ASSIGN_MODULO: - assigned = new ModuloActionItem(null, expr, assigned); - break; - case ASSIGN_MULTIPLY: - assigned = new MultiplyActionItem(null, expr, assigned); - break; - case ASSIGN_PLUS: - assigned = new AddActionItem(null, expr, assigned, true/*TODO:SWF version?*/); - break; - case ASSIGN_SHIFT_LEFT: - assigned = new LShiftActionItem(null, expr, assigned); - break; - case ASSIGN_SHIFT_RIGHT: - assigned = new RShiftActionItem(null, expr, assigned); - break; - case ASSIGN_USHIFT_RIGHT: - assigned = new URShiftActionItem(null, expr, assigned); - break; - case ASSIGN_XOR: - assigned = new BitXorActionItem(null, expr, assigned); - break; - } - if (expr instanceof VariableActionItem) { - ((VariableActionItem) expr).setStoreValue(assigned); - ((VariableActionItem) expr).setDefinition(false); - ret = expr; - } else if (expr instanceof GetMemberActionItem) { - ret = new SetMemberActionItem(null, ((GetMemberActionItem) expr).object, ((GetMemberActionItem) expr).memberName, assigned); - } else { - throw new ActionParseException("Invalid assignment", lexer.yyline()); + if (debugMode) { + System.out.println("/ternar-middle"); } + } + + rhs = expressionPrimary(allowRemainder, registerVars, inFunction, inMethod, allowRemainder, variables); + if (rhs == null) { + lexer.pushback(op); break; + } + + lookahead = peekLex(); + while ((isBinaryOperator(lookahead) && getSymbPrecedence(lookahead) < /* > on wiki */ getSymbPrecedence(op)) + || (lookahead.type.isRightAssociative() && getSymbPrecedence(lookahead) == getSymbPrecedence(op))) { + rhs = expression1(rhs, getSymbPrecedence(lookahead), registerVars, inFunction, inMethod, allowRemainder, variables); + lookahead = peekLex(); + } + + switch (op.type) { + case TERNAR: + lhs = new TernarOpItem(null, lhs, mhs, rhs); + break; + case SHIFT_LEFT: + lhs = new LShiftActionItem(null, lhs, rhs); + break; + case SHIFT_RIGHT: + lhs = new RShiftActionItem(null, lhs, rhs); + break; + case USHIFT_RIGHT: + lhs = new URShiftActionItem(null, lhs, rhs); + break; + case BITAND: + lhs = new BitAndActionItem(null, lhs, rhs); + break; + case BITOR: + lhs = new BitOrActionItem(null, lhs, rhs); + break; + case DIVIDE: + lhs = new DivideActionItem(null, lhs, rhs); + break; + case MODULO: + lhs = new ModuloActionItem(null, lhs, rhs); + break; + case EQUALS: + lhs = new EqActionItem(null, lhs, rhs, true/*FIXME SWF version?*/); + break; + case STRICT_EQUALS: + lhs = new StrictEqActionItem(null, lhs, rhs); + break; + case NOT_EQUAL: + lhs = new NeqActionItem(null, lhs, rhs, true/*FIXME SWF version?*/); + break; + case STRICT_NOT_EQUAL: + lhs = new StrictNeqActionItem(null, lhs, rhs); + break; + case LOWER_THAN: + lhs = new LtActionItem(null, lhs, rhs, true/*FIXME SWF version?*/); + break; + case LOWER_EQUAL: + lhs = new LeActionItem(null, lhs, rhs); + break; + case GREATER_THAN: + lhs = new GtActionItem(null, lhs, rhs); + break; + case GREATER_EQUAL: + lhs = new GeActionItem(null, lhs, rhs, true/*FIXME SWF version?*/); + break; + case AND: + lhs = new AndItem(null, lhs, rhs); + break; + case OR: + lhs = new OrItem(null, lhs, rhs); + break; + case FULLAND: + lhs = new AndActionItem(null, lhs, rhs); + break; + case FULLOR: + lhs = new OrActionItem(null, lhs, rhs); + break; + case MINUS: + lhs = new SubtractActionItem(null, lhs, rhs); + break; + case MULTIPLY: + lhs = new MultiplyActionItem(null, lhs, rhs); + break; + case PLUS: + lhs = new AddActionItem(null, lhs, rhs, true); + break; + case XOR: + lhs = new BitXorActionItem(null, lhs, rhs); + break; + case AS: + + break; + case INSTANCEOF: + lhs = new InstanceOfActionItem(null, lhs, rhs); + break; + case IS: + + break; + + case ASSIGN: + case ASSIGN_BITAND: + case ASSIGN_BITOR: + case ASSIGN_DIVIDE: + case ASSIGN_MINUS: + case ASSIGN_MODULO: + case ASSIGN_MULTIPLY: + case ASSIGN_PLUS: + case ASSIGN_SHIFT_LEFT: + case ASSIGN_SHIFT_RIGHT: + case ASSIGN_USHIFT_RIGHT: + case ASSIGN_XOR: + GraphTargetItem assigned = rhs; + switch (lookahead.type) { + case ASSIGN: + //assigned = assigned; + break; + case ASSIGN_BITAND: + assigned = new BitAndActionItem(null, lhs, assigned); + break; + case ASSIGN_BITOR: + assigned = new BitOrActionItem(null, lhs, assigned); + break; + case ASSIGN_DIVIDE: + assigned = new DivideActionItem(null, lhs, assigned); + break; + case ASSIGN_MINUS: + assigned = new SubtractActionItem(null, lhs, assigned); + break; + case ASSIGN_MODULO: + assigned = new ModuloActionItem(null, lhs, assigned); + break; + case ASSIGN_MULTIPLY: + assigned = new MultiplyActionItem(null, lhs, assigned); + break; + case ASSIGN_PLUS: + assigned = new AddActionItem(null, lhs, assigned, true/*TODO:SWF version?*/); + break; + case ASSIGN_SHIFT_LEFT: + assigned = new LShiftActionItem(null, lhs, assigned); + break; + case ASSIGN_SHIFT_RIGHT: + assigned = new RShiftActionItem(null, lhs, assigned); + break; + case ASSIGN_USHIFT_RIGHT: + assigned = new URShiftActionItem(null, lhs, assigned); + break; + case ASSIGN_XOR: + assigned = new BitXorActionItem(null, lhs, assigned); + break; + } + if (lhs instanceof VariableActionItem) { + ((VariableActionItem) lhs).setStoreValue(assigned); + ((VariableActionItem) lhs).setDefinition(false); + lhs = lhs; + } else if (lhs instanceof GetMemberActionItem) { + lhs = new SetMemberActionItem(null, ((GetMemberActionItem) lhs).object, ((GetMemberActionItem) lhs).memberName, assigned); + } else { + throw new ActionParseException("Invalid assignment", lexer.yyline()); + } + break; + case IDENTIFIER: + switch (lookahead.value.toString()) { + case "add": + lhs = new StringAddActionItem(null, lhs, rhs); + break; + case "eq": + lhs = new StringEqActionItem(null, lhs, rhs); + break; + case "ne": + lhs = new StringNeActionItem(null, lhs, rhs); + break; + case "lt": + lhs = new StringLtActionItem(null, lhs, rhs); + break; + case "ge": + lhs = new StringGeActionItem(null, lhs, rhs); + break; + case "gt": + lhs = new StringGtActionItem(null, lhs, rhs); + break; + case "le": + lhs = new StringLeActionItem(null, lhs, rhs); + break; + } + break; + } + } + + switch (lookahead.type) { case INCREMENT: //postincrement - if (!(expr instanceof VariableActionItem) && !(expr instanceof GetMemberActionItem)) { + lex(); + if (!(lhs instanceof VariableActionItem) && !(lhs instanceof GetMemberActionItem)) { throw new ActionParseException("Invalid assignment", lexer.yyline()); } - ret = new PostIncrementActionItem(null, expr); + lhs = new PostIncrementActionItem(null, lhs); break; case DECREMENT: //postdecrement - if (!(expr instanceof VariableActionItem) && !(expr instanceof GetMemberActionItem)) { + lex(); + if (!(lhs instanceof VariableActionItem) && !(lhs instanceof GetMemberActionItem)) { throw new ActionParseException("Invalid assignment", lexer.yyline()); } - ret = new PostDecrementActionItem(null, expr); + lhs = new PostDecrementActionItem(null, lhs); break; case DOT: //member case BRACKET_OPEN: //member case PARENT_OPEN: //function call - lexer.pushback(s); - ret = memberOrCall(expr, registerVars, inFunction, inMethod, variables); - break; - case IDENTIFIER: - switch (s.value.toString()) { - case "add": - ret = new StringAddActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "eq": - ret = new StringEqActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "ne": - ret = new StringNeActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "lt": - ret = new StringLtActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "ge": - ret = new StringGeActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "gt": - ret = new StringGtActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - case "le": - ret = new StringLeActionItem(null, expr, expression(registerVars, inFunction, inMethod, allowRemainder, variables)); - break; - default: - lexer.pushback(s); - } + lhs = memberOrCall(lhs, registerVars, inFunction, inMethod, variables); break; default: - lexer.pushback(s); - } - - if (ret == null) { - if (expr instanceof ParenthesisItem) { - if (isType(((ParenthesisItem) expr).value)) { - GraphTargetItem expr2 = expression(false, registerVars, inFunction, inMethod, true, variables); - if (expr2 != null) { - ret = new CastOpActionItem(null, ((ParenthesisItem) expr).value, expr2); + if (lhs instanceof ParenthesisItem) { + if (isType(((ParenthesisItem) lhs).value)) { + GraphTargetItem expr2 = expression(registerVars, inFunction, inMethod, true, variables); + if (expr2 != null) { + lhs = new CastOpActionItem(null, ((ParenthesisItem) lhs).value, expr2); + } } } - } } - - ret = fixPrecedence(ret); - return ret; + if (debugMode) { + System.out.println("/expression1"); + } + return lhs; } private boolean isType(GraphTargetItem item) { @@ -1522,29 +1595,28 @@ public class ActionScriptParser { return new CommaExpressionItem(null, expr); } - private GraphTargetItem expression(boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, ActionParseException { + private GraphTargetItem expressionPrimary(boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables) throws IOException, ActionParseException { if (debugMode) { - System.out.println("expression:"); + System.out.println("primary:"); } GraphTargetItem ret = null; ParsedSymbol s = lex(); - boolean existsRemainder = false; - boolean assocRight = false; + switch (s.type) { case NEGATE: versionRequired(s, 5); ret = expression(registerVars, inFunction, inMethod, false, variables); ret = new BitXorActionItem(null, ret, new DirectValueActionItem(4.294967295E9)); - existsRemainder = true; + break; case MINUS: s = lex(); if (s.isType(SymbolType.DOUBLE)) { ret = new DirectValueActionItem(null, 0, -(double) (Double) s.value, new ArrayList()); - existsRemainder = true; + } else if (s.isType(SymbolType.INTEGER)) { ret = new DirectValueActionItem(null, 0, -(long) (Long) s.value, new ArrayList()); - existsRemainder = true; + } else { lexer.pushback(s); GraphTargetItem num = expression(registerVars, inFunction, inMethod, true, variables); @@ -1572,22 +1644,22 @@ public class ActionScriptParser { break; case TYPEOF: ret = new TypeOfActionItem(null, expression(registerVars, inFunction, inMethod, false, variables)); - existsRemainder = true; + break; case TRUE: ret = new DirectValueActionItem(null, 0, Boolean.TRUE, new ArrayList()); - existsRemainder = true; + break; case NULL: ret = new DirectValueActionItem(null, 0, new Null(), new ArrayList()); - existsRemainder = true; + break; case UNDEFINED: ret = new DirectValueActionItem(null, 0, new Undefined(), new ArrayList()); break; case FALSE: ret = new DirectValueActionItem(null, 0, Boolean.FALSE, new ArrayList()); - existsRemainder = true; + break; case CURLY_OPEN: //Object literal s = lex(); @@ -1628,24 +1700,24 @@ public class ActionScriptParser { case STRING: ret = pushConst(s.value.toString()); ret = memberOrCall(ret, registerVars, inFunction, inMethod, variables); - existsRemainder = true; + break; case NEWLINE: ret = new DirectValueActionItem(null, 0, "\r", new ArrayList()); - existsRemainder = true; + break; case NAN: ret = new DirectValueActionItem(null, 0, Double.NaN, new ArrayList()); - existsRemainder = true; + break; case INFINITY: ret = new DirectValueActionItem(null, 0, Double.POSITIVE_INFINITY, new ArrayList()); - existsRemainder = true; + break; case INTEGER: case DOUBLE: ret = new DirectValueActionItem(null, 0, s.value, new ArrayList()); - existsRemainder = true; + break; case DELETE: GraphTargetItem varDel = variable(registerVars, inFunction, inMethod, variables); @@ -1665,17 +1737,17 @@ public class ActionScriptParser { if (s.type == SymbolType.DECREMENT) { ret = new PreDecrementActionItem(null, prevar); } - existsRemainder = true; + break; case NOT: ret = new NotItem(null, expression(registerVars, inFunction, inMethod, false, variables)); - existsRemainder = true; + break; case PARENT_OPEN: ret = new ParenthesisItem(null, expression(registerVars, inFunction, inMethod, true, variables)); expectedType(SymbolType.PARENT_CLOSE); ret = memberOrCall(ret, registerVars, inFunction, inMethod, variables); - existsRemainder = true; + break; case NEW: GraphTargetItem newvar = variable(registerVars, inFunction, inMethod, variables); @@ -1688,7 +1760,7 @@ public class ActionScriptParser { } else { throw new ActionParseException("Invalid new item", lexer.yyline()); } - existsRemainder = true; + break; case EVAL: expectedType(SymbolType.PARENT_OPEN); @@ -1696,7 +1768,7 @@ public class ActionScriptParser { expectedType(SymbolType.PARENT_CLOSE); evar = memberOrCall(evar, registerVars, inFunction, inMethod, variables); ret = evar; - existsRemainder = true; + break; case IDENTIFIER: case THIS: @@ -1709,28 +1781,20 @@ public class ActionScriptParser { var = memberOrCall(var, registerVars, inFunction, inMethod, variables); ret = var; } - existsRemainder = true; + break; default: GraphTargetItem excmd = expressionCommands(s, registerVars, inFunction, inMethod, -1, variables); if (excmd != null) { - existsRemainder = true; //? + //? ret = excmd; break; } lexer.pushback(s); } - if (allowRemainder && existsRemainder) { - GraphTargetItem rem = ret; - do { - rem = expressionRemainder(rem, registerVars, inFunction, inMethod, assocRight, variables); - if (rem != null) { - ret = rem; - } - } while ((!assocRight) && (rem != null)); - } + if (debugMode) { - System.out.println("/expression"); + System.out.println("/primary"); } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java index 2dc66039e..127046a4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/SymbolType.java @@ -12,9 +12,12 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action.parser.script; +import com.jpexs.decompiler.graph.GraphTargetItem; + /** * * @author JPEXS @@ -31,10 +34,10 @@ public enum SymbolType { ELSE, FOR, EACH, - IN, + IN(GraphTargetItem.PRECEDENCE_RELATIONAL,true), IF, RETURN, - SUPER, + SUPER (GraphTargetItem.PRECEDENCE_PRIMARY,false), SWITCH, THROW, TRY, @@ -51,7 +54,7 @@ public enum SymbolType { CLASS, CONST, EXTENDS, - FUNCTION, + FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY,false), GET, IMPLEMENTS, INTERFACE, @@ -61,126 +64,158 @@ public enum SymbolType { VAR, IMPORT, USE, - FALSE, - NULL, - THIS, - TRUE, + FALSE (GraphTargetItem.PRECEDENCE_PRIMARY,false), + NULL (GraphTargetItem.PRECEDENCE_PRIMARY,false), + THIS (GraphTargetItem.PRECEDENCE_PRIMARY,false), + TRUE (GraphTargetItem.PRECEDENCE_PRIMARY,false), //Operators - PARENT_OPEN, - PARENT_CLOSE, - CURLY_OPEN, - CURLY_CLOSE, - BRACKET_OPEN, - BRACKET_CLOSE, - SEMICOLON, - COMMA, - REST, - DOT, - ASSIGN, - GREATER_THAN, - LOWER_THAN, - NOT, - NEGATE, - TERNAR, - COLON, - EQUALS, - STRICT_EQUALS, - LOWER_EQUAL, - GREATER_EQUAL, - NOT_EQUAL, - STRICT_NOT_EQUAL, - AND, - OR, - FULLAND, - FULLOR, - INCREMENT, - DECREMENT, - PLUS, - MINUS, - MULTIPLY, - DIVIDE, - BITAND, - BITOR, - XOR, - MODULO, - SHIFT_LEFT, - SHIFT_RIGHT, - USHIFT_RIGHT, - ASSIGN_PLUS, - ASSIGN_MINUS, - ASSIGN_MULTIPLY, - ASSIGN_DIVIDE, - ASSIGN_BITAND, - ASSIGN_BITOR, - ASSIGN_XOR, - ASSIGN_MODULO, - ASSIGN_SHIFT_LEFT, - ASSIGN_SHIFT_RIGHT, - ASSIGN_USHIFT_RIGHT, - AS, - DELETE, - INSTANCEOF, - IS, - NAMESPACE_OP, - NEW, - TYPEOF, - VOID, + PARENT_OPEN (GraphTargetItem.PRECEDENCE_PRIMARY,false), + PARENT_CLOSE (GraphTargetItem.PRECEDENCE_PRIMARY,false), + CURLY_OPEN (GraphTargetItem.PRECEDENCE_PRIMARY,false), + CURLY_CLOSE (GraphTargetItem.PRECEDENCE_PRIMARY,false), + BRACKET_OPEN (GraphTargetItem.PRECEDENCE_PRIMARY,false), + BRACKET_CLOSE (GraphTargetItem.PRECEDENCE_PRIMARY,false), + SEMICOLON , + COMMA (GraphTargetItem.PRECEDENCE_COMMA,false), + REST , + DOT (GraphTargetItem.PRECEDENCE_PRIMARY,false), + ASSIGN (GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + GREATER_THAN (GraphTargetItem.PRECEDENCE_RELATIONAL,true), + LOWER_THAN (GraphTargetItem.PRECEDENCE_RELATIONAL,true), + NOT(GraphTargetItem.PRECEDENCE_UNARY,false), + NEGATE (GraphTargetItem.PRECEDENCE_UNARY,false), + TERNAR (GraphTargetItem.PRECEDENCE_CONDITIONAL,true,true), /*!! ternar !!!*/ + COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL,false),/*!! ternar !!!*/ + EQUALS (GraphTargetItem.PRECEDENCE_EQUALITY,true), + STRICT_EQUALS (GraphTargetItem.PRECEDENCE_EQUALITY,true), + LOWER_EQUAL (GraphTargetItem.PRECEDENCE_RELATIONAL,true), + GREATER_EQUAL (GraphTargetItem.PRECEDENCE_RELATIONAL,true), + NOT_EQUAL (GraphTargetItem.PRECEDENCE_EQUALITY,true), + STRICT_NOT_EQUAL (GraphTargetItem.PRECEDENCE_EQUALITY,true), + AND(GraphTargetItem.PRECEDENCE_LOGICALAND,true), + OR(GraphTargetItem.PRECEDENCE_LOGICALOR,true), + FULLAND(GraphTargetItem.PRECEDENCE_LOGICALAND,true), + FULLOR(GraphTargetItem.PRECEDENCE_LOGICALOR,true), + INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX,false),//OR Unary + DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX,false), //OR Unary + PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE,true), + MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE,true), //OR Unary + MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE,true), + DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE,true), + BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND,true), + BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR,true), + XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR,true), + MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT,true), + SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT,true), + SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT,true), + USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT,true), + ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT,true,true), + AS(GraphTargetItem.PRECEDENCE_RELATIONAL,true), + DELETE(GraphTargetItem.PRECEDENCE_UNARY,false), + INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL,true), + IS(GraphTargetItem.PRECEDENCE_RELATIONAL,true), + NAMESPACE_OP (GraphTargetItem.PRECEDENCE_PRIMARY,false), + NEW(GraphTargetItem.PRECEDENCE_PRIMARY,false), + TYPEOF (GraphTargetItem.PRECEDENCE_UNARY,false), + VOID , ATTRIBUTE, //Other - STRING, + STRING(GraphTargetItem.PRECEDENCE_PRIMARY,false), COMMENT, XML, - IDENTIFIER, - INTEGER, - DOUBLE, - TYPENAME, + IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY,false), + INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY,false), + DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY,false), + TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY,false), EOF, - TRACE, - GETURL, - GOTOANDSTOP, - NEXTFRAME, - PLAY, - PREVFRAME, - TELLTARGET, - STOP, - STOPALLSOUNDS, - TOGGLEHIGHQUALITY, - ORD, - CHR, - DUPLICATEMOVIECLIP, - STOPDRAG, - GETTIMER, - LOADVARIABLES, - LOADMOVIE, - GOTOANDPLAY, - MBORD, - MBCHR, - MBLENGTH, - MBSUBSTRING, - RANDOM, - REMOVEMOVIECLIP, - STARTDRAG, - SUBSTR, - LENGTH, //string.length - INT, - TARGETPATH, - NUMBER_OP, - STRING_OP, + TRACE(GraphTargetItem.PRECEDENCE_PRIMARY,false), + GETURL(GraphTargetItem.PRECEDENCE_PRIMARY,false), + GOTOANDSTOP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + NEXTFRAME(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PLAY(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PREVFRAME(GraphTargetItem.PRECEDENCE_PRIMARY,false), + TELLTARGET(GraphTargetItem.PRECEDENCE_PRIMARY,false), + STOP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + STOPALLSOUNDS(GraphTargetItem.PRECEDENCE_PRIMARY,false), + TOGGLEHIGHQUALITY(GraphTargetItem.PRECEDENCE_PRIMARY,false), + ORD(GraphTargetItem.PRECEDENCE_PRIMARY,false), + CHR(GraphTargetItem.PRECEDENCE_PRIMARY,false), + DUPLICATEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + STOPDRAG(GraphTargetItem.PRECEDENCE_PRIMARY,false), + GETTIMER(GraphTargetItem.PRECEDENCE_PRIMARY,false), + LOADVARIABLES(GraphTargetItem.PRECEDENCE_PRIMARY,false), + LOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY,false), + GOTOANDPLAY(GraphTargetItem.PRECEDENCE_PRIMARY,false), + MBORD(GraphTargetItem.PRECEDENCE_PRIMARY,false), + MBCHR(GraphTargetItem.PRECEDENCE_PRIMARY,false), + MBLENGTH(GraphTargetItem.PRECEDENCE_PRIMARY,false), + MBSUBSTRING(GraphTargetItem.PRECEDENCE_PRIMARY,false), + RANDOM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + REMOVEMOVIECLIP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + STARTDRAG(GraphTargetItem.PRECEDENCE_PRIMARY,false), + SUBSTR(GraphTargetItem.PRECEDENCE_PRIMARY,false), + LENGTH(GraphTargetItem.PRECEDENCE_PRIMARY,false), //string.length + INT(GraphTargetItem.PRECEDENCE_PRIMARY,false), + TARGETPATH(GraphTargetItem.PRECEDENCE_PRIMARY,false), + NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY,false), IFFRAMELOADED, - INFINITY, - EVAL, - UNDEFINED, - NEWLINE, - NAN, - GETVERSION, - CALL, - LOADMOVIENUM, - LOADVARIABLESNUM, - PRINT, - PRINTNUM, - PRINTASBITMAP, - PRINTASBITMAPNUM, - UNLOADMOVIE, - UNLOADMOVIENUM, - FSCOMMAND + INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY,false), + EVAL(GraphTargetItem.PRECEDENCE_PRIMARY,false), + UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY,false), + NEWLINE(GraphTargetItem.PRECEDENCE_PRIMARY,false), + NAN(GraphTargetItem.PRECEDENCE_PRIMARY,false), + GETVERSION(GraphTargetItem.PRECEDENCE_PRIMARY,false), + CALL(GraphTargetItem.PRECEDENCE_PRIMARY,false), + LOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + LOADVARIABLESNUM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PRINT(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PRINTNUM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PRINTASBITMAP(GraphTargetItem.PRECEDENCE_PRIMARY,false), + PRINTASBITMAPNUM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + UNLOADMOVIE(GraphTargetItem.PRECEDENCE_PRIMARY,false), + UNLOADMOVIENUM(GraphTargetItem.PRECEDENCE_PRIMARY,false), + FSCOMMAND(GraphTargetItem.PRECEDENCE_PRIMARY,false); + + private int precedence = GraphTargetItem.NOPRECEDENCE; + private boolean binary = false; + private boolean rightAssociative = false; + + public boolean isBinary() { + return binary; + } + + public boolean isRightAssociative() { + return rightAssociative; + } + + public int getPrecedence() { + return precedence; + } + + + private SymbolType(int precedence,boolean binary){ + this.precedence = precedence; + this.binary = binary; + } + + private SymbolType(int precedence,boolean binary, boolean rightAssociative){ + this.precedence = precedence; + this.binary = binary; + this.rightAssociative = rightAssociative; + } + + private SymbolType(){ + + } }