{"record":{"id":"83169962f6882e1b","repo":"babalae/better-genshin-impact","slug":"token-tokens-pos-value","errorCode":null,"errorMessage":"意外的 token：{tokens[pos].Value}","messagePattern":"意外的 token：(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs","lineNumber":381,"sourceCode":"                pos++;\n                return new FuncCallNode(name, args);\n            }\n            return new FuncCallNode(name, []);\n        }\n\n        if (tokens[pos].Type == TokenType.Number)\n        {\n            var val = double.Parse(tokens[pos].Value, CultureInfo.InvariantCulture); pos++;\n            return new NumberNode(val);\n        }\n\n        if (tokens[pos].Type == TokenType.Bool)\n        {\n            var val = tokens[pos].Value == \"true\"; pos++;\n            return new BoolNode(val);\n        }\n\n        throw new InvalidOperationException($\"意外的 token：{tokens[pos].Value}\");\n    }\n\n    // ========== AST 求值（统一返回 object: double 或 bool） ==========\n\n    /// <summary>求值 AST 节点</summary>\n    private object Eval(AstNode node, int currentIndex)\n    {\n        return node switch\n        {\n            BoolNode b => b.Value,\n            NumberNode n => n.Value,\n            UnaryOpNode u => EvalUnary(u, currentIndex),\n            BinaryOpNode b => EvalBinary(b, currentIndex),\n            FuncCallNode f => EvalFunc(f.Name, f.Args, currentIndex),\n            _ => false\n        };\n    }\n","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs#L363-L399","documentation":"Thrown by ConditionEvaluator.ParsePrimary as a catch-all when the token at the current parse position is none of: LParen, Identifier, Number, or Bool. This means the grammar encountered a token where a primary expression (value or sub-expression) was expected but got an operator or comma instead. When called via Evaluate(), this is caught internally and Evaluate returns false.","triggerScenarios":"A malformed condition expression where an operator appears where a value is expected. For example: `&& q-ready()` (starts with operator), `q-ready(,)` (empty argument position), or `since()` followed immediately by a comma with no value. Also triggered by consecutive operators like `q-ready() && || low-hp()`.","commonSituations":"User writes a condition with a misplaced operator, empty argument, or dangling comma in a function call. Often from partial editing or incorrect copy-paste of expression fragments.","solutions":["Inspect the token value in the error message to identify what was unexpected.","Ensure each operand position has a valid primary expression (identifier, number, bool, function call, or parenthesized group).","Remove double operators or misplaced commas.","Test the expression in isolation with logging enabled to trace the parse."],"exampleFix":"// before (dangling operator)\n\"condition\": \"&& q-ready()\"\n\n// after\n\"condition\": \"q-ready()\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Evaluate catches this internally (line 147-151) and returns false.\n// To detect when a condition silently fails, wrap Evaluate with logging:\nbool result;\ntry\n{\n    result = evaluator.Evaluate(expr, idx, name, action);\n}\ncatch\n{\n    result = false; // Evaluate itself shouldn't throw, but be safe\n}\nLogger.LogDebug(\"条件 {Expr} => {Result}\", expr, result);","preventionTips":["The Evaluate method handles this gracefully by returning false — no crash occurs.","When a condition always evaluates false unexpectedly, review the expression for misplaced operators.","Avoid starting expressions with operators (&&, ||) or placing operators in argument positions.","Ensure function arguments are non-empty expressions between commas."],"tags":["condition-evaluator","parser","expression","syntax"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}