It's good that you reduced your program to a minimal example, unfortunately it has become a bit too minimal. Based on your other questions, I'll start with the following version of your code:
noun(box) --> [box].
noun(table) --> [table].
conn(C) :- member(C,[on,in]).
req(C) --> noun(X), [Fun], noun(Y), { C =.. [Fun,X,Y], conn(Fun) }.
The following works:
?- phrase(req(Req), [box, on, table]).
Req = on(box, table) ;
false.
But the most general query does not work:
?- phrase(req(Req), Phrase).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [12] _4008=..[_4014,box|...]
This is unfortunate, since the most general query is very handy: It gives you some "testing for free", allowing you to run your code without having to think of test cases. The reason for the error here is that we are trying to apply =../2 with a variable function symbol.
I would write this grammar more like this:
noun(box) --> [box].
noun(table) --> [table].
connector(X, Y, on(X, Y)) -->
[on].
connector(X, Y, in(X, Y)) -->
[in].
req(C) -->
noun(X),
connector(X, Y, C),
noun(Y).
This is a bit more explicit, but it allows us to test (exhaustively, because there is no recursion!) with the most general query:
?- phrase(req(Req), Phrase).
Req = on(box, box),
Phrase = [box, on, box] ;
Req = on(box, table),
Phrase = [box, on, table] ;
Req = in(box, box),
Phrase = [box, in, box] ;
Req = in(box, table),
Phrase = [box, in, table] ;
Req = on(table, box),
Phrase = [table, on, box] ;
Req = on(table, table),
Phrase = [table, on, table] ;
Req = in(table, box),
Phrase = [table, in, box] ;
Req = in(table, table),
Phrase = [table, in, table].
Concrete tests work as well (this is hopefully not surprising):
?- phrase(req(Req), [box, on, table]).
Req = on(box, table) ;
false.
Letting the connector rules construct the term allows them to do extra work for specific connectors. For example, we might want to treat "inside" as a synonym for "in":
connector(X, Y, in(X, Y)) -->
[in] | [inside].
?- phrase(req(Req), [box, in, box]).
Req = in(box, box) ;
false.
?- phrase(req(Req), [box, inside, box]).
Req = in(box, box) ;
false.
Or we might want to treat "X under Y" as a synonym for "Y on X":
connector(X, Y, on(Y, X)) -->
[under].
?- phrase(req(Req), [table, under, box]).
Req = on(box, table) ;
false.