Prolog - DCG parser with input from file

2019-08-04 15:42发布

作为项目的一部分,我需要写一个分析器,可以读取一个文件,并解析成事实,我可以在我的程序中使用。

文件结构如下所示:

property = { el1 , el2 , ... }.  

我想到底是:

property(el1).
property(el2).
...

我读我的文件是这样的:

main :-
       open('myFile.txt', read, Str),
       read_file(Str,Lines),
       close(Str),
       write(Lines), nl.

read_file(Stream,[]) :-
                       at_end_of_stream(Stream).

read_file(Stream,[X|L]) :-
                          \+ at_end_of_stream(Stream),
                          read(Stream,X),
                          parse(X),            % Here I call upon my parser.
                          read_file(Stream,L).

现在,我已经阅读一些书籍和网上有关DCG,但它们都解释同样简单的例子,其中像“猫吃蝙蝠”等就可以生成句子...当我想用它上面的例子我惨遭失败。

我没有管理是“解析”的下面一行:

property = el1.

property(el1).

有了这个:

parse(X) :-
           X =.. List,    % Reason I do this is because X is one atom and not a list.
           phrase(sentence(Statement), List),
           asserta(Statement).

sentence(Statement) --> ['=', Gender, Person] , { Statement =.. [Gender, Person] }.

我甚至不知道如果我使用的DCG在这里以正确的方式,所以任何的帮助在此将不胜感激。 现在我遇到的问题是,如何与多个元素在我的名单这样做,以及如何处理“{”和“}”。
我真正想要的是能处理这些类型的语句(超过2元)一DCG:

现在我知道了身边很多人在这里指的是库dcg_basics和PIO当谈到DCGS。 不过,我有另外一个问题,当我尝试使用库我收到错误:

ERROR: (c:/users/ldevriendt/documents/prolog/file3.pl:3):
      Type error: `text' expected, found `http/dcg_basics'
Warning: (c:/users/ldevriendt/documents/prolog/file3.pl:3):
      Goal (directive) failed: user:[library(http/dcg_basics)]

当我这样做:

:- [library(http/dcg_basics)].

附加信息:

  • 我使用的程序: SWI-Prolog的编辑器在Windows环境。

任何帮助,将不胜感激!

编辑:这样做的目的是问题是更多地了解DCG及其在解析器使用。

Answer 1:

只要你的文件是普通的Prolog语法,我们建议你使用Prolog项IO。 完全结构化术语读取单个呼叫。 使用DCG其方式更加复杂,有点低效率的(不知道这里,应该测量,但读(期限)调用用C语言实现Prolog的解析器...)看到这个其他的问题 ,即使用同样的格式(至少,你可以检查是否存在其他人的SO得到的回答是为贵公司相同的分配......)

评论后编辑 ...

你说得对,DCG是处理一般解析Prolog中的正确途径。 在DCG制作参数可以被看作是语义属性,因此编程DCG可以看作是在输入端提供工作语义分析(参见属性语法 ,在语言工程的一个重要技术-also-)。

事实上呈现的例子可以非常顺利地进行,而不与长期IO所需的黑客解决。

这里是:

:- use_module(library(pio)).  % autoload(ed), added just for easy browsing
:- use_module(library(dcg/basics)).

property(P) -->
    b, "my props", b, "=", b, "{", elS(Es) , b, "}", b,
    { P =.. [property|Es] }.

elS([E|Es]) --> el(E), b, ("," -> elS(Es) ; {Es = []}).
el(N) --> number(N).
el(S) --> csym(S). % after Jeremy Knees comment...
b --> blanks.

%   parse a C symbol
csym(S) -->
    [F], { code_type(F, csymf) },
    csym1(Cs),
    !, { atom_codes(S, [F|Cs]) }.

csym1([C|Cs]) -->
    [C], { code_type(C, csym) },
    csym1(Cs).
csym1([]) --> [].

这样,我们有

?- phrase(property(P), "my props = {1,2,3}").
P = property(1, 2, 3).

由于库( pureio )我们可以应用语义编程Prolog的数据流,并予以奖励短语/ 2的相同行为。

更多

这对方的回答显示出实现与运营商的分辨率,和懒惰评估一个表达式计算器的实用方法。



Answer 2:

好了,家庭作业问题的目的是学习。 用DCG做它会教你比胡闹运营商更多一般有用的技能。

