我想写一个可以处理记事本中显示的文本的DCG。 我已经阅读了一些关于编写DCG的在线教程,但其中没有一篇文章是免费的文本,涉及字符串,日期和整数。我真的不确定如何开始编写DCG(如何表示一条线甚至一个日期)。 有什么帮助吗?
答案 0 :(得分:2)
'技巧'是以声明的方式处理问题,给出第一个更具选择性的模式。您的数据格式具有明显定义的柱状结构,并且可以使用库(dcg / basics)来处理:
:- [library(dcg/basics)].
row([Date,Key|Numerics]) -->
date(Date), separe, key(Key), separe, numeric_pairs(Numerics).
date(D/M/Y) -->
integer(D), "/", integer(M), "/", integer(Y).
key([F|Ks]) -->
[F], {F \= 0' }, string(Ks).
numeric_pairs([Num:Perc|NPs]) -->
integer(Num), separe, number(Perc), "%", whites, !, numeric_pairs(NPs).
numeric_pairs([]) --> [].
separe --> white, whites.
试验:
?- atom_codes('02/18/2014 BATS Z 235122734 6.90% 109183482 10.50% 147587409 7.80%', Cs), phrase(row(R), Cs).
Cs = [48, 50, 47, 49, 56, 47, 50, 48, 49|...],
R = [2/18/2014, [66, 65, 84, 83, 32, 90], 235122734:6.9, 109183482:10.5, 147587409:7.8]
我必须说调试不是很容易。当Prolog回溯你没有任何关于出了什么问题的提示时......我猜应该有一条专门的痕迹...
要提供DCG,请参阅库(pure_input),或者 - 更容易调试 - 使用read_line_to_codes / 2
按时获取一行编辑也许我的点击使用read_line_to_codes / 2是一个糟糕的。
以下是对测试数据的完整扫描,使用phrase_from_file / 2以及随后选择的相应列和总和(参数所需的列)。
:- [library(dcg/basics)].
:- [library(pure_input)].
test(ColToSum, Tot) :-
phrase_from_file(row(Rows), '/tmp/test.txt'),
maplist(get_col(ColToSum), Rows, Cols),
sum_list(Cols, Tot).
get_col(ColToSum, Row, Col) :-
nth1(ColToSum, Row, Col:_).
row([[Date,Key|Numerics]|Rows]) -->
date(Date), separe, key(Key), separe, numeric_pairs(Numerics), "\n",
row(Rows).
row(Rows) -->
string(_), "\n",
row(Rows).
row([]) --> [].
date(D/M/Y) -->
integer(D), "/", integer(M), "/", integer(Y).
key([F|Ks]) -->
[F], {F \= 0' }, string(Ks).
numeric_pairs([Num:Perc|NPs]) -->
integer(Num), separe, number(Perc), "%", whites, !, numeric_pairs(NPs).
numeric_pairs([]) --> [].
separe --> white, whites.
产生
?- test(3,X).
X = 561877153
如果您使用的是Windows,请使用“\ r \ n”作为行终止符...
HTH