From f4e3d99aeaf789f8ffc44d8a5049d14e758fb5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 8 Jun 2025 14:20:52 +0200 Subject: [PATCH] Fixed: #2466 AS1/2/3 Highlighter freezing - expression missing operand, + also fixed saving --- .../parser/script/ActionScript3Parser.java | 5 +- .../script/ActionScript3SimpleParser.java | 24 +-- .../parser/script/ActionScript2Parser.java | 7 +- .../script/ActionScript2SimpleParser.java | 7 +- .../flash/simpleparser/SimpleParser.java | 178 +++++++++--------- 5 files changed, 114 insertions(+), 107 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index d8e1c0c5f..82fff2a44 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -2213,8 +2213,9 @@ public class ActionScript3Parser { rhs = expressionPrimary(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables, abc); if (rhs == null) { - lexer.pushback(op); - break; + throw new AVM2ParseException("Missing operand", lexer.yyline()); + //lexer.pushback(op); + //break; } lookahead = peekExprToken(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java index 0984b8163..2e6a61115 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java @@ -87,7 +87,6 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } - int varLenBefore = variables.size(); boolean t = true; name(errors, thisType, needsActivation, openedNamespaces, null, false, false, true, variables, importedClasses, abc); @@ -240,9 +239,9 @@ public class ActionScript3SimpleParser implements SimpleParser { expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER); } lastVarName += propName + "::" + s.value.toString(); - variables.add(new Variable(false, lastVarName, s.position, null)); + variables.add(new Variable(false, lastVarName, s.position, null)); } else { - lastVarName += propName; + lastVarName += propName; variables.add(new Variable(false, lastVarName, propPosition, null)); if (s.type == SymbolType.NAMESPACESUFFIX) { //nsSuffix = "#" + s.value; @@ -711,7 +710,7 @@ public class ActionScript3SimpleParser implements SimpleParser { method(errors, outsidePackage, isPrivate, isInterface, isNative, customNs, new Reference<>(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, fname, true, classVariables, abc, fnamePos, returnTypeRef); traitVariables.add(new ClassTrait(fullClassName, fname, customNs, fnamePos, isStatic, "Function", returnTypeRef.getVal())); - + /* if (isGetter) { if (!ft.paramTypes.isEmpty()) { @@ -785,14 +784,14 @@ public class ActionScript3SimpleParser implements SimpleParser { String traitType = "*"; if (s.type == SymbolType.COLON) { - traitType = type(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, classVariables, abc); + traitType = type(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, classVariables, abc); s = lex(); } else { //* } traitVariables.add(new ClassTrait(fullClassName, nameSymbol.value.toString(), customNs, nameSymbol.position, isStatic, traitType, "Function".equals(traitType) ? "*" : null)); - + if (s.type == SymbolType.ASSIGN) { List constVarVariables = new ArrayList<>(); expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, isStatic, true, constVarVariables, false, abc); @@ -834,7 +833,7 @@ public class ActionScript3SimpleParser implements SimpleParser { Stack sinitLoops = new Stack<>(); Map sinitLoopLabels = new HashMap<>(); - HashMap sinitRegisterVars = new HashMap<>(); + HashMap sinitRegisterVars = new HashMap<>(); while (scriptTraitsBlock( errors, importedClasses, @@ -846,7 +845,7 @@ public class ActionScript3SimpleParser implements SimpleParser { sinitLoopLabels, sinitRegisterVars, sinitVariables, - externalTypes + externalTypes )) { //empty } @@ -1028,7 +1027,7 @@ public class ActionScript3SimpleParser implements SimpleParser { Reference returnTypeRef = new Reference<>(null); method(errors, !inPackage, false, false, isNative, null, new Reference<>(false), importedClasses, false, isFinal, null, openedNamespaces, true, "", true, sinitVariables, abc, s.position, returnTypeRef); - + sinitTraitVariables.add(new Variable(true, fname, s.position, true, "Function", returnTypeRef.getVal())); break; case CONST: @@ -1051,7 +1050,6 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); } sinitTraitVariables.add(new Variable(true, traitSymb.value.toString(), traitSymb.position, null, traitType, traitType.equals("Function") ? "*" : null)); - if (s.type == SymbolType.ASSIGN) { expression(errors, null, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, true, true, sinitVariables, false, abc); @@ -1671,13 +1669,17 @@ public class ActionScript3SimpleParser implements SimpleParser { rhs = expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); if (!rhs) { lexer.pushback(op); - break; + errors.add(new SimpleParseException("Missing operand", lexer.yyline(), op.position)); + return false; } lookahead = peekExprToken(); while ((lookahead.type.isBinary() && lookahead.type.getPrecedence() < /* > on wiki */ op.type.getPrecedence()) || (lookahead.type.isRightAssociative() && lookahead.type.getPrecedence() == op.type.getPrecedence())) { rhs = expression1(errors, rhs, lookahead.type.getPrecedence(), thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); + if (!rhs) { + break; + } lookahead = peekExprToken(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index 38e7dd5a5..678b9a195 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -184,7 +184,7 @@ import java.util.Map; public class ActionScript2Parser { private static final GraphTargetDialect DIALECT = ActionGraphTargetDialect.INSTANCE; - + /** * Builtin classes that can be casted to */ @@ -1531,8 +1531,9 @@ public class ActionScript2Parser { rhs = expressionPrimary(allowRemainder, inFunction, inMethod, inTellTarget, allowRemainder, variables, functions, true, hasEval); if (rhs == null) { - lexer.pushback(op); - break; + throw new ActionParseException("Missing operand", lexer.yyline()); + //lexer.pushback(op); + //break; } lookahead = peekLex(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java index 8d7f8ec5b..ac0236f27 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java @@ -36,7 +36,6 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -1145,13 +1144,17 @@ public class ActionScript2SimpleParser implements SimpleParser { rhs = expressionPrimary(errors, inFunction, inMethod, inTellTarget, allowRemainder, variables, true, hasEval); if (rhs == false) { lexer.pushback(op); - break; + errors.add(new SimpleParseException("Missing operand", lexer.yyline(), op.position)); + return false; } lookahead = peekLex(); while ((isBinaryOperator(lookahead) && getSymbPrecedence(lookahead) < /* > on wiki */ getSymbPrecedence(op)) || (lookahead.type.isRightAssociative() && getSymbPrecedence(lookahead) == getSymbPrecedence(op))) { rhs = expression1(errors, rhs, getSymbPrecedence(lookahead), inFunction, inMethod, inTellTarget, allowRemainder, variables, hasEval); + if (!rhs) { + break; + } lookahead = peekLex(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java index d51129dda..626ca540d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java @@ -66,15 +66,15 @@ public interface SimpleParser { for (String type : externalTypes) { externalSimpleTypes.add(type.contains(".") ? type.substring(type.lastIndexOf(".") + 1) : type); } - + Map definitionToType = new LinkedHashMap<>(); Map definitionToCallType = new LinkedHashMap<>(); Map traitFullNameToDefinition = new LinkedHashMap<>(); - + Map positionToStatic = new LinkedHashMap<>(); - findClassTraits(privateVariables, traitFullNameToDefinition,definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); + findClassTraits(privateVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); findClassTraits(sharedVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); - + parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, traitFullNameToDefinition); for (Map.Entry entry : referenceToExternalTypeIndex.entrySet()) { if (!externalTypeIndexToReference.containsKey(entry.getValue())) { @@ -83,88 +83,7 @@ public interface SimpleParser { externalTypeIndexToReference.get(entry.getValue()).add(entry.getKey()); } } - - public static void findClassTraits( - List variables, - Map traitFullNameToDefinition, - Map> definitionPosToReferences, - Map positionToStatic, - Map definitionToType, - Map definitionToCallType - ) { - for (VariableOrScope v : variables) { - if (v instanceof ClassTrait) { - ClassTrait ct = (ClassTrait) v; - definitionPosToReferences.put(ct.position, new ArrayList<>()); - positionToStatic.put(ct.position, ct.isStatic); - if (ct.type != null) { - definitionToType.put(ct.position, ct.type); - } - if (ct.callType != null) { - definitionToCallType.put(ct.position, ct.callType); - } - traitFullNameToDefinition.put(ct.getFullIdentifier(), ((ClassTrait) v).position); - } - if (v instanceof Scope) { - Scope s = (Scope) v; - findClassTraits(s.getPrivateItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); - findClassTraits(s.getSharedItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); - } - } - } - public static boolean searchTrait( - Variable v, - Map privateVarFullNameToDefinitionPosition, - Map privateVarNameToDefinitionPosition, - Map definitionToType, - Map definitionToCallType, - Map traitFullNameToDefinition, - Map> definitionPosToReferences, - Map referenceToDefinition - ) { - boolean traitFound = false; - if (v.hasParent()) { - List parts = v.getParts(); - - Integer definitionPos = null; - String firstName = parts.get(0); - if (privateVarFullNameToDefinitionPosition.containsKey(firstName)) { - definitionPos = privateVarFullNameToDefinitionPosition.get(firstName); - } else if (privateVarNameToDefinitionPosition.containsKey(firstName)) { - definitionPos = privateVarNameToDefinitionPosition.get(firstName); - } - if (definitionPos != null) { - if (definitionToType.containsKey(definitionPos)) { - String type = definitionToType.get(definitionPos); - traitFound = true; - for (int p = 1; p < parts.size(); p++) { - String part = parts.get(p); - if (part.equals("()")) { - type = definitionToCallType.get(definitionPos); - } else if (part.equals("[]")) { - type = "*"; - } else { - String traitKey = type + "/" + part; - if (!traitFullNameToDefinition.containsKey(traitKey)) { - traitFound = false; - break; - } - definitionPos = traitFullNameToDefinition.get(traitKey); - type = definitionToType.get(definitionPos); - } - } - - if (traitFound) { - definitionPosToReferences.get(definitionPos).add(v.position); - referenceToDefinition.put(v.position, definitionPos); - } - } - } - } - return traitFound; - } - public static void parseVariablesList( List privateVariables, List sharedVariables, @@ -205,7 +124,7 @@ public interface SimpleParser { } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { - + if (externalSimpleTypes.contains(v.name)) { referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); } else { @@ -294,10 +213,10 @@ public interface SimpleParser { } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { - + if (externalSimpleTypes.contains(v.name)) { referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); - } else { + } else { boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition); if (!traitFound) { parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); @@ -307,7 +226,7 @@ public interface SimpleParser { definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); definitionPosToReferences.get(-v.position - 1).add(v.position); referenceToDefinition.put(v.position, -v.position - 1); - } + } } } else { @@ -366,4 +285,85 @@ public interface SimpleParser { } } } + + public static void findClassTraits( + List variables, + Map traitFullNameToDefinition, + Map> definitionPosToReferences, + Map positionToStatic, + Map definitionToType, + Map definitionToCallType + ) { + for (VariableOrScope v : variables) { + if (v instanceof ClassTrait) { + ClassTrait ct = (ClassTrait) v; + definitionPosToReferences.put(ct.position, new ArrayList<>()); + positionToStatic.put(ct.position, ct.isStatic); + if (ct.type != null) { + definitionToType.put(ct.position, ct.type); + } + if (ct.callType != null) { + definitionToCallType.put(ct.position, ct.callType); + } + traitFullNameToDefinition.put(ct.getFullIdentifier(), ((ClassTrait) v).position); + } + if (v instanceof Scope) { + Scope s = (Scope) v; + findClassTraits(s.getPrivateItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); + findClassTraits(s.getSharedItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); + } + } + } + + public static boolean searchTrait( + Variable v, + Map privateVarFullNameToDefinitionPosition, + Map privateVarNameToDefinitionPosition, + Map definitionToType, + Map definitionToCallType, + Map traitFullNameToDefinition, + Map> definitionPosToReferences, + Map referenceToDefinition + ) { + boolean traitFound = false; + if (v.hasParent()) { + List parts = v.getParts(); + + Integer definitionPos = null; + String firstName = parts.get(0); + if (privateVarFullNameToDefinitionPosition.containsKey(firstName)) { + definitionPos = privateVarFullNameToDefinitionPosition.get(firstName); + } else if (privateVarNameToDefinitionPosition.containsKey(firstName)) { + definitionPos = privateVarNameToDefinitionPosition.get(firstName); + } + if (definitionPos != null) { + if (definitionToType.containsKey(definitionPos)) { + String type = definitionToType.get(definitionPos); + traitFound = true; + for (int p = 1; p < parts.size(); p++) { + String part = parts.get(p); + if (part.equals("()")) { + type = definitionToCallType.get(definitionPos); + } else if (part.equals("[]")) { + type = "*"; + } else { + String traitKey = type + "/" + part; + if (!traitFullNameToDefinition.containsKey(traitKey)) { + traitFound = false; + break; + } + definitionPos = traitFullNameToDefinition.get(traitKey); + type = definitionToType.get(definitionPos); + } + } + + if (traitFound) { + definitionPosToReferences.get(definitionPos).add(v.position); + referenceToDefinition.put(v.position, definitionPos); + } + } + } + } + return traitFound; + } }