15.3 Putting it in Prolog

We will now implement the improved top-down generator in Prolog. The main predicate is called generate_topdown/2. The first argument is a logical formula representing the semantic content that we want to express. With this formula, let's call it SemInput, we build the following feature structure:

[cat:s, semF:[sem:SemInput|_] |_].

That's the feature structure that we start generation with. When we are finished this feature structure will be further specified and among other things it will contain a feature syn which holds the syntactic structure that was built. We extract it and return it in the second argument of generate_topdown.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% generate_topdown(+logical formula, ?parse tree)
 
generate_topdown(SemInput, Parse) :-
        StartFS = [cat:s, semF:[sem:SemInput|_] |_],
        apply_rules_topdown(StartFS),
        val(syn,Parse,StartFS,_).

This is the predicate that applies grammar rules in a top-down fashion. We need two clauses to deal with lexical and phrasal rules. In both cases we unify the incoming feature structure with the left hand side of the rule. For lexical rules, we have found a word if the unification works. For phrase structure rules, we have to produce constituents fitting the categories on the right hand side of the rule. That is done by expand_rhs.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% apply_rules_topdown(+node/feature structure)
 
apply_rules_topdown(FS) :-
        lex(_Word, WordFS),
        unify_silent(WordFS,FS,_).
 
apply_rules_topdown(FS) :-
        LHS ---> RHS,
        unify_silent(FS,LHS,_),
        expand_rhs(RHS).

expand_rhs/1 is a normal list processing predicate that makes sure that apply_rules_topdown is applied to all feature structures in its input list. It uses select_node_to_expand to select one, applies apply_rules_topdown to it and then makes a recursive call with the remainder of the list.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% expand_rhs(+list of nodes)
 
expand_rhs([]).
expand_rhs([FS|FSs]) :-
        select_node_to_expand([FS|FSs],Node,Rest),
        apply_rules_topdown(Node),
        expand_rhs(Rest).

select_node_to_expand/3 takes as input a list of feature structures in its first argument. We want to select the first feature structure in that list where the value of the sem feature und the semF feature is instantiated (i.e., not uninstantiated). We return the node that we found in the second argument, and the rest of the list in the third argument. This predicate fails if there is no feature structure in the list where the semantics is specified.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% select_node_to_expand(+list of nodes, -node, -rest)
 
select_node_to_expand([Node|Rest], Node, Rest) :-
        val(semF,SemF,Node,_),
        val(sem,Sem,SemF,_),
        \+ var(Sem), !.
select_node_to_expand([FS|FSs], Node, [FS|Rest]) :-
        select_node_to_expand(FSs, Node, Rest).


Patrick Blackburn and Kristina Striegnitz
Version 1.2.4 (20020829)