关于Prolog tokenizer

时间:2015-03-14 00:31:43

标签: prolog lexer

我的一项任务要求我们建立一个prolog tokenizer。现在我写了一个可以改变空间并将其换成新行的谓词。但我不知道如何将其实施到主程序中。

替换部件如下所示:

replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]):- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).

Main部分有一个名为removewhite(list1 list2)

的谓词

那么如何让removewhite执行替换?

2 个答案:

答案 0 :(得分:5)

你对一个标记器有点'偏离':removewhite / 2不会给你带来任何有用的功能。相反,请考虑使用DCG(当然,如果您的Prolog提供此功能):

tokenize(String, Tokens) :- phrase(tokenize(Tokens), String).

tokenize([]) --> [].
tokenize(Tokens) --> skip_spaces, tokenize(Tokens).
tokenize([Number|Tokens]) --> number(Number), tokenize(Tokens).

skip_spaces --> code_types(white, [_|_]).
number(N) --> code_types(digit, [C|Cs]), {number_codes(N,[C|Cs])}.

code_types(Type, [C|Cs]) --> [C], {code_type(C,Type)}, !, code_types(Type, Cs).
code_types(_, []) --> [].

尽管简单,但它是一种相当高效的扫描仪,易于扩展。 在SWI-Prolog中,它具有(非ISO兼容)扩展以有效处理字符串,这可以从顶层调用,如:

?- tokenize(`123  4 567  `, L).
L = [123, 4, 567]

?- atom_codes('123  4 567  ',Cs), tokenize(Cs, L).
Cs = [49, 50, 51, 32, 32, 52, 32, 53, 54|...],
L = [123, 4, 567] 

顺便说一句,在SWI-Prolog中,数字// 1是library(dcg/basics)预定义的(当然还有更多功能)。

无论如何,关于你的问题

  

如何让removewhite执行replace?

我觉得你真的'吠叫错误的树':删除一个空间 - 实际上 分隔符 - 会搞砸你的输入...

答案 1 :(得分:1)

你可以写一个更强大的"强大的"谓词

replace_all(_, _, [], []).
replace_all(L, R, [X|T], [R|T2]):- 
    member(X, L),
    replace_all(L, R, T, T2).

replace_all(L, R, [X|T], [X|T2]) :- 
    \+ member(X, L),
    replace_all(L, R, T, T2).

然后,你将有

removewhite(List1, List2) :-
    remove_all([' ', '\t'], '\n', List1, List2).