You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Superpower中两个TextParser用Or组合解析失败的解决方案咨询

解决Superpower解析器Or组合的回溯问题

这是个典型的解析器回溯问题,我来帮你分析和解决:

问题原因

Superpower的Or运算符默认不会自动回溯输入位置。当你用identifier001.Or(identifier002)时,解析器会先尝试第一个解析器identifier001(匹配insert(...)):

  • 解析interrupt(12)时,identifier001会先匹配前两个字符"in"(和insert的前缀一致),但第三个字符是t而不是insert需要的s,此时第一个解析器失败,但输入指针已经停在了第3位,不会回到初始位置去尝试第二个解析器identifier002,所以抛出了语法错误。

解决方案

要让解析器在第一个选项失败时回溯到初始位置,尝试第二个选项,有两种简单的方式:

方式1:用Try()包装每个解析器

Try()方法会捕获解析失败的情况,并将输入指针重置到解析前的位置,这样后续的Or就能从正确的起点尝试下一个解析器:

TextParser<List<string>> combined = identifier001.Try().Or(identifier002.Try());

方式2:使用Parser.Choice()方法

Superpower提供了更简洁的Choice方法,它内部已经封装了回溯逻辑,专门用于处理多个解析器的"任一匹配"场景:

TextParser<List<string>> combined = Parser.Choice(identifier001, identifier002);

修正后的完整代码

using Superpower;
using Superpower.Parsers;
using System.Collections.Generic;
using System;

class Program
{
    static void Main()
    {
        string testInterrupt = "interrupt(12)";
        string testInsert = "insert(20,12)";
        string testDelete = "delete(18)";

        TextParser<List<string>> identifier001 = 
            from prefix in Span.EqualTo("insert")
            from open in Character.EqualTo('(')
            from num0 in Character.Numeric.Many()
            from comma1 in Character.EqualTo(',')
            from num1 in Character.Numeric.Many()
            from close in Character.EqualTo(')')
            select new List<string> { prefix.ToStringValue(), string.Join("", num0), string.Join("", num1) };

        TextParser<List<string>> identifier002 = 
            from prefix in Span.EqualTo("interrupt")
            from open in Character.EqualTo('(')
            from num0 in Character.Numeric.Many()
            from close in Character.EqualTo(')')
            select new List<string> { prefix.ToStringValue(), string.Join("", num0) };

        // 使用Choice方法组合解析器
        TextParser<List<string>> combined = Parser.Choice(identifier001, identifier002);

        // 测试interrupt(12)
        try
        {
            var res = combined.Parse(testInterrupt);
            Console.WriteLine("解析interrupt(12)结果:");
            foreach (var item in res)
            {
                Console.WriteLine(item);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"解析interrupt(12)失败: {ex.Message}");
        }

        // 测试insert(20,12)
        try
        {
            var res = combined.Parse(testInsert);
            Console.WriteLine("\n解析insert(20,12)结果:");
            foreach (var item in res)
            {
                Console.WriteLine(item);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"解析insert(20,12)失败: {ex.Message}");
        }

        // 测试delete(18)(应该失败)
        try
        {
            var res = combined.Parse(testDelete);
            Console.WriteLine("\n解析delete(18)结果:");
            foreach (var item in res)
            {
                Console.WriteLine(item);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"\n解析delete(18)失败(符合预期): {ex.Message}");
        }
    }
}

运行结果

  • interrupt(12)会输出:
    interrupt
    12
    
  • insert(20,12)会输出:
    insert
    20
    12
    
  • delete(18)会抛出错误,符合你的需求。

内容的提问来源于stack exchange,提问作者cppxaxa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:42:59