{"record":{"id":"79845c15cdc4871c","repo":"babalae/better-genshin-impact","slug":"name-79845c","errorCode":null,"errorMessage":"函数 {name} 缺少右括号","messagePattern":"函数 (.+?) 缺少右括号","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs","lineNumber":362,"sourceCode":"        }\n\n        if (tokens[pos].Type == TokenType.Identifier)\n        {\n            var name = tokens[pos].Value; pos++;\n            if (tokens[pos].Type == TokenType.LParen)\n            {\n                pos++;\n                var args = new List<AstNode>();\n                if (tokens[pos].Type != TokenType.RParen)\n                {\n                    args.Add(ParseOrExpr(tokens, ref pos));\n                    while (tokens[pos].Type == TokenType.Comma)\n                    {\n                        pos++;\n                        args.Add(ParseOrExpr(tokens, ref pos));\n                    }\n                }\n                if (tokens[pos].Type != TokenType.RParen) throw new InvalidOperationException($\"函数 {name} 缺少右括号\");\n                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","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs#L344-L380","documentation":"Thrown by ConditionEvaluator.ParsePrimary when parsing a function call (identifier followed by '(') and the arguments are consumed but no ')' follows. This is the function-call-specific variant of the missing-parenthesis error. When called via Evaluate(), this is caught internally and Evaluate returns false.","triggerScenarios":"A condition expression with a function call missing its closing ')', e.g. `since(1, true, 香菱` or `count(3, 0`. After parsing all comma-separated arguments, the parser expects ')' but finds End or another token.","commonSituations":"User writes a JSON strategy condition with a function call that is missing its closing ')'. Common when functions have multiple arguments and the user forgets the final paren, e.g. `last-exec(5, true`.","solutions":["Check the function name in the error message ({name}) to locate the problematic call.","Ensure every function call has a closing ')' after its last argument.","Review multi-argument function syntax: func(arg1, arg2, ...) must end with ')'.","Validate expressions before use with a test Evaluate call."],"exampleFix":"// before (missing closing paren on function)\n\"condition\": \"since(1 > 5\"\n\n// after\n\"condition\": \"since(1) > 5\"","handlingStrategy":"try-catch","validationCode":"// Verify all function calls in the expression are properly closed\nstatic bool AreFunctionCallsClosed(string expr)\n{\n    int depth = 0;\n    bool inFunc = false;\n    for (int i = 0; i < expr.Length; i++)\n    {\n        if (expr[i] == '(') { depth++; inFunc = true; }\n        if (expr[i] == ')') { depth--; inFunc = false; }\n        if (depth < 0) return false;\n    }\n    return depth == 0 && !inFunc;\n}","typeGuard":null,"tryCatchPattern":"// Evaluate catches this internally and returns false.\n// The warning log at line 149 includes the expression and error message,\n// so check application logs for '条件表达式求值失败' to find the problematic expression.","preventionTips":["When writing multi-argument function calls like last-exec(5, true, 香菱), always close with ')'.","The Evaluate method logs the expression and error message at warning level — check logs.","Build complex expressions incrementally, testing each function call individually.","Remember function syntax: funcname(arg1, arg2, ...) — always terminates with ')'."],"tags":["condition-evaluator","parser","expression","function-call"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}