如何在Prolog中实现CFG?解析代码测试不通过求助
修正Prolog上下文无关文法解析器问题
核心问题分析
- 原CFG的
Num规则存在逻辑错误,正确的多位数定义应该是Num → Digit | Num Digit(你写的Num → Digit | Num是左递归死循环,无法匹配连续数字)。 - 当前
num谓词仅实现了单个数字的匹配,无法处理输入中的多位数(比如'3','2'组成的连续数字序列)。 parse谓词的参数处理错误,没有正确接收输入列表并验证完全匹配。
修正后的完整代码
% 解析入口:接收输入列表,确保整个序列被完全解析 parse(Lst) :- lines(Lst, []). % 实现 Lines → Line ; Lines | Line lines(X, A) :- line(X, Y), semicolon(Y, Z), lines(Z, A). lines(X, Y) :- line(X, Y). % 实现 Line → Num , Line | Num line(X, A) :- num(X, Y), comma(Y, Z), line(Z, A). line(X, Y) :- num(X, Y). % 修正后的 Num 规则:匹配单个数字或连续多个数字 num(X, Y) :- digit(X, Y). num(X, Y) :- digit(X, T), num(T, Y). % 匹配分号(修正拼写错误) semicolon([';' | T], T). % 匹配逗号 comma([',' | T], T). % 匹配单个数字,用member简化代码 digit([X | T], T) :- member(X, ['0','1','2','3','4','5','6','7','8','9']).
关键修正说明
- parse谓词:改为直接接收输入列表,调用
lines(Lst, [])确保输入被完全解析到空列表,没有剩余字符。 - num谓词:恢复递归匹配逻辑,既支持单个数字,也支持连续多个数字的组合,解决多位数识别问题。
- digit谓词:用
member/2替代重复的;判断,代码更简洁易维护。 - 拼写修正:将
simecolon改为规范的semicolon,不影响功能但提升代码可读性。
测试验证
运行查询:
?- parse(['3', '2', ',', '0', ';', '1', ',', '5', '6', '7', ';', '2']).
会返回true,符合预期。
内容的提问来源于stack exchange,提问作者Yosef
相关产品推荐
相关产品推荐

