<< Prev | - Up - | Next >> |
It is easy to turn this recognizer into a parser --- and (unlike with bottomup_recognizer.pl
) it's actually worth doing this, because it is efficient on small grammars. As is so often the case in Prolog, moving from a recognizer to a parser is simply a matter of adding additional arguments to record the structure we find along the way.
Here's the code. The ideas involved should be familiar by now. Read what is going on in the fourth argument position declaratively:
?- op(700,xfx,--->).
parse_topdown(Category,[Word|Reststring],Reststring,[Category,Word]) :-
lex(Word,Category).
parse_topdown(Category,String,Reststring,[Category|Subtrees]) :-
Category ---> RHS,
matches(RHS,String,Reststring,Subtrees).
matches([],String,String,[]).
matches([Category|Categories],String,RestString,[Subtree|Subtrees]) :-
parse_topdown(Category,String,String1,Subtree),
matches(Categories,String1,RestString,Subtrees).
And here's the new driver that we need:
parse_topdown(String,Parse) :-
parse_topdown(s,String,[],Parse).
Time to play. Here's a simple example:
parse_topdown([vincent,fell]).
[s,[np,[pn,vincent]],[vp,[iv,fell]]]
yes
And another one:
parse_topdown([vincent,shot,marsellus]).
[s,[np,[pn,vincent]],[vp,[tv,shot],[np,[pn,marsellus]]]]
yes
And here's a much harder one:
parse_topdown([jules,believed,the,robber,who,shot,the,robber,who,shot,the,
robber,who,shot,marsellus,fell]).
[s,[np,[pn,jules]],[vp,[sv,believed],[s,[np,[det,the],
[nbar,[n,robber],[rel,[wh,who],[vp,[tv,shot],[np,[det,the],
[nbar,[n,robber],[rel,[wh,who],[vp,[tv,shot],[np,[det,the],
[nbar,[n,robber],[rel,[wh,who],[vp,[tv,shot],
[np,[pn,marsellus]]]]]]]]]]]]]],[vp,[iv,fell]]]]]
yes
As this last example shows, we really need a pretty-print output!
<< Prev | - Up - | Next >> |