2013-01-16 19 views
3

我在Prolog中编写了解析器。我还没有完成。它是代码的一部分。下一步是杀死字符串中的所有空白。在Prolog中删除字符串中的空格

parse(Source, Tree) :- kill_whitespace(Source, CleanInput), % remove whitespaces 
         actual_parse(CleanInput, Tree). 

actual_parse(CleanInput, Tree):- phrase(expr(Tree),CleanInput). 

expr(Ast) --> term(Ast1), expr_(Ast1,Ast). 
expr_(Acc,Ast) --> " + ", !, term(Ast2), expr_(plus(Acc,Ast2), Ast). 
expr_(Acc,Ast) --> " - ", !, term(Ast2), expr_(minus(Acc,Ast2), Ast). 
expr_(Acc,Acc) --> []. 

term(Ast) --> factor(Ast1), term_(Ast1,Ast). 
term_(Acc,Ast) --> " * ", !, factor(Ast2), term_(mul(Acc,Ast2),Ast). 
term_(Acc,Ast) --> " ** ", !, factor(Ast2), term_(pol(Acc,Ast2),Ast). 
term_(Acc,Acc) --> []. 

factor(Ast) --> "(", !, expr(Ast), ")". 
factor(D)--> [X], { X >= 48 , X=<57 , D is X-48 }. 
factor(id(N,E)) --> "x", factor(N), ":=", expr(E), ";". 

例如:

?- parse("x2:=4",T). 
    T = id(2, 4) 

真!但是,当我写:

?- parse("x2 := 4",T). 
false. 

它必须是真实的,以及它应该是一个过滤器:kill_whitespace(Source, CleanInput)

不同的解决方案效率低下。 我该怎么做?

回答

1

我通常放置一个“跳过”非终端在那里可以发生空间。这样的跳过通常会丢弃评论以及任何其他“无趣”文本。

为了保持尽可能简单地:

% discard any number of spaces 
s --> "" ; " ", s. 

我喜欢短的名字,以保持语法干净。要放弃新行等。还有:

s --> "" ; (" ";"\t";"\n";"\r"), s. 

A '风格' 注:不是

parse(Source, Tree) :- 
    expr(Tree, Source, []). 

你可以考虑

parse(Source, Tree) :- 
    phrase(expr(Tree), Source). 
1

好吧,简单的方法是解析字符串并删除空白/只保留non-whispace filter predicate。但是这需要第二次解析。

一种其他的方式来解决它是用自己的谓语“得”字,
foo --> "a".变得foo --> get("a").其中get//1是一样的东西:

get(X) --> [X]. 
get(X) --> whitespace, get(X). 
+0

过滤器很难*保留*所需空间,如内部字符串。而且还可能有空间需要分离令牌的地方。为真,最后的情况既不是从我提出的跳跃谓词中处理的...... – CapelliC

+0

@CapelliC确实。最好标记输入并处理所有的空白/字符串/等问题,然后解析它。 –

0

编写解析器的通常的方法是分两个阶段写:

第一阶段进行词法分析并产生令牌的流。在这一点上,对解析不重要的空白和其他“令牌”(例如评论)被丢弃。

第二阶段进行解析本身,检查由词法分析器产生的标记列表。