:- module(pio, [ phrase_from_file/2, % :Grammarbody, +File phrase_from_file/3, % :Grammarbody, +File, +Options phrase_of_from_file/4, % :Grammarbody, :Reader, +File, +Options rider_to_lazy_list/3, % :Reader(Stream, Xs0,Xs),Stream, -LazyList stream_to_lazy_list/2 % :Stream, -LazyList % SWI compatibility ]). /** Pure, phrase based, Prolog I/O This library provides side effect free I/O. Files can now be processed in a pure side effect free manner with DCGs. Many Prolog predicates only read data from a file, those programs can be made side effect free. @author Ulrich Neumerkel */ :- use_module(library(error)). %% phrase_from_file(:Grammar, +File) is nondet. % % == % ... --> [] | [_], ... . % ?- phrase_from_file((..., "searchstring", ...), myfile). :- op(950,fy, [$]). $(X) :- copy_term_nat(X,Y),numbervars(Y,0,_),portray_clause(call:Y), X, portray_clause(exit:_). % copy_term_nat(X,Z),numbervars(Z,0,_),portray_clause(exit:Z). %$(X) :- % copy_term_nat(X,Y),numbervars(Y,0,_),portray_clause(fail:Y), % fail. :- meta_predicate phrase_from_file(2,+). :- meta_predicate phrase_from_file(2,+,+). % debatable :- meta_predicate phrase_of_from_file(2,:,+,+). :- meta_predicate setup_call_cleanup(0, 0, 0). % compatibility setup_call_cleanup( Setup_0, Call_0, Cleanup_0) :- Setup_0, call_cleanup(Call_0, Cleanup_0). :- load_foreign_files([plstream], [], initIO). %run :- phrase_of_from_file("a",swi_read_pending_input,a,[]). run :- setup_call_cleanup( $swi_open(a,read,Stream), ( rider_to_lazy_list(swi_read_pending_input,Stream,Xs), Xs = "a" ), $swi_close(Stream)). phrase_from_file(Nonterminal_2, File) :- phrase_from_file(Nonterminal_2, File, []). phrase_from_file(Nonterminal_2, File) :- current_prolog_flag(double_quotes, Value), ( Value == chars -> Reader_3 = read_chars_input % recommended ; Value == codes -> Reader_3 = read_codes_input % suboptimal ; ), phrase_of_from_file(Nonterminal_2, Reader_3, File). phrase_of_from_file(Nonterminal_2, Reader, File, Options) :- must_be(list, Options), must_be(oneof([[]]), Options), % currently... setup_call_cleanup( open(File, read, Stream), ( reader_to_lazy_list(Reader_3, Stream, Xs), phrase(Nonterminal_2, Xs) ), close(Stream)). reader_to_lazy_list(Reader_3, Stream, Xs) :- stream_property(Stream, position(Pos)), freeze(Xs, reader_step(Reader_3, Stream, Pos, Xs)). reader_step(Reader_3, Stream, Pos, Xs0) :- set_stream_position(Stream, Pos), ( at_end_of_stream(Stream) -> Xs0 = [] ; % phrase(call(call(Reader,Stream)), Xs0,Xs), call(Reader_3, Stream, Xs0,Xs), reader_step(Reader_3, Stream, Xs) ). %% stream_to_lazy_list(+Stream, -Xs) is det. % stream_to_lazy_list(Stream, Xs) :- rider_to_lazy_list(swi_read_pending_input,Stream, Xs). tokenwise(Method,Stream) --> [Token], {call(Method, Stream, Token)}. % Xs = [_,_,_,_,_,_,_|_], phrase_from_file((...,seq(Xs),...,seq(Xs),...), '/etc/passwd').