2015-07-11 28 views
4

我似乎一直在努力编写DCG来解析输入文件。但它似乎应该很简单?是否有任何提示或技巧来思考这个问题?创建文件输入dcg的一般模式是什么?

对于一个具体的例子,可以说我想解析一个fasta文件。 (https://en.wikipedia.org/wiki/FASTA_format)。我想阅读每个描述和每个序列的后面跟踪。

:- use_module(library(pio)). 
:- use_module(library(dcg/basics)). 
:- portray_text(true). 
:- set_prolog_flag(double_quotes, codes). 
:- set_prolog_flag(back_quotes,string). 

fasta_file([]) -->[]. 
fasta_file([Section|Sections]) --> 
    fasta_section(Section), 
    fasta_file(Sections). 


fasta_section(Section) --> 
    fasta_description(Description), 
    fasta_seq(Sequence), 
    {Section =.. [section,Description,Sequence]}. 

fasta_description(Description) --> 
    ">", 
    string(Description), 
    {no_gt(Description), 
    no_nl(Description)}. 


fasta_seq([]) --> []. 
fasta_seq(Seq) --> 
    nt([S]), 
    fasta_seq(Ss), 
    {S="X"->Seq =Ss;Seq=[S|Ss]}. 

nt("A") --> "A". 
nt("C") --> "C". 
nt("G") --> "G". 
nt("T") --> "T". 
nt("X") --> "\n". 

no_gt([]). 
no_gt([E|Es]):- 
    dif([E],">"), 
    no_gt(Es). 

no_nl([]). 
no_nl([E|Es]):- 
    dif([E],"\n"), 
    no_nl(Es). 

现在这显然是错误的。我想该行为是

?-phrase(fasta_section(S),">frog\nACGGGGTACG\n>duck\nACGTTAG"). 
S = section("frog","ACGGGGTACG"); 
S = section("duck","ACGTTAG"); 
false. 

但是,如果我做了phrase(fasta_file(Sections),">frog\nACGGGGTACG\n>duck\nACGTTAG).科统一使用节/ 2秒的列表,这是我想要的,但我现在的代码似乎相当hacky-我是如何处理的换行符例如。

+0

错字:'S =“X” - >'应该读取'[S] =“X” - >' – false

+0

[This answer] (HTTP://计算器。com/a/12942551/772868)将会对你感兴趣。 – false

+1

用{{Section = section(Description,Sequence)}替换'{Section = .. [section,Description,Sequence]}'' – false

回答

0

肯定,有“小”打字的问题:

nt("A") -->"A", 
nt("C") -->"C", 
nt("G") -->"G", 
nt("T") -->"T". 

应该

nt("A") -->"A". 
nt("C") -->"C". 
nt("G") -->"G". 
nt("T") -->"T". 

反正,我也有过调试DCG我的问题,我写了一个解析器Prolog的一个加载MySQL转储(真正的SQL,真的),并且当发现意想不到的东西时,例如转义字符串或UTF8(?)奇怪的编码,它是一种痛苦。

我会建议使用短语/ 3,看看是否有一个不可分开的尾巴。此外,可以帮助在已知的,表现良好的序列之后放置一些调试输出。

当然,我假设您已经尝试使用SWI-Prolog调试器。

此外,提防

... 
dif([E],">"), 
... 

你设置一下双引号相应的标志吗?在DCG机构,重写机械照顾匹配的,但默认情况下一个在SWI-Prolog的代码序列不匹配双引号中的字符串...

编辑

我认为这将不解决有关总体战略的怀疑......无论如何,这是我将如何处理这个问题?

fasta_file([]) -->[]. 
fasta_file([Section|Sections]) --> 
    fasta_section(Section), 
    fasta_file(Sections). 

fasta_section(section(Description,Sequence)) --> 
    fasta_description(Description), 
    fasta_seq(SequenceCs), {atom_codes(Sequence, SequenceCs)}, !. 

fasta_description(Description) --> 
    ">", string(DescriptionCs), "\n", {atom_codes(Description, DescriptionCs)}. 

fasta_seq([S|Seq]) --> nt(S), fasta_seq(Seq). 
fasta_seq([]) --> "\n" ; []. % optional \n at EOF 

nt(0'A) --> "A". 
nt(0'C) --> "C". 
nt(0'G) --> "G". 
nt(0'T) --> "T". 

现在

?- phrase(fasta_file(S), `>frog\nACGGGGTACG\n>duck\nACGTTAG`). 
S = [section(frog, 'ACGGGGTACG'), section(duck, 'ACGTTAG')] ; 
false. 

注意:fasta_seq // 1子句的顺序很重要,因为它实现了'渴望'解析 - 主要是为了提高效率。正如我所说的,我不得不解析SQL,几个MB是常见的。

编辑

?- phrase((string(_),fasta_section(S)), `>frog\nACGGGGTACG\n>duck\nACGTTAG`,_). 
S = section(frog, 'ACGGGGTACG') ; 
S = section(duck, 'ACGTTAG') ; 
false. 

fasta_section // 1是意味着以匹配确定序列。为了全部回溯,我们必须提供回溯点。在这种情况下,来自库(dcg/basics)的字符串// 1执行作业

+1

对不起,逗号是这个问题中的拼写错误。 我现在使用双引号这些东西和反向引号的字符串,因为它似乎是最兼容的做事方式。 – user27815

+0

如果我想要使用fasta_section // 1和返回轨道来查找每个解决方案,那么该怎么办? – user27815

+0

@ user27815:看最后一次编辑... – CapelliC

相关问题