2015-07-11 9 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). разделы едина со списком разделов/2s, что то, что я хочу, но мой текущий код кажется вполне hacky-, как я обработал символ новой строки например.

+0

Typo: 'S =" X "->' должен читать '[S] =" X "->' – false

+0

[Этот ответ] (HTTP: // StackOverflow.com/a/12942551/772868) будет представлять для вас интерес. – false

+1

Заменить '{Section = .. [section, Description, Sequence]}' by '{Section = section (Описание, последовательность)}' – 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, я написал парсер, чтобы загрузить в Прологе а MySQL dump (простой 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 это означает, чтобы соответствовать определенной последовательности. Чтобы получить все отбросы, мы должны предоставить точку возврата. В этом случае строка // 1 из библиотеки (dcg/basics) выполняет задание

+1

Извините, что запятые были опечаткой в ​​вопросе. Теперь я использую двойные кавычки для этих вещей и обратные кавычки для строк, поскольку это, по-видимому, самый совместимый способ делать вещи. – user27815

+0

Как насчет того, хотел ли я использовать fasta_section // 1 и back track для поиска каждого решения? – user27815

+0

@ user27815: посмотреть последнее изменение ... – CapelliC