Prolog - 带有文件输入的DCG解析器

Flo*_*ndt 8 parsing prolog swi-prolog dcg

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

文件结构如下所示:

property = { el1 , el2 , ... }.  
Run Code Online (Sandbox Code Playgroud)

我最终想要的是:

property(el1).
property(el2).
...
Run Code Online (Sandbox Code Playgroud)

我这样读了我的文件:

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).
Run Code Online (Sandbox Code Playgroud)

现在我已经阅读了几本书和网上关于DCG的内容,但他们都解释了相同的简单例子,你可以生成句子,如"猫吃蝙蝠"等......当我想用它来做上面的例子时我惨遭失败.

我所做的是"解析"下面的行:

property = el1.
Run Code Online (Sandbox Code Playgroud)

property(el1).
Run Code Online (Sandbox Code Playgroud)

有了这个:

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] }.
Run Code Online (Sandbox Code Playgroud)

我甚至不知道我是否在这里以正确的方式使用dcg,所以任何对此的帮助都将不胜感激.现在我遇到的问题是,如何使用列表中的多个元素执行此操作,以及如何处理"{"和"}".
我真正想要的是一个可以处理这些类型的句子(超过2个元素)的dcg:句子分裂

现在我知道这里的很多人在涉及到dcgs时都会参考图书馆dcg_basics和pio.但是,我还有一个问题,当我尝试使用该库时,我收到错误:

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)]
Run Code Online (Sandbox Code Playgroud)

当我这样做:

:- [library(http/dcg_basics)].
Run Code Online (Sandbox Code Playgroud)

附加信息:

任何有关这方面的帮助将不胜感激!

编辑:这个问题的目的是了解更多关于DCG及其在解析器中的使用.

Cap*_*liC 9

只要你的文件是普通的Prolog语法,你就建议使用Prolog术语IO.只需一次调用即可读取完整结构化的术语.使用DCG其方式更加复杂,有点低效率的(不知道这里,应该测量,但读(期限)调用用C语言实现Prolog的解析器...)看到这个其他的问题,即使用同样的格式(至少,你可以检查一下其他人是否在这里得到了关于同一作业的答案...)

评论后编辑 ......

你是对的,DCG是处理Prolog中一般解析的正确方法.DCG产品中的参数可以被视为语义属性,因此编程DCG可以被视为对输入提供工作语义分析(参见属性语法,一种重要的技术 - 也是语言工程).

事实上,所提出的示例可以很好地解决,而不需要术语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([]) --> [].
Run Code Online (Sandbox Code Playgroud)

有了这个,我们有

?- phrase(property(P), "my props = {1,2,3}").
P = property(1, 2, 3).
Run Code Online (Sandbox Code Playgroud)

感谢库(pureio),我们可以将语义编程应用于Prolog流,并获得与/ 2相同的行为奖励.

更多

这个其他答案显示了实现具有操作员分辨率和延迟评估的表达式计算器的实用方法.