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

如何用Prolog基础DCG实现正则式风格的子串捕获并生成字符串?

需求:给Prolog基础DCG添加正则式风格的子串捕获功能

正则表达式可轻松捕获子串,比如字符串"Jaco was an American bassist"匹配PCRE2语法的正则表达式:

(?sm)^([Jj]aco).+(was|is).+?(American|famous).+(dancer|bassist|singer|programmer|dueller)

能捕获到Jaco、was、American、bassist这几个子串。

现有一个DCG可以匹配该字符串,还能生成所有可能的字符串变体,但无法捕获指定子串:

jaco_bassist --> ("J" ; "j"), "aco", space, ("was" ; "is"), space, ("a" ; "an"), space,
                   ("American" ; "famous"), space,
                   ("dancer" ; "bassist" ; "singer" ; "programmer" ; "dueller").
space --> " ".

需要基于Prolog基础DCG(如B-Prolog支持的)实现和正则表达式一致的子串捕获功能,同时保留生成所有可能字符串的能力。用member/2枚举选项的方法在简单场景下可行,但面对复杂结构(比如有48种拼写变体的姓氏kjellerstrand)就存在局限:

kjellerstrand --> "k", ("je" ; "ä"), "ll", ("" ; "er" ; "ar"), 
                  ("st" ; "b"), ("" ; "r"), "a", (""; "n"), "d".

实现方案

1. 核心思路:给DCG添加捕获参数

利用DCG的额外参数传递捕获结果,封装专门的capture/2规则,既保留原有匹配/生成逻辑,又能提取目标子串。

% 捕获规则:匹配目标规则Goal,将匹配到的字符串联成Capture原子
capture(Goal, Capture) -->
    call_dcg(Goal, Chars),
    { atom_chars(Capture, Chars) }.

% 适配B-Prolog的DCG调用逻辑,将规则转换为字符列表
call_dcg(Goal, Chars) -->
    Goal,
    { phrase(Goal, Chars) }.

% 改造后的jaco_bassist,返回4个捕获项
jaco_bassist(C1, C2, C3, C4) -->
    capture(("J" ; "j") ++ "aco", C1),  % 捕获名字部分
    space,
    capture(("was" ; "is"), C2),        % 捕获系动词
    space,
    ("a" ; "an"), space,
    capture(("American" ; "famous"), C3), % 捕获形容词
    space,
    capture(("dancer" ; "bassist" ; "singer" ; "programmer" ; "dueller"), C4). % 捕获职业

space --> " ".

2. 处理复杂分支结构(如kjellerstrand)

无需拆解原有复杂规则,直接用capture/2包装即可自动捕获所有拼写变体:

% 捕获kjellerstrand的所有拼写形式
capture_kjellerstrand(Capture) -->
    capture(kjellerstrand, Capture).

% 保留原有复杂规则不变
kjellerstrand --> "k", ("je" ; "ä"), "ll", ("" ; "er" ; "ar"), 
                  ("st" ; "b"), ("" ; "r"), "a", (""; "n"), "d".

3. 功能验证

  • 匹配与捕获:输入字符串时,直接返回对应捕获项:
    ?- phrase(jaco_bassist(C1,C2,C3,C4), "Jaco was an American bassist").
    C1 = "Jaco", C2 = "was", C3 = "American", C4 = "bassist".
    
  • 生成所有变体:枚举所有可能的字符串组合,同时得到对应捕获项:
    ?- phrase(jaco_bassist(C1,C2,C3,C4), String), atom_chars(Str, String).
    % 输出示例:
    Str = "Jaco was a famous dancer", C1 = "Jaco", C2 = "was", C3 = "famous", C4 = "dancer" ;
    Str = "jaco is an American bassist", C1 = "jaco", C2 = "is", C3 = "American", C4 = "bassist" ;
    % ... 所有其他组合变体
    

方案优势

  • 完全基于基础DCG语法,适配B-Prolog环境;
  • 保留DCG原生的生成能力,不会因添加捕获功能丢失枚举变体特性;
  • 对复杂分支结构友好,无需修改原有规则逻辑,仅需包装capture规则即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:10:34