我觉得你的问题是不太与DCG的天生就比用字符串处理。

你有一堆的,你用大学(该= ..运算符)以列表和字符串之间进行转换的地方。 大学可能不是你想要的这里。 大学统一与列表的术语。

foo(bar, baz)  =..  [foo, bar, baz]

你需要了解的是,在Prolog的字符串可以在几种不同形式的字符串“喜弗洛雷斯”可能是

“喜弗洛雷斯” - 这是一个原子 - 的事情“固体块”。 不需要对一些字符序列(见你的书)的单引号,所以hi_flores是没有单引号一个完美的原子。

[104,105,32,70,108,111,114,101,115] - a list of ASCII codes.  This is likely what you want. These can be written with double quotes, "hi Floris"  in prolog code.

To save your sanity, put

:- portray_text(true).  

在文件中,以便它打印出“喜弗洛里斯”在调试,而不是一串数字。

还有一个字符数的列表

[H,I, '', 'F',L,O,R,I,S]

但你可能不希望这些。

您可能会发现SICSTUS兼容性预解码read_line有用。

如今,在DCG,你有时要匹配“文字” - 从字面上那个东西。 如果是这样,把在列表中。 这里有一个DCG因为如果在一些隐约VBish语言语句

if_statement  --> "if", wh, "(", condition, ")", wh, 
                  "then", wh, body, wh, "else", wh,
                  else_body, wh, "endif".

% whitespace
wh -->  [].
wh -->  " ", wh.
wh --> [10], wh.   % handle newline and cr
wh --> [12], wh.

在WH的到处都是可选的空白。

现在,对于整体战略,你可以在一行一次读,或在整个文件中读取。 对于一条线,用read_line,返回代码列表。 read_file_to_codes会得到整个文件。

如果您使用的整个文件的策略,和换行符是显著,你需要从空白的定义中删除它们,效果显着。

而且,当然,这一切都导致了为什么对这个问题的问题是注满,这样,而不是教师的盒子的问题。



Answer 3:

我解析字符串到一个列表,然后控制列表。 使用DCG你可以转换

T = (saf>{saf, as13s}>a32s>asf).

S = [saf-0, saf-1, as13s-1, a32s-2, asf-3] .

注意做到:

1. parseLine(<<Yourpattern>>,Position) --> parseLine(L,Position), parseLine(R,NewPosition)
2. parseLine(Item,Pos) --> [Item-Pos].

这里有2种模式来处理这些是(L> R)和{L,R}。 这不会有太大的复杂,非常容易阅读。



Answer 4:

恕我直言,DCG语法规则是在符号化相当难看,真应该DCG从未甚至提出该任务的事情; 实打实的与DCG是解析令牌,因为Prolog使用符号处理,所以我可以说,最好的选择是建立一个外来呼叫到,例如c标记者将与令牌的普通列表统一,然后让DCG做什么它一直尽管对于。 通过这种方式,实现清洁,你不必担心解析CR,空格...

假设你有哪些具有如下所示的语句中的假想语言:

object:
       object in a yields b,
       object in b yields C.

我不希望即使在DCG标记化而这个想象; 我懒得去学习如何使用还没有被设计用于这种任务的工具这样做。 更好的办法是有一个外国调用一个谓词,将我提供的令牌的普通列表。

 tokenize(A,ListOfTokens), phrase(yourDGCstartRule(Information), ListOfTokens, _).

我们的运行示例中的列表将简单地看作为:

ListOfTokens = [object,:,object,in,a,yields,b,',',object,in,b,yields,c].

我认为这是方式更优雅和你的规则相应映射。 我可能是错于思绪但最终这是一个品味的问题,以及矿山,DCG是不是一个标记,除非被严格要求我永远不会使用它为。 Admitedly我能发现一些应用中,它将使意义也用它作为分词器,但仍认为我的任务要分开。

请注意,我不是说序言不具有良好的设施,你总是可以做的序言标化,但你应该只用符号和其他一些stricly需要的字符或字符串(如大写字符串分隔任务,让DCG处理,像适当的名称或其它字符)。

最后,在我看来,人们可能已经忘记了符号化和分析是两个分离的任务; 更多的序言,因为令牌符号是什么序言擅长和解析令牌/什么DCG越办越好,争取embeeded语义接口序言这是可取的方案符号(而不是字符)。



文章来源: Prolog - DCG parser with input from file