:- module(parser, [prompt/1, readList/1, readLine/1, split/2, join/2, intercalate/3]). % functions for dealing with lines of text % eg obtaining one, parsing it into a list of words, and rejoining it % prompt provides the user with a '>' prompt % readList merely obtains and parses the input % readLine obtains a raw line of input % split parses a line of text into words % join takes a list of words and joins them into one string prompt(L) :- write('> '), readList(L). readList(L) :- readLine(X), split(X,L). readLine(L) :- get_char(C), readLine_tail(C,L). readLine_tail('\n',[]) :- !. readLine_tail(C,[C|X]) :- get_char(C2), readLine_tail(C2,X). split(X,R) :- wordList(R,X,[]), !. join([X|Y],R) :- join(Y,Rx), atom_concat(X,Rx,R). join([X],R) :- R = X. intercalate([X|Y], Spacer, Result) :- intercalate(Y, Spacer, Tail), atom_concat(X, Spacer, Head), atom_concat(Head, Tail, Result). intercalate([X], _, Result) :- Result = X. wordList(X) --> whitespace, wordList(X). wordList([X]) --> word(X). wordList([X]) --> word(X), whitespace. wordList([X|Y]) --> word(X), whitespace, wordList(Y). word(W) --> charList(X), {atom_chars(W,X)}. charList([X|Xs]) --> char(X), charList(Xs). charList([X]) --> char(X). whitespace --> whsp, whitespace. whitespace --> whsp. whsp --> oneOf(_,[' ', '\r', '\n', '\t']). char(X) --> noneOf(X,[' ', '\r', '\n', '\t']). oneOf(X,L) --> [X], {member(X,L)}. noneOf(X,L) --> [X], {not(member(X,L))}.