作为项目的一部分,我需要写一个分析器,可以读取一个文件,并解析成事实,我可以在我的程序中使用。
文件结构如下所示:
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