{"record":{"id":"1cb337edc1f5ed9a","repo":"antlr/antlr4","slug":"tag-delimiters-out-of-order-in-pattern-pattern-1cb337","errorCode":null,"errorMessage":"tag delimiters out of order in pattern: {pattern}","messagePattern":"tag delimiters out of order in pattern: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs","lineNumber":645,"sourceCode":"                }\n            }\n            //\t\tSystem.out.println(\"\");\n            //\t\tSystem.out.println(starts);\n            //\t\tSystem.out.println(stops);\n            if (starts.Count > stops.Count)\n            {\n                throw new ArgumentException(\"unterminated tag in pattern: \" + pattern);\n            }\n            if (starts.Count < stops.Count)\n            {\n                throw new ArgumentException(\"missing start tag in pattern: \" + pattern);\n            }\n            int ntags = starts.Count;\n            for (int i = 0; i < ntags; i++)\n            {\n                if (starts[i] >= stops[i])\n                {\n                    throw new ArgumentException(\"tag delimiters out of order in pattern: \" + pattern);\n                }\n            }\n            // collect into chunks now\n            if (ntags == 0)\n            {\n                string text = Sharpen.Runtime.Substring(pattern, 0, n);\n                chunks.Add(new TextChunk(text));\n            }\n            if (ntags > 0 && starts[0] > 0)\n            {\n                // copy text up to first tag into chunks\n                string text = Sharpen.Runtime.Substring(pattern, 0, starts[0]);\n                chunks.Add(new TextChunk(text));\n            }\n            for (int i_1 = 0; i_1 < ntags; i_1++)\n            {\n                // copy inside of <tag>\n                string tag = Sharpen.Runtime.Substring(pattern, starts[i_1] + start.Length, stops[i_1]);","sourceCodeStart":627,"sourceCodeEnd":663,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs#L627-L663","documentation":"While splitting a pattern, the i-th start delimiter position is not before the i-th stop delimiter position (starts[i] >= stops[i]). This happens with interleaved delimiters such as '<a><b>' where scanning pairs them out of order relative to the collected indexes, or when a stop appears before its start in the string. The pattern's tag structure is malformed.","triggerScenarios":"Patterns with crossed or nested-looking delimiters (e.g. \"><\", \"<a> ><\") where the k-th stop occurs at or before the k-th start; malformed concatenation producing delimiter sequences like '>...<'.","commonSituations":"Programmatic pattern assembly that concatenates fragments each carrying their own delimiters in the wrong order; hand-editing patterns and swapping halves; escaped delimiters making the effective order cross.","solutions":["Rewrite the pattern so each '<' immediately precedes its matching '>' with no crossing pairs.","Log the compiled starts/stops index lists (temporarily instrument the Chunkify/split path or count delimiters yourself) to see which pair is inverted.","Build patterns from small validated fragments ('text', '<tag>') joined in order instead of raw string surgery."],"exampleFix":"// before\nstring pattern = fragA + \"><\" + fragB; // crossed delimiters\nvar p = parser.CompileParseTreePattern(pattern, RULE_r, null);\n\n// after\nstring pattern = fragA + \"<\" + tag + \">\" + fragB; // well-formed tag","handlingStrategy":"validation","validationCode":"// Verify each start precedes its paired stop before compiling\nvar starts = IndexesOfUnescaped(pattern, '<'); var stops = IndexesOfUnescaped(pattern, '>');\nif (starts.Count == stops.Count)\n    for (int i = 0; i < starts.Count; i++)\n        if (starts[i] >= stops[i]) throw new ArgumentException($\"tag delimiters crossed at {starts[i]}\");","typeGuard":null,"tryCatchPattern":"try { matcher.Compile(pattern); } catch (ArgumentException ex) when (ex.Message.Contains(\"out of order\")) { /* rebuild the pattern from validated fragments */ }","preventionTips":["Assemble patterns from small validated fragments instead of raw concatenation.","Test pattern builders with unit tests asserting well-formed delimiter pairs."],"tags":["antlr","csharp","pattern","delimiters","malformed"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}