Menu ▾ ▴

#183 Optional arguments don't work with generation

open
None
7
2007-12-11
2007-12-06
No

Generation doesn't work well if I make a category optional. In the following grammar, the first four rules are okay, but the latter don't work as I expect them to:

top:[sem=[ok_1,Name]] --> send, a, bug, report, ? (name:[sem=Name]).
top:[sem=[ok_2,Name]] --> send, a, bug, report, to, ? (the, honourable), name:[sem=Name].
top:[sem=[ok_3,Name]] --> send, a, bug, report, ? (to ; for), name:[sem=Name].
top:[sem=[ok_4,Name]] --> send, a, bug, report, (name:[sem=Name] ; to, name:[sem=Name]).
top:[sem=[bad_1,Name]] --> send, a, bug, report, ? (to, name:[sem=Name]).
top:[sem=[bad_2,Name]] --> send, a, bug, report, ? (name:[sem=Name], to).
top:[sem=[bad_3,Name]] --> send, a, bug, report, ? (to ; name:[sem=Name]).
top:[sem=[bad_4,Name]] --> send, a, bug, report, ([] ; name:[sem=Name]).
top:[sem=[bad_5,Name]] --> send, a, bug, report, (to ; name:[sem=Name]).

name:[sem=rayner] --> manny.

This is correct (or at least as I expect):

?- generate([ok_1,X], _, Sent).
X = rayner, Sent = [send,a,bug,report,manny] ? ;
X = _, Sent = [send,a,bug,report] ? ;
no

Note that X will be unbound when the optional name isn't selected. But this is not correct:

?- generate([bad_1,X], _, Sent).
X = _, Sent = [send,a,bug,report] ? ;
no

The optional name is never selected. And the only thing that differs with ok_1 is the optional part ? (to,name:[]) instead of ? (name:[]).

All the other bads behave in the same way, and they all have the same error in the autogenerated generation module:

top(...,[],[bad_1,B],C,D,E) -->
{D is C+1}, {D=<E},
[send], [a], [bug], [report],
( {A=(lex(to),F)}, [to], name(F,[],B,D,D,E)
; {A=empty_constituent}, []
).

The problem is that the call to name is ...,D,D,E), where it should be ...,DD,D,E). And {D is C+1} should be {DD is C+1}. Compare with the correctly translated ok_1:

top(...,[],[ok_1,B],C,D,E) -->
{DD is C+1}, {DD=<E},
[send], [a], [bug], [report],
( {A=F}, name(F,[],B,DD,D,E)
; {A=H}, null_sem(H,[],B,DD,D,E)
).

I have no idea how the generator_compiler works, so I hope someone else can fix this for me...

Discussion

  • peter ljunglöf

    peter ljunglöf - 2007-12-06
     
  • peter ljunglöf

    peter ljunglöf - 2007-12-07

    Logged In: YES
    user_id=1932543
    Originator: YES

    Another thing: it would be nice if the null_sem/8 predicate instantiated the semantics to '*null_value*'. Now it looks like:

    null_sem(phrase(null_sem,no_line_info,empty_constituent),[],A,B,C,D)-->{C is B+1},{C=<D},[].

    Why not add {A='*null_value*'} at the end of the RHS?

     
  • peter ljunglöf

    peter ljunglöf - 2007-12-11
    • assigned_to: nobody --> heatherleaf
     
  • peter ljunglöf

    peter ljunglöf - 2007-12-11

    Logged In: YES
    user_id=1932543
    Originator: YES

    I think I solved the problem. In generator_compiler.pl, replace the following clause on line 794:

    add_depth_checking_to_rule_body((P ; Q), (P1 ; Q1), CostIn, CostOut, CostMax) :-
    add_depth_checking_to_rule_body(P, P1, CostIn, CostOut, CostMax),
    add_depth_checking_to_rule_body(Q, Q1, CostIn, CostOut, CostMax),
    !.

    by the following:

    add_depth_checking_to_rule_body((P ; Q), (P1,PPost ; Q1,QPost), CostIn, CostOut, CostMax) :-
    add_depth_checking_to_rule_body(P, P1, CostIn, PCostOut, CostMax),
    add_depth_checking_to_rule_body(Q, Q1, CostIn, QCostOut, CostMax),
    PPost = {CostOut = PCostOut},
    QPost = {CostOut = QCostOut},
    !.

    I.e., defer the unification of CostOut until later. With this change, my test cases work fine.

    I have checked in my changes, I don't think there will be any problems with existing grammars.

    ----------------------------------------------------------------

    Also, I think that the ad-hoc solutions in regulus2dcg.pl, with the null_sem category, are not necessary anymore. I.e., I think that the following in regulus2dcg can be removed:

    * line 191-196:
    pre_process_rule1((?P), DCGType, (P1 ; NullP1), HeadP) :-
    DCGType = keep_line_info(static_for_generation),
    !,
    null_sem_version_of_constituent(P, NullP),
    pre_process_rule1(P, DCGType, P1, HeadP),
    pre_process_rule1(NullP, DCGType, NullP1, HeadP).

    * line 68-71:
    ( DCGType = keep_line_info(static_for_generation) ->
    assertz(category_internal(null_sem, [sem])) ;
    true
    ),

    * line 79-82:
    ( DCGType = keep_line_info(static_for_generation) ->
    add_rule_for_null_sem_cat(DCGRules1, DCGRules2) ;
    DCGRules1 = DCGRules2
    ),

    * lines 592-609:
    null_sem_version_of_constituent(P, NullP) :-
    P = _Cat:FeatValPairs,
    member(sem=SemVal, FeatValPairs),
    NullP = null_sem:[sem=SemVal],
    !.
    null_sem_version_of_constituent(_P, NullP) :-
    NullP = [].

    add_rule_for_null_sem_cat(DCGRules, [NullSemCatRule | DCGRules]) :-
    null_sem_cat_rule(NullSemCatRule),
    !.

    null_sem_cat_rule(rule((cat(null_sem, Feats, SemVal) --> []), no_line_info)) :-
    Feats = [],
    SemVal = no_value.

    I have not checked in this, I need more information about the use of the null_sem category.

     

Log in to post a comment.