swaffelay
swaffelay

Reputation: 302

dcg parsing in random order

I have some text files which I would like to parse, however the order of for exemple stop and start could be different. Stop could appear first or last, this is a dummy exemple as there are multiple variables like stop,start ...

Exemple1.txt

stop: 1

start: 2

exemple2.txt

start: 9

stop: 4

I know how to parse start and stop when start is first and stop is second, however how would I do this when these are in random order.

parseStart(D) --> "start: " , integer(D).
parseStop(D) --> "stop: " , integer(D).

I recieve the to be parsed file from stdin , so I do
read_string to parse 1 line, turn that into char list and do phrase(parseStart(Startint),line1), same for line 2, however than I have to know the order which I don't.

Maybe I could do something like

parseBoth(StartInt,StopInt) --> parseStart(startInt) <|> parseStop(StopInt) 

And do that two times and check if both are unified ? However this seems like a hack and I am wondering if there is a better way to do this ?

Edit: stop, start are just one of the many exemples, I have many dcg expressions that are in random order, how would I do this since trying every order would mean that I have to write 6! predicates for the 6 possible stop,start,end,time ... expressions

Upvotes: 2

Views: 111

Answers (1)

Paulo Moura
Paulo Moura

Reputation: 18663

Maybe something like:

parse(start(Start), stop(Stop)) -->
    first(Token),
    rest(Token, Start, Stop).

first(start) --> "start: ".
first(stop)  --> "stop: ".

rest(start, Start, Stop) -->
    integer(Start), stop(Stop).
rest(stop, Start, Stop) -->
    integer(Stop), start(Start).

start(Start) --> "start: " , integer(Start).
stop(Stop)   --> "stop: " , integer(Stop).

Update after the question edit.

If all lines of your text files have the format "keyword: integer", you could use:

parse_pairs([]) -->
    eos.
parse_pairs([Pair| Pairs]) -->
    parse_pair(Pair),
    parse_pairs(Pairs).

parse_pair(Key-Value) -->
    string(String), ": ", integer(Value), blanks,
    {atom_string(Key, String)}.

Sample call:

?- phrase(parse_pairs(Pairs), "start: 1\nstop: 2").
Pairs = [start-1, stop-2] .

Upvotes: 1

Related Questions