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

如何避免Prolog DCG解析数字网格时产生额外结果?

DCG解析数字网格时避免末尾空列表的解决方法

问题场景

使用SWI-Prolog的library(dcg/basic)编写DCG,将数字网格解析为行列表(每行是数字列表),原代码如下:

input([]) --> eos.
input([Line|Lines]) -->
    line(Line),
    input(Lines).

line([]) --> eol.
line([Num|Nums]) -->
    whites,
    number(Num),
    line(Nums).

运行时发现解析结果末尾会追加额外的空列表,根源是eol(换行)和eos(输入结束)都能匹配输入末尾,导致最后一行被额外解析出空行。

通用解决思路

核心是明确行的定义:行要么是「非空数字列表 + 换行符」(中间行),要么是「非空数字列表 + 输入结束」(最后一行),禁止匹配无意义的空行。具体可以通过两种方式实现:


方案1:调整line规则,只匹配非空行并兼容换行/输入结束

先定义匹配非空数字序列的辅助规则,再让line规则明确匹配「非空数字序列 + 换行/输入结束」:

% 匹配非空的数字列表
numbers([Num|Nums]) -->
    whites,
    number(Num),
    rest_numbers(Nums).

% 匹配后续的数字(可以为空)
rest_numbers([]) --> [].
rest_numbers([Num|Nums]) -->
    whites,
    number(Num),
    rest_numbers(Nums).

% 匹配一行:非空数字列表 + 换行 或 输入结束
line(Line) -->
    numbers(Line),
    (eol ; eos).

% 输入解析规则:若干行 + 输入结束
input([]) --> eos.
input([Line|Lines]) -->
    line(Line),
    input(Lines).

方案2:拆分input规则,区分中间行和最后一行

直接在input规则里明确:中间行必须带换行,最后一行直接结束于输入末尾,同时确保所有行都是非空的:

% 匹配非空数字列表
line([Num|Nums]) -->
    whites,
    number(Num),
    rest_numbers(Nums).

rest_numbers([]) --> [].
rest_numbers([Num|Nums]) -->
    whites,
    number(Num),
    rest_numbers(Nums).

% 最后一行:非空行 + 输入结束
input([Line]) --> line(Line), eos.
% 中间行:非空行 + 换行 + 剩余输入
input([Line|Lines]) --> line(Line), eol, input(Lines).

关键说明

两种方案都通过禁止空行匹配解决了末尾空列表的问题:

  • 方案1更灵活,兼容输入末尾有无换行的情况;
  • 方案2逻辑更直观,明确区分中间行和最后一行的终止条件。

不需要直接操作差异列表,通过调整DCG规则的匹配条件即可解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 03:58:08