0

I'm reading a file containing context free grammar and tokenizing each line and generating a list of the form

L = ['S', =, a, 'S', b, ;, 'S', =, c;].

In the list ';' means new line. This list may extend based on the grammar in the file. Now i wanted to partition the list for every ';' encountered.

For example, consider the following rule

getRule(List, First, Rest):-

I should be able to get the first grammar line 'S', =, a, 'S', b, as first and the remaining list as Rest each time recursively.

Anil
  • 2,405
  • 6
  • 25
  • 28

1 Answers1

1

Here is the whole thing (how to split your List into Rules) :

getRules([], _Delimiter, []) :- !.
getRules(List, Delimiter, [Rule|Rules]) :-
    getRule(List, Delimiter, Rule, Rest),
    getRules(Rest, Delimiter, Rules).

Using the getRule you asked for :

getRule([], _Delimiter, [], []) :- !.
getRule([Delimiter|Rest], Delimiter, [], Rest) :- !.
getRule([Item|List], Delimiter, [Item|Rule], Rest) :-
    getRule(List, Delimiter, Rule, Rest).

Callable with

?- getRule(['S', =, a, 'S', b, ;, 'S', =, c, ;], ;, Rule, Rest).

Returns

Rule = ['S', =, a, 'S', b],
Rest = ['S', =, c, ;].

And the main one :

?- getRules(['S', =, a, 'S', b, ;, 'S', =, c, ;], ;, Rules).

returns

Rules = [['S', =, a, 'S', b], ['S', =, c]].

You can obviously hardcode ; if you want !
Please ask if you need any explanation about the code.
I added the modification discussed in comments and remove spoilers since you read it.

Here is the other thing you asked for :

divideRules(Rules, PureRules) :-
    divideRules_(Rules, Temp),
    append(Temp, PureRules).
divideRules_([], []) :- !.
divideRules_([Rule|Rules], [PureRule|PureRules]) :-
    divideRule(Rule, PureRule),
    divideRules_(Rules, PureRules).
divideRule(Rule, PureRule) :-
    getRule(Rule, ::=, Left, Right),
    append([Left, [::=]], NewLeft),
    getRules(Right, '|', PureRight),
    maplist(append(NewLeft), PureRight, PureRule).

Here is my guess but I can't run a prolog interpreter now so it's untested :

grammarize([], []) :- !.
grammarize([[Left, ::=|Right]|PureRules], [grammar(Left, Right)|Grammars]) :-
    grammarize(PureRules, Grammars).
m09
  • 7,490
  • 3
  • 31
  • 58
  • Your piece of code is working but when i'm calling with `get_rules(['S',::=,a,'S',b,;,'S',::=,c], ;, Rules).` it is returning false...why?? – Anil Nov 28 '11 at 00:38
  • 1
    because there is no ; at the end, you can add getRule([], _Delimiter, [], []) :- !. at the top of getRule clauses to make it work even without ; at the end ! – m09 Nov 28 '11 at 00:43
  • I edited my post to take that into account (and removed spoilers since they were kinda late). – m09 Nov 28 '11 at 00:49
  • thanks for your help. But i have 1 more question. What if i wanted to read the list `['S', =, a, 'S', b, ;, 'S', =, c, ;]` until a delimiter is encountered and put it in a new list. As i showed in my question, if i wanted to use `getRule(List, First, Rest):-` such that `list` will be the given list,`first` will be the list of items till the first `;` is encountered ... so on..so that i can easily access the list 'first' everytime. – Anil Nov 28 '11 at 01:12
  • 1
    I already answered that ! ?- getRule(['S', =, a, 'S', b, ;, 'S', =, c, ;], ;, Rule, Rest). will put the first rule in Rule. – m09 Nov 28 '11 at 07:04
  • 1
    And BTW, if you already calculate Rules, you do not need to call getRule to calculate the first, rule, you can just write [First|_Rules] = Rules – m09 Nov 28 '11 at 08:22
  • Thanks. Can you further help me with an insert predicate i'm struggling with? – Anil Nov 28 '11 at 18:44
  • Sure, but make a new question if it's not related to this split problem maybe ! – m09 Nov 28 '11 at 18:45
  • That is somewhat related to this question itself..After splitting the list into `[[S,::=,a,S,b],[S,::=,c,|,d]]` i want to write an insert function something like `insert(grammar(g1),....)` such that it generates a list of the form `L=[grammar(S,::=,a,S,b),grammar(S,::=,c),grammar(S,::=,d)....]` If you observe here..if the grammar is something like `S ::= c | d` i should divide it and write it as `S,::=,c` and `S,::=,d` – Anil Nov 28 '11 at 18:54
  • 1
    @bharathkumar : posted something, usage is ?- divideRules([['S', ::=, a, 'S', b],['S', ::=, c, '|', d]], PureRules). – m09 Nov 28 '11 at 19:26
  • where should i make changes to get this output `PureRules =[grammar('S', [a, 'S', b]), grammar('S', [c]), grammar('S', [d])].` instead of `PureRules = [['S', a, 'S', b], ['S', c], ['S', d]].` – Anil Nov 28 '11 at 19:55
  • thank you so much...to be frank i'm really very bad at prolog but have to work on it, struggling, but have to learn much. – Anil Nov 28 '11 at 21:02
  • i've posted a new question regarding dcg and database facts. Pls have a look at that and provide me with some tips. http://stackoverflow.com/questions/8336153/calling-facts-from-database-in-prolog – Anil Dec 01 '11 at 06:16
  • @ven Well I'm not familiar with DCGs in prolog, but I think that false or someone else will be happy to help you ! – m09 Dec 01 '11 at 09:45