Discussion:
How to hide implied tokens in DCG rules?
Stassa Patsantzis
2011-06-25 16:15:45 UTC
Permalink
Hi all!

I'm trying to find a way to hide implied tokens while parsing (or generating) a phrase with DCGs. Here's what I mean. I want to parse, eg, these two phrases:
   
        "I like ice cream and I like jam".
        "I like ice cream and jam"
       
- using the same DCG rule. The second "I like" is implied, but it's not wrong to use it.
   
Because of everything else that's going on in the ruleset, it's a bit complicated to just do, say:

   like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).
       
It would be very convenient if I could hide tokens, like I say above. So, is there a way to do this?
     
- Thanks,
Stassa
-------------- next part --------------
HTML attachment scrubbed and removed
Carlo Capelli
2011-06-26 11:34:41 UTC
Permalink
Post by Stassa Patsantzis
Hi all!
I'm trying to find a way to hide implied tokens while parsing (or
generating) a phrase with DCGs. Here's what I mean. I want to parse, eg,
"I like ice cream and I like jam".
"I like ice cream and jam"
- using the same DCG rule. The second "I like" is implied, but it's not wrong to use it.
Because of everything else that's going on in the ruleset, it's a bit
like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).
It would be very convenient if I could hide tokens, like I say above. So,
is there a way to do this?
- Thanks,
Stassa
a very simple change to your DCG could do:

like(X,Y) -->
[A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.

Anyway, DCGs usually require you to make the patterns explicit.

bye Carlo
Post by Stassa Patsantzis
-------------- next part --------------
HTML attachment scrubbed and removed
_______________________________________________
SWI-Prolog mailing list
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
-------------- next part --------------
HTML attachment scrubbed and removed
Stassa Patsantzis
2011-06-26 16:34:57 UTC
Permalink
--- On Sun, 26/6/11, Stassa Patsantzis <***@yahoo.com> wrote:

From: Stassa Patsantzis <***@yahoo.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Carlo Capelli" <***@gmail.com>
Date: Sunday, 26 June, 2011, 12:34

    Hi Carlo!

    Thank you for replying. It would indeed be very simple to use a disjunction like you suggest, unfortunately, ike I said, I can't :)
   
    The reason I can't do it is because I need to do some type-checking. A different example would be declaring multiple variables using a single type word, say:
   
        integer x, y;
   
    - instead of:
   
        integer x;
        integer y;
       
    The type-checking is done by a rule like:
   
        integer(X) --> [integer, X].
   
    So I need a rule of the form:
   
        integer(X,Y) --> integer(X), [','], integer(Y).
       
    Only of course this will parse as:
   
   
    integer x, integer y;
       
    So I need to skip the second instance of "integer" somehow, but still let integer(X,Y) parse. That's why I say it needs to be "implied".
           
    Sorry -this still isn't a full example, but a) I'm trying to figure out the general case and b) a literal example would be a bit too involved, I fear.
   
    Thanks again and have a great Sunday afternoon!
    - Stassa

--- On Sun, 26/6/11, Carlo Capelli <***@gmail.com> wrote:

From: Carlo Capelli <***@gmail.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis"
<***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Sunday, 26 June, 2011, 7:34

2011/6/25 Stassa Patsantzis <***@yahoo.com>

Hi all!



I'm trying to find a way to hide implied tokens while parsing (or generating) a phrase with DCGs. Here's what I mean. I want to parse, eg, these two phrases:

   

        "I like ice cream and I like jam".

        "I like ice cream and jam"

       

- using the same DCG rule. The second "I like" is implied, but it's not wrong to use it.

   

Because of everything else that's going on in the ruleset, it's a bit complicated to just do, say:



   like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).

       

It would be very convenient if I could hide tokens, like I say above. So, is there a way to do this?

     

- Thanks,

Stassa


a very simple change to your DCG could do:



like(X,Y) -->

    [A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.



Anyway, DCGs usually require you to make the patterns explicit.



bye Carlo


 
-------------- next part --------------

HTML attachment scrubbed and removed

_______________________________________________

SWI-Prolog mailing list

SWI-***@lists.iai.uni-bonn.de

https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog



-------------- next part --------------
HTML attachment scrubbed and removed
Feliks Kluzniak
2011-06-27 16:11:01 UTC
Permalink
Hi Stassa,

It would seem to me that for the particular example of type checking it
might be more convenient to separate the parser from the type checker. The
conventional approach is to make the parser produce a convenient abstract
syntax tree, and then to make subsequent passes (like type checking) operate
on (and perhaps modify) that tree.

So, for example,

integer( integer_declarations[ Var | Vars ] ) -->
[ integer, Var ],
rest_of_declaration( Vars ),
[ (;) ].


rest_of_declaration( [ Var | Vars ] ) -->
[ (,) ],
!,
rest_of_declaration( Vars ).

rest_of_declaration( [] ) --> [] .

The technique of using an auxiliary nonterminal symbol for optional or
iterated stuff is also a standard one.

Is this relevant to your questions?

-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Stassa Patsantzis
Sent: Sunday, June 26, 2011 11:35 AM
To: swi-***@lists.iai.uni-bonn.de
Subject: [SWIPL] How to hide implied tokens in DCG rules?



--- On Sun, 26/6/11, Stassa Patsantzis <***@yahoo.com> wrote:

From: Stassa Patsantzis <***@yahoo.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Carlo Capelli" <***@gmail.com>
Date: Sunday, 26 June, 2011, 12:34

    Hi Carlo!

    Thank you for replying. It would indeed be very simple to use a
disjunction like you suggest, unfortunately, ike I said, I can't :)
   
    The reason I can't do it is because I need to do some type-checking. A
different example would be declaring multiple variables using a single type
word, say:
   
        integer x, y;
   
    - instead of:
   
        integer x;
        integer y;
       
    The type-checking is done by a rule like:
   
        integer(X) --> [integer, X].
   
    So I need a rule of the form:
   
        integer(X,Y) --> integer(X), [','], integer(Y).
       
    Only of course this will parse as:
   
   
    integer x, integer y;
       
    So I need to skip the second instance of "integer" somehow, but still
let integer(X,Y) parse. That's why I say it needs to be "implied".
           
    Sorry -this still isn't a full example, but a) I'm trying to figure out
the general case and b) a literal example would be a bit too involved, I
fear.
   
    Thanks again and have a great Sunday afternoon!
    - Stassa

--- On Sun, 26/6/11, Carlo Capelli <***@gmail.com> wrote:

From: Carlo Capelli <***@gmail.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis"
<***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Sunday, 26 June, 2011, 7:34

2011/6/25 Stassa Patsantzis <***@yahoo.com>

Hi all!



I'm trying to find a way to hide implied tokens while parsing (or
generating) a phrase with DCGs. Here's what I mean. I want to parse, eg,
these two phrases:

   

        "I like ice cream and I like jam".

        "I like ice cream and jam"

       

- using the same DCG rule. The second "I like" is implied, but it's not
wrong to use it.

   

Because of everything else that's going on in the ruleset, it's a bit
complicated to just do, say:



   like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).

       

It would be very convenient if I could hide tokens, like I say above. So, is
there a way to do this?

     

- Thanks,

Stassa


a very simple change to your DCG could do:



like(X,Y) -->

    [A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.



Anyway, DCGs usually require you to make the patterns explicit.



bye Carlo


 
-------------- next part --------------

HTML attachment scrubbed and removed

_______________________________________________

SWI-Prolog mailing list

SWI-***@lists.iai.uni-bonn.de

https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog



-------------- next part --------------
HTML attachment scrubbed and removed
Feliks Kluzniak
2011-06-27 19:17:57 UTC
Permalink
Should have been

rest_of_declaration( [ Var | Vars ] ) -->
[ (,), Var ],
...

of course.


-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Feliks Kluzniak
Sent: Monday, June 27, 2011 11:11 AM
To: 'Stassa Patsantzis'; swi-***@lists.iai.uni-bonn.de
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?

Hi Stassa,

It would seem to me that for the particular example of type checking it
might be more convenient to separate the parser from the type checker. The
conventional approach is to make the parser produce a convenient abstract
syntax tree, and then to make subsequent passes (like type checking) operate
on (and perhaps modify) that tree.

So, for example,

integer( integer_declarations[ Var | Vars ] ) -->
[ integer, Var ],
rest_of_declaration( Vars ),
[ (;) ].


rest_of_declaration( [ Var | Vars ] ) -->
[ (,) ],
!,
rest_of_declaration( Vars ).

rest_of_declaration( [] ) --> [] .

The technique of using an auxiliary nonterminal symbol for optional or
iterated stuff is also a standard one.

Is this relevant to your questions?

-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Stassa Patsantzis
Sent: Sunday, June 26, 2011 11:35 AM
To: swi-***@lists.iai.uni-bonn.de
Subject: [SWIPL] How to hide implied tokens in DCG rules?



--- On Sun, 26/6/11, Stassa Patsantzis <***@yahoo.com> wrote:

From: Stassa Patsantzis <***@yahoo.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Carlo Capelli" <***@gmail.com>
Date: Sunday, 26 June, 2011, 12:34

    Hi Carlo!

    Thank you for replying. It would indeed be very simple to use a
disjunction like you suggest, unfortunately, ike I said, I can't :)
   
    The reason I can't do it is because I need to do some type-checking. A
different example would be declaring multiple variables using a single type
word, say:
   
        integer x, y;
   
    - instead of:
   
        integer x;
        integer y;
       
    The type-checking is done by a rule like:
   
        integer(X) --> [integer, X].
   
    So I need a rule of the form:
   
        integer(X,Y) --> integer(X), [','], integer(Y).
       
    Only of course this will parse as:
   
   
    integer x, integer y;
       
    So I need to skip the second instance of "integer" somehow, but still
let integer(X,Y) parse. That's why I say it needs to be "implied".
           
    Sorry -this still isn't a full example, but a) I'm trying to figure out
the general case and b) a literal example would be a bit too involved, I
fear.
   
    Thanks again and have a great Sunday afternoon!
    - Stassa

--- On Sun, 26/6/11, Carlo Capelli <***@gmail.com> wrote:

From: Carlo Capelli <***@gmail.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis"
<***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Sunday, 26 June, 2011, 7:34

2011/6/25 Stassa Patsantzis <***@yahoo.com>

Hi all!



I'm trying to find a way to hide implied tokens while parsing (or
generating) a phrase with DCGs. Here's what I mean. I want to parse, eg,
these two phrases:

   

        "I like ice cream and I like jam".

        "I like ice cream and jam"

       

- using the same DCG rule. The second "I like" is implied, but it's not
wrong to use it.

   

Because of everything else that's going on in the ruleset, it's a bit
complicated to just do, say:



   like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).

       

It would be very convenient if I could hide tokens, like I say above. So, is
there a way to do this?

     

- Thanks,

Stassa


a very simple change to your DCG could do:



like(X,Y) -->

    [A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.



Anyway, DCGs usually require you to make the patterns explicit.



bye Carlo


 
-------------- next part --------------

HTML attachment scrubbed and removed

_______________________________________________

SWI-Prolog mailing list

SWI-***@lists.iai.uni-bonn.de

https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog



-------------- next part --------------
HTML attachment scrubbed and removed
Samer Abdallah
2011-06-28 08:42:04 UTC
Permalink
Referring back to Jan's earlier request for opinions on a DCG basics
module, I think this is a good example of a use-case for the
seqmap//N and seqmap_with_sep//N grammar rules I mentioned in
one of my earlier posts. With these available, the rule for integer
declarations becomes

integer(Vars) --> [integer], seqmap_with_sep( ',', out, Vars), ';'.

where out//1 is another utility I keep handy for these occasions:
out(X) --> [X].

seqmap//N (sequential map) is the equivalent of maplist/N for DCGS:

seqmap(P,[]) --> [].
seqmap(P,[A|AX]) --> call(P,A), seqmap(P,AX).
% etc for seqmap//3, seqmap//4..

seqmap_with_sep is similar but puts a phrase strictly in-between calls
to phrase P, ie only if there are 2 or more elements in the list.
I just my implementation and noticed that it fails if the list is empty.
I mu checked st have a had a good reason for this, and it fits all my use cases, so here it is:

seqmap_with_sep(S,P,[A|AX]) --> phrase(S), call(P,A), seqmap_with_prefix(S,P,AX).

seqmap_with_prefix(S,P,[]) --> [].
seqmap_with_prefix(S,P,[A,AX]) --> phrase(S), call(P,A), seqmap_with_prefix(S,P,AX).
% etc for higher arities


Samer.
Post by Feliks Kluzniak
Hi Stassa,
It would seem to me that for the particular example of type checking it
might be more convenient to separate the parser from the type checker. The
conventional approach is to make the parser produce a convenient abstract
syntax tree, and then to make subsequent passes (like type checking) operate
on (and perhaps modify) that tree.
So, for example,
integer( integer_declarations[ Var | Vars ] ) -->
[ integer, Var ],
rest_of_declaration( Vars ),
[ (;) ].
rest_of_declaration( [ Var | Vars ] ) -->
[ (,) ],
!,
rest_of_declaration( Vars ).
rest_of_declaration( [] ) --> [] .
The technique of using an auxiliary nonterminal symbol for optional or
iterated stuff is also a standard one.
Is this relevant to your questions?
-- Feliks
-----Original Message-----
e] On Behalf Of Stassa Patsantzis
Sent: Sunday, June 26, 2011 11:35 AM
Subject: [SWIPL] How to hide implied tokens in DCG rules?
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
Date: Sunday, 26 June, 2011, 12:34
Hi Carlo!
Thank you for replying. It would indeed be very simple to use a
disjunction like you suggest, unfortunately, ike I said, I can't :)
The reason I can't do it is because I need to do some type-checking. A
different example would be declaring multiple variables using a single type
integer x, y;
integer x;
integer y;
integer(X) --> [integer, X].
integer(X,Y) --> integer(X), [','], integer(Y).
integer x, integer y;
So I need to skip the second instance of "integer" somehow, but still
let integer(X,Y) parse. That's why I say it needs to be "implied".
Sorry -this still isn't a full example, but a) I'm trying to figure out
the general case and b) a literal example would be a bit too involved, I
fear.
Thanks again and have a great Sunday afternoon!
- Stassa
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis"
Date: Sunday, 26 June, 2011, 7:34
Hi all!
I'm trying to find a way to hide implied tokens while parsing (or
generating) a phrase with DCGs. Here's what I mean. I want to parse, eg,
"I like ice cream and I like jam".
"I like ice cream and jam"
- using the same DCG rule. The second "I like" is implied, but it's not wrong to use it.
Because of everything else that's going on in the ruleset, it's a bit
like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).
It would be very convenient if I could hide tokens, like I say above. So, is
there a way to do this?
- Thanks,
Stassa
like(X,Y) -->
[A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.
Anyway, DCGs usually require you to make the patterns explicit.
bye Carlo
-------------- next part --------------
HTML attachment scrubbed and removed
_______________________________________________
SWI-Prolog mailing list
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
-------------- next part --------------
HTML attachment scrubbed and removed
_______________________________________________
SWI-Prolog mailing list
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
_______________________________________________
SWI-Prolog mailing list
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
Richard O'Keefe
2011-06-28 23:39:41 UTC
Permalink
Post by Samer Abdallah
Referring back to Jan's earlier request for opinions on a DCG basics
module, I think this is a good example of a use-case for the
seqmap//N and seqmap_with_sep//N grammar rules I mentioned in
one of my earlier posts. With these available, the rule for integer
declarations becomes
integer(Vars) --> [integer], seqmap_with_sep( ',', out, Vars), ';'.
out(X) --> [X].
This is a textbook example of the limitations of this approach:
where does this rule say _anywhere_ that the items must be identifiers?
(Oh, the ';' at the end should be [';'] -- just a typo.)
Post by Samer Abdallah
seqmap(P,[]) --> [].
seqmap(P,[A|AX]) --> call(P,A), seqmap(P,AX).
% etc for seqmap//3, seqmap//4..
The nice thing about

ids([V|Vs]) --> [identifier(V)], rest_ids(Vs).
rest_ids([]) --> [';'].
rest_ids(Vs) --> [','], ids(Vs).

is that it's obviously LL(1). We could have an LL1ish preprocessor that
exploited this, giving us a translation something like

ids(identifier(V), [V|Vs], [T|R1], R) :-
rest_ids(T, Vs, R1, R).

rest_ids(';', [], R, R).
rest_ids(',', Vs, [T|R1], R) :-
ids(T, Vs, R1, R).

If you're forcing a one token lookahead all the time,
how do you handle the end of the token list?
The classic way:

ll1_phrase(NT, [Token|List]) :-
append(List, [end_of_file], List1),
NT =.. [P|Args],
append(Args, [List1,[]], Args1),
G =.. [P,Token|Args1],
call(G).

which isn't pretty. Is this worth writing up?

call(NT, Token,
Samer Abdallah
2011-06-29 11:03:20 UTC
Permalink
Post by Richard O'Keefe
Post by Samer Abdallah
Referring back to Jan's earlier request for opinions on a DCG basics
module, I think this is a good example of a use-case for the
seqmap//N and seqmap_with_sep//N grammar rules I mentioned in
one of my earlier posts. With these available, the rule for integer
declarations becomes
integer(Vars) --> [integer], seqmap_with_sep( ',', out, Vars), ';'.
out(X) --> [X].
where does this rule say _anywhere_ that the items must be identifiers?
(Oh, the ';' at the end should be [';'] -- just a typo.)
is this what you mean?

integer(Vars) --> [integer], seqmap_with_sep( [','], identifier, Vars), [';'].
identifier(X) --> [identifier(X)].
Post by Richard O'Keefe
The nice thing about
ids([V|Vs]) --> [identifier(V)], rest_ids(Vs).
rest_ids([]) --> [';'].
rest_ids(Vs) --> [','], ids(Vs).
is that it's obviously LL(1). We could have an LL1ish preprocessor that
exploited this, giving us a translation something like
ids(identifier(V), [V|Vs], [T|R1], R) :-
rest_ids(T, Vs, R1, R).
rest_ids(';', [], R, R).
rest_ids(',', Vs, [T|R1], R) :-
ids(T, Vs, R1, R).
Yes, this is true. But I don't have an LL1 preprocessor and
I do use DCGs all the time, and not just for parsers, so seqmap
and seqmap_with_sep are very useful abstractions that save
me writing a lot of recursive boilerplate (just like maplist/N) and,
to my eye, communicate the declarative intent quite well. Also,
I think it would be possible to write an LL1 preprocessor
that could handle the high-order code, given a suitable representation
of the grammar rules (see, eg Swiestra and Duponcheel's parser
combinator library, as discussed in John Hugh's (2000) paper
'Generalizing Monads to Arrows').

The next bit seems to have been cut off in mid flow - can
you elaborate on "call(NT, Token,"?

Samer.
Post by Richard O'Keefe
If you're forcing a one token lookahead all the time,
how do you handle the end of the token list?
ll1_phrase(NT, [Token|List]) :-
append(List, [end_of_file], List1),
NT =.. [P|Args],
append(Args, [List1,[]], Args1),
G =.. [P,Token|Args1],
call(G).
which isn't pretty. Is this worth writing up?
call(NT, Token,
Ulrich Neumerkel
2011-06-27 23:29:30 UTC
Permalink
Post by Feliks Kluzniak
Should have been
rest_of_declaration( [ Var | Vars ] ) -->
[ (,), Var ],
...
[(,), Var] should read [',', Var].

(,) is invalid syntax in ISO and 8 other systems. Similar cases where
SWI is a bit too permissive are #93 and #94:

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_assessment#93

, is not an atom. It has to be written ',' to be one.

There is no need to put round brackets around an atom that is an
operator if that atom occurs alone or in a list or an argument list.
Kuniaki Mukai
2011-06-28 06:24:24 UTC
Permalink
Post by Ulrich Neumerkel
Post by Feliks Kluzniak
Should have been
rest_of_declaration( [ Var | Vars ] ) -->
[ (,), Var ],
...
[(,), Var] should read [',', Var].
(,) is invalid syntax in ISO and 8 other systems. Similar cases where
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_assessment#93
, is not an atom. It has to be written ',' to be one.
There is no need to put round brackets around an atom that is an
operator if that atom occurs alone or in a list or an argument list.
I am ashamed to have little attention to the syntax of (SWI-)Prolog
so far long. I should change my attitude.

Now I see that the comma is not an atom. But could you tell me
what is the comma in the following.

(a, b)

Is this comma an atom ? Or is it not an atom but a punctuation
symbol ? If it is the latter, what is the main functor of this term ?
Thank you for answering this, which seems to be a FAQ.

Kuniaki
Post by Ulrich Neumerkel
_______________________________________________
SWI-Prolog mailing list
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
Richard O'Keefe
2011-06-28 06:31:55 UTC
Permalink
Post by Kuniaki Mukai
Now I see that the comma is not an atom. But could you tell me
what is the comma in the following.
(a, b)
Is this comma an atom ?
No. It is a punctuation mark, just like "(" or "|".
Post by Kuniaki Mukai
Or is it not an atom but a punctuation symbol ?
If it is the latter, what is the main functor of this term ?
The principal functor of (a, b) is (',')/2.
That is in some ways an accident; in DEC-10 and Quintus
Prolog the principal functor of (a | b) was (';')/2.
Kuniaki Mukai
2011-06-28 13:18:58 UTC
Permalink
Post by Richard O'Keefe
Post by Kuniaki Mukai
Now I see that the comma is not an atom. But could you tell me
what is the comma in the following.
(a, b)
Is this comma an atom ?
No. It is a punctuation mark, just like "(" or "|".
Post by Kuniaki Mukai
Or is it not an atom but a punctuation symbol ?
If it is the latter, what is the main functor of this term ?
The principal functor of (a, b) is (',')/2.
That is in some ways an accident; in DEC-10 and Quintus
Prolog the principal functor of (a | b) was (';')/2.
Thank you for the interesting and clear answer.

Kuniaki
Ulrich Neumerkel
2011-06-28 09:26:57 UTC
Permalink
Post by Kuniaki Mukai
I am ashamed to have little attention to the syntax of (SWI-)Prolog
so far long. I should change my attitude.
Now I see that the comma is not an atom. But could you tell me
what is the comma in the following.
(a, b)
Is this comma an atom ? Or is it not an atom but a punctuation
symbol ? If it is the latter, what is the main functor of this term ?
Thank you for answering this, which seems to be a FAQ.
If you want to understand the complete syntax, you definitely need the
standard in front of you. Please read the following for how to obtain
it:

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/

The comma has many special roles: separating arguments in argument
lists and lists like f(a,b) or [a,b] and being an infix operator. In
the case of (a, b) it is an infix operator (',')/2.

There is another similar special symbol - the bar. Similar to the
comma, it is not an atom. It is a head tail separator as in [A|As]
and an infix operator ('|')/2 provided an appropriate operator
declarations is present. For this, please refer to:

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#C2
Kuniaki Mukai
2011-06-28 13:25:30 UTC
Permalink
Post by Ulrich Neumerkel
If you want to understand the complete syntax, you definitely need the
standard in front of you. Please read the following for how to obtain
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/
The comma has many special roles: separating arguments in argument
lists and lists like f(a,b) or [a,b] and being an infix operator. In
the case of (a, b) it is an infix operator (',')/2.
There is another similar special symbol - the bar. Similar to the
comma, it is not an atom. It is a head tail separator as in [A|As]
and an infix operator ('|')/2 provided an appropriate operator
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#C2
There are a lot of definitive stuff there. Thank you.

Kuniaki
Stassa Patsantzis
2011-06-28 16:52:15 UTC
Permalink
Dear Feliks,

Hi and thank you very much for your reply (and also thank you everyone else who replied) and sorry for taking so long to come back to you. What you suggest is indeed what I was looking for. I hope you like ice cream because now I owe you some :)

As usual I feel a bit thick because this is such an obvious solution. I keep forgetting that DCG notation is just normal Prolog, so I treat it as if it's some sort of arcane magic. I actually have some "auxiliary" nonterminals in my code, but it didn't occur to me to pass a compound term as an argument, or write a recursive grammar rule. I shall now smack myself... :smack:

Using your code, I made it work like this:

integer( [ Var | Vars ] ) -->
    [ integer, Var ],
    rest_of_declaration( Vars ),
    [ ';' ].

rest_of_declaration( [] ) -->  [] .

rest_of_declaration( [ Var | Vars ] ) -->
    [ ',', Var ],
    rest_of_declaration( Vars ).


By the way, all this started because I was "porting" (sorry) some code from LPA Prolog to Swi, and in LPA this is correct syntax:

lhside, [implied] --> rhside.

- which will cause the "implied" token to be ommited, more or less like in Feliks' code. Obviously this is not supported in SWI so my code broke, but then I expected it to since I 've read the part in the Swi manual where it says there is no ISO standard for DCG's. So I was wondering- does any one know why not? It seems strange, considering Prolog was created for language processing in the first place. On the other hand, it's also strange that in my one-year module working with Prolog at uni, we didn't cover DCG's and I understand that's the way it is in most courses. Possibly that has something to do with standardisation?

Also- where would be a good place to start in Swi's sources should one want to add such functionality? I had a look in pl\boot\dcg.pl and it looks like dcg_translate_rule/2 is the predicate that handles, well, dcg rule translation?

Obviously the last two questions aren't addressed to Feliks alone!

Regards,
- Stassa

--- On Mon, 27/6/11, Feliks Kluzniak <***@utdallas.edu> wrote:

From: Feliks Kluzniak <***@utdallas.edu>
Subject: RE: [SWIPL] How to hide implied tokens in DCG rules?
To: "'Stassa Patsantzis'" <***@yahoo.com>, swi-***@lists.iai.uni-bonn.de
Date: Monday, 27 June, 2011, 12:11

Hi Stassa,

It would seem to me that for the particular example of type checking it
might be more convenient to separate the parser from the type checker.  The
conventional approach is to make the parser produce a convenient abstract
syntax tree, and then to make subsequent passes (like type checking) operate
on (and perhaps modify) that tree.

So, for example,

integer( integer_declarations[ Var | Vars ] ) --> 
    [ integer, Var ], 
    rest_of_declaration( Vars ),
    [ (;) ].


rest_of_declaration( [ Var | Vars ] ) -->
    [ (,) ],
    !,
    rest_of_declaration( Vars ).

rest_of_declaration( [] ) -->  [] .

The technique of using an auxiliary nonterminal symbol for optional or
iterated stuff is also a standard one.

Is this relevant to your questions?

-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Stassa Patsantzis
Sent: Sunday, June 26, 2011 11:35 AM
To: swi-***@lists.iai.uni-bonn.de
Subject: [SWIPL] How to hide implied tokens in DCG rules?



--- On Sun, 26/6/11, Stassa Patsantzis <***@yahoo.com> wrote:

From: Stassa Patsantzis <***@yahoo.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Carlo Capelli" <***@gmail.com>
Date: Sunday, 26 June, 2011, 12:34

    Hi Carlo!

    Thank you for replying. It would indeed be very simple to use a
disjunction like you suggest, unfortunately, ike I said, I can't :)
   
    The reason I can't do it is because I need to do some type-checking. A
different example would be declaring multiple variables using a single type
word, say:
   
        integer x, y;
   
    - instead of:
   
        integer x;
        integer y;
       
    The type-checking is done by a rule like:
   
        integer(X) --> [integer, X].
   
    So I need a rule of the form:
   
        integer(X,Y) --> integer(X), [','], integer(Y).
       
    Only of course this will parse as:
   
   
    integer x, integer y;
       
    So I need to skip the second instance of "integer" somehow, but still
let integer(X,Y) parse. That's why I say it needs to be "implied".
           
    Sorry -this still isn't a full example, but a) I'm trying to figure out
the general case and b) a literal example would be a bit too involved, I
fear.
   
    Thanks again and have a great Sunday afternoon!
    - Stassa

--- On Sun, 26/6/11, Carlo Capelli <***@gmail.com> wrote:

From: Carlo Capelli <***@gmail.com>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis"
<***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Sunday, 26 June, 2011, 7:34

2011/6/25 Stassa Patsantzis <***@yahoo.com>

Hi all!



I'm trying to find a way to hide implied tokens while parsing (or
generating) a phrase with DCGs. Here's what I mean. I want to parse, eg,
these two phrases:

   

        "I like ice cream and I like jam".

        "I like ice cream and jam"

       

- using the same DCG rule. The second "I like" is implied, but it's not
wrong to use it.

   

Because of everything else that's going on in the ruleset, it's a bit
complicated to just do, say:



   like(X,Y) --> ['I', 'like', X, and], (['I', 'like', Y]; [Y]).

       

It would be very convenient if I could hide tokens, like I say above. So, is
there a way to do this?

     

- Thanks,

Stassa


a very simple change to your DCG could do:



like(X,Y) -->

    [A, B, X, and], ([A, B, Y]; [Y]), {(A='I';A=you), B=like}.



Anyway, DCGs usually require you to make the patterns explicit.



bye Carlo


 
-------------- next part --------------

HTML attachment scrubbed and removed

_______________________________________________

SWI-Prolog mailing list

SWI-***@lists.iai.uni-bonn.de

https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog



-------------- next part --------------
HTML attachment scrubbed and removed
_______________________________________________
SWI-Prolog mailing list
SWI-***@lists.iai.uni-bonn.de
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog

-------------- next part --------------
HTML attachment scrubbed and removed
Ulrich Neumerkel
2011-06-28 17:00:41 UTC
Permalink
Post by Stassa Patsantzis
integer( [ Var | Vars ] ) -->
[ integer, Var ],
rest_of_declaration( Vars ),
[ ';' ].
No need to quote the ;! Simply write [;].

Only , and | are very special.

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_assessment#31
Stassa Patsantzis
2011-06-28 17:17:42 UTC
Permalink
Ah, you're right.



Hm, that's a useful link. I missed it before. Thank you Ulrich!



-Stassa

--- On Tue, 28/6/11, Ulrich Neumerkel <***@complang.tuwien.ac.at> wrote:

From: Ulrich Neumerkel <***@complang.tuwien.ac.at>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: ***@utdallas.edu, ***@yahoo.com, swi-***@lists.iai.uni-bonn.de
Date: Tuesday, 28 June, 2011, 13:00
Post by Stassa Patsantzis
integer( [ Var | Vars ] ) -->
    [ integer, Var ],
    rest_of_declaration( Vars ),
    [ ';' ].
No need to quote the ;! Simply write [;].

Only , and | are very special.

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_assessment#31
-------------- next part --------------
HTML attachment scrubbed and removed
Paulo Moura
2011-06-28 19:07:03 UTC
Permalink
Post by Stassa Patsantzis
lhside, [implied] --> rhside.
- which will cause the "implied" token to be ommited, more or less like in Feliks' code. Obviously this is not supported in SWI so my code broke, ...
Hum? The above syntax *is* supported in SWI-Prolog (and in other Prolog compilers that support DCGs; Logtalk also supports it). It is also included in the DCGs standardization proposal (at least in the last revision with me as editor):

-----
7.14.3 Push-back lists
A push-back list is a proper list of terminals on the left-hand side of a grammar rule (see 3.14). A push-back list contains terminals that would be asserted in the input terminal list after the terminals consumed by the successful application of the grammar rule.

7.14.3.1 Examples
For example, assume that we need rules to look-ahead one or two tokens that would be consumed next. This could be easily accomplished by the following two grammar rules:

look_ahead(X), [X] --> [X].
look_ahead(X, Y), [X,Y] --> [X,Y].

When used for parsing, procedurally, these grammar rules can be interpreted as, respectively, consuming, and then restoring, one or two terminals.
-----

What problems did you found when trying to use it?

Cheers,

Paulo


-----------------------------------------------------------------
Paulo Jorge Lopes de Moura, PhD
Assistant Professor
Dep. of Computer Science, University of Beira Interior
6201-001 Covilhã, Portugal

Office 3.18 Ext. 3276
Phone: +351 275319891 Fax: +351 275319899
Email: <mailto:***@di.ubi.pt>

Home page: <http://www.di.ubi.pt/~pmoura>
Research: <http://logtalk.org/> Blog: <http://blog.logtalk.org/>
-----------------------------------------------------------------
Stassa Patsantzis
2011-07-03 12:26:01 UTC
Permalink
Post by Paulo Moura
What problems did you found when trying to use it?
Cheers,
Paulo
Ooops! Sorry Paulo, it seems I've missed a bunch of emails to the list (and also at least half a thread). Indeed I had no idea that this syntax is supported in Swi, or that it has a name! It's not in the Swi documentation and the LPA documentation doesn't call it a "push-back list", or, indeed, anything (so google wasn't my friend).

The problem I've had with it, well, here's the following snippet, this time taken verbatim from my code (I'm compiling it separately from the rest of my program, just to make sure):  

    deals_or(Z), [target] --> target(Z),
        { player(Z) }.

    target(X) --> ([target];['Target']), player(X).

    player(X) --> [player], {player(X)}.

    player('us').
    player('them').

In LPA, the query:

    | ?- phrase(deals_or(X), Y).

- finds the following bindings (as intended):

    X = us ,
    Y = [player] ;

    X = them ,
    Y = [player] ;

    no

While in Swi it simply fails. For reference, the full sentence I'm trying to parse is (sentences of the form):

"Lightning Bolt deals 3 damage to target creature or player".

Where "target X or Y" is basically a type declaration in the language, equivalent to "integer x, y;" and deals_or/1 is an auxiliary non-terminal of a messy rule that I'd rather not quote here (I was in a hurry). It should work on its own of course.

This is strange because I also tried a pbl example from LPA's documentation and it works the same in Swi. This means either that the incompatibility must be somewhere else in my code, or that there is some very subtle difference in the implementation of pbl's in the two compilers. Anyway, good news Paulo, at least I know where to look. So thanks again- I'll keep digging.

Have a beautiful Sunday afternoon!

Regards,
Stassa
-------------- next part --------------
HTML attachment scrubbed and removed
Paulo Moura
2011-07-03 15:35:34 UTC
Permalink
Post by Stassa Patsantzis
Post by Paulo Moura
What problems did you found when trying to use it?
Cheers,
Paulo
Ooops! Sorry Paulo, it seems I've missed a bunch of emails to the list (and also at least half a thread). Indeed I had no idea that this syntax is supported in Swi, or that it has a name! It's not in the Swi documentation and the LPA documentation doesn't call it a "push-back list", or, indeed, anything (so google wasn't my friend).
deals_or(Z), [target] --> target(Z),
{ player(Z) }.
target(X) --> ([target];['Target']), player(X).
player(X) --> [player], {player(X)}.
player('us').
player('them').
| ?- phrase(deals_or(X), Y).
X = us ,
Y = [player] ;
X = them ,
Y = [player] ;
no
"Lightning Bolt deals 3 damage to target creature or player".
Where "target X or Y" is basically a type declaration in the language, equivalent to "integer x, y;" and deals_or/1 is an auxiliary non-terminal of a messy rule that I'd rather not quote here (I was in a hurry). It should work on its own of course.
This is strange because I also tried a pbl example from LPA's documentation and it works the same in Swi. This means either that the incompatibility must be somewhere else in my code, or that there is some very subtle difference in the implementation of pbl's in the two compilers. Anyway, good news Paulo, at least I know where to look. So thanks again- I'll keep digging.
If you use instead phrase/3 you get (tested on SWI-Prolog and Logtalk):

?- phrase(deals_or(X), Input, Rest).
X = us,
Input = [target, player|_G26],
Rest = [target|_G26] ;
X = them,
Input = [target, player|_G26],
Rest = [target|_G26] ;
X = us,
Input = ['Target', player|_G26],
Rest = [target|_G26] ;
X = them,
Input = ['Target', player|_G26],
Rest = [target|_G26].

The de fact standard definition of phrase/2 is:

phrase(GrammarRuleBody, Input) :-
phrase(GrammarRuleBody, Input, []).

This explains why you don't get any answer to the goal phrase(deals_or(X), Y) as there is no solution where Rest is the empty list. It might be that LPA Prolog is using a different definition for phrase/2?

Cheers,

Paulo


-----------------------------------------------------------------
Paulo Jorge Lopes de Moura, PhD
Assistant Professor
Dep. of Computer Science, University of Beira Interior
6201-001 Covilhã, Portugal

Office 3.18 Ext. 3276
Phone: +351 275319891 Fax: +351 275319899
Email: <mailto:***@di.ubi.pt>

Home page: <http://www.di.ubi.pt/~pmoura>
Research: <http://logtalk.org/> Blog: <http://blog.logtalk.org/>
-----------------------------------------------------------------
Stassa Patsantzis
2011-07-03 17:03:04 UTC
Permalink
Paulo,
Post by Paulo Moura
phrase(GrammarRuleBody, Input) :-
    phrase(GrammarRuleBody, Input, []).
Oooh! I see now... I've been tracing my grammar for the last couple of hours and I couldn't figure out why phrase/2 (not -/3) seemed to expect a "[ ]" at the end of target/2... To be honest, I haven't really grokked DCG's yet, all I know about phrase/2 & /3 is from Clocksin & Mellish so if you could recommend a more complete text I'd be grateful.
Post by Paulo Moura
This explains why you don't get any answer to the goal phrase(deals_or(X), Y)
as there is no solution where Rest is the empty list. It might be that LPA Prolog
is using a different definition for phrase/2?
Unfortunately, LPA is closed source and their definition of phrase/2 and phrase/3 seems to be in object code (I can't find a Prolog source). Also, DCG's are not traceable in their editor so I've developped my grammar using the "trial and error (mostly error)" method. Hence why I'm so stumped by how it all works.

I'll have to do some more work to get my code as I want it on Swi, but for the moment I want it to just run on Swi, and I think I'm getting there. Thanks for your help, Paulo and everyone else. I really appreciate it. :)

- Regards,
Stassa.

--- On Sun, 3/7/11, Paulo Moura <***@di.ubi.pt> wrote:

From: Paulo Moura <***@di.ubi.pt>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Prolog mailing list" <swi-***@lists.iai.uni-bonn.de>
Date: Sunday, 3 July, 2011, 11:35
Post by Paulo Moura
Post by Paulo Moura
What problems did you found when trying to use it?
Cheers,
Paulo
Ooops! Sorry Paulo, it seems I've missed a bunch of emails to the list (and also at least half a thread). Indeed I had no idea that this syntax is supported in Swi, or that it has a name! It's not in the Swi documentation and the LPA documentation doesn't call it a "push-back list", or, indeed, anything (so google wasn't my friend).
The problem I've had with it, well, here's the following snippet, this time taken verbatim from my code (I'm compiling it separately from the rest of my program, just to make sure): 
     deals_or(Z), [target] --> target(Z),
         { player(Z) }.
     target(X) --> ([target];['Target']), player(X).
     player(X) --> [player], {player(X)}.
     player('us').
     player('them').
     | ?- phrase(deals_or(X), Y).
     X = us ,
     Y = [player] ;
     X = them ,
     Y = [player] ;
     no
"Lightning Bolt deals 3 damage to target creature or player".
Where "target X or Y" is basically a type declaration in the language, equivalent to "integer x, y;" and deals_or/1 is an auxiliary non-terminal of a messy rule that I'd rather not quote here (I was in a hurry). It should work on its own of course.
This is strange because I also tried a pbl example from LPA's documentation and it works the same in Swi. This means either that the incompatibility must be somewhere else in my code, or that there is some very subtle difference in the implementation of pbl's in the two compilers. Anyway, good news Paulo, at least I know where to look. So thanks again- I'll keep digging.
If you use instead phrase/3 you get (tested on SWI-Prolog and Logtalk):

?- phrase(deals_or(X), Input, Rest).
X = us,
Input = [target, player|_G26],
Rest = [target|_G26] ;
X = them,
Input = [target, player|_G26],
Rest = [target|_G26] ;
X = us,
Input = ['Target', player|_G26],
Rest = [target|_G26] ;
X = them,
Input = ['Target', player|_G26],
Rest = [target|_G26].

The de fact standard definition of phrase/2 is:

phrase(GrammarRuleBody, Input) :-
    phrase(GrammarRuleBody, Input, []).

This explains why you don't get any answer to the goal phrase(deals_or(X), Y) as there is no solution where Rest is the empty list. It might be that LPA Prolog is using a different definition for phrase/2?

Cheers,

Paulo


-----------------------------------------------------------------
Paulo Jorge Lopes de Moura, PhD
Assistant Professor
Dep. of Computer Science, University of Beira Interior
6201-001 Covilhã, Portugal

Office 3.18  Ext. 3276
Phone: +351 275319891 Fax: +351 275319899
Email: <mailto:***@di.ubi.pt>

Home page: <http://www.di.ubi.pt/~pmoura>
Research:  <http://logtalk.org/> Blog: <http://blog.logtalk.org/>
-----------------------------------------------------------------

-------------- next part --------------
HTML attachment scrubbed and removed
Richard O'Keefe
2011-07-04 23:50:06 UTC
Permalink
Post by Stassa Patsantzis
Post by Paulo Moura
What problems did you found when trying to use it?
Cheers,
Paulo
Ooops! Sorry Paulo, it seems I've missed a bunch of emails to the list (and also at least half a thread). Indeed I had no idea that this syntax is supported in Swi, or that it has a name! It's not in the Swi documentation and the LPA documentation doesn't call it a "push-back list", or, indeed, anything (so google wasn't my friend).
deals_or(Z), [target] --> target(Z),
{ player(Z) }.
target(X) --> ([target];['Target']), player(X).
player(X) --> [player], {player(X)}.
player('us').
player('them').
Let me show you one valid translation here, done manually,
assuming everything is pure (so we can use a more intuitive
direct translation).

deals_or(Z, S0, [target|S1]) :-
target(Z, S0, S1),
player(Z).

target(X, S0, S) :-
( S0 = [target|S1]
; S0 = ['Target'|S1]
),
player(X, S1, S).

player(X, [player|S], S) :-
player(X).

player(us).
player(them).

And let's see a call to that:

?- deals_or(X, Y, []).

It is immediately obvious that this *cannot* have any solutions,
because there is no way whatever that [] can be made to match [target|S1].

Never mind the exact translation. It's intuitively obvious that
a grammar rule that explicitly pushes something back into the input
CANNOT leave the input empty!

If we try the query

?- deals_or(X, S0, S).

we get the answers

(X = us ; X = them),
S0 = [T,player|R],
(T = target ; T = 'Target'),
S = [target|R].

Let's see what translation we actually get in SWI Prolog:

deals_or(Z, S0, S) :-
target(Z, S0, S1),
player(Z),
S2 = S1,
S = [target|S2]. % This is where the pushback happens

target(X, S0, S) :-
( S0 = [target|S1]
; S0 = ['Target'|S1]
),
player(X, S1, S).

player(us).
player(them).

player(X, [player|S1], S) :-
player(X),
S = S1.

This is a perfectly good translation.
gprolog produces

player(X, [player|S], S) :-
player(X).

deals_or(Z, S0, S) :-
target(Z, S0, S1),
player(Z),
S = [target|S1].


It is also _exactly_ the translation produced by gprolog.
Ciao produces

deals_or(Z. S0, S) :-
'C'(S, target, S1), % equivalent to S = [target|S1]
target(Z, S0, S1),
player(Z).

which is OK for pure code but was abandoned in other Prologs years ago
because of the problems it has with impure code. However, it makes no
difference here. In this context, it produces exactly the same *results*
as SWI Prolog and GProlog.

Yap produces

player(us).
player(them).

player(X, S0, S) :-
'C'(S0, player, S), % equivalent to S0 = [player|S]
player(A).

target(X, S0, S) :-
( 'C'(S0, target, S1
; 'C'(S0, 'Target', S1)
),
player(X, S1, S).

deals_or(Z, S0, S) :-
target(Z, S0, S1),
player(Z),
'C'(S, target, S1). % pushback here

and once again

| ?- phrase(deals_or(X), Y).

just quietly fails.
Post by Stassa Patsantzis
| ?- phrase(deals_or(X), Y).
X = us ,
Y = [player] ;
X = them ,
Y = [player] ;
no
Then LPA is alone in this, because DEC-10 Prolog, C Prolog, and Quintus Prolog would have
produced, and SICStus Prolog does produce, exactly the same results here as SWI Prolog,
YAP, ciao, and GProlog.

The simplest bug in LPA that could explain this would be if

phrase(NT, S0) :- phrase(NT, S0, _).

instead of the correct

phrase(NT, S0) :- phrase(NT, S0, []).
Stassa Patsantzis
2011-07-05 19:47:20 UTC
Permalink
Richard,

hi and thank you for the very involved reply. Thanks to it and by the power of a million monkeys on typewriters, I managed to produce some code that does what I want it to do:


    deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or], deals_or(A).

    deals_or(X) --> skipping(target), target(X).

    skipping(X), [X] --> [].
    skipping(_) --> [].

    target(X) --> [target], player(X).
    target(X) --> [target], creature(X).
   
    player(X) --> {isa_player(X)}, [player].
    isa_player('us').
    isa_player('them').

    creature(X) --> {isa_creature(X)}, [creature].
    isa_creature('Goblin').
    isa_creature('Demon').
   
So now I can ask the query:

    phrase(deals(X,Y,Z,A), ['Lightning Bolt',deals,3,damage,to,target,creature,or,player]).

- and get back:

    X = 'Lightning Bolt',
    Y = 3,
    Z = 'Goblin',
    A = us ;   
    ...   
    Z = 'Goblin',
    A = them ;
    ...   
    Z = 'Demon',
    A = us ;   
    ...
    Z = 'Demon',
    A = them ;   
    false.
   
- which is exactly correct.

So my problem was that a push-back list on the left hand side of a rule "pushes" a token beyond what's on its right hand side, whereas I was trying to make it affect a token _before_ the input. Somehow I managed to do that in LPA Prolog, and I doubt it's meant to do that, I must have broken something. Otherwise I reckon I'd be having many more problems with my grammar. In any case my grammar was a bit bloated so I'll have to rewrite it from scratch anyway. I guess we'll never know what caused that fun little bug...

Incidentally, I also, now, understand the meaning of the push-back list example in the DCG standardisation proposal, which didn't make sense to me before! Indeed I am enlightened by basking in the glow of masters! ^_^

Thank you very much, Richard and Paulo and everyone else who helped, this had stumped me no end.

Take care,
-Stassa

--- On Mon, 4/7/11, Richard O'Keefe <***@cs.otago.ac.nz> wrote:

From: Richard O'Keefe <***@cs.otago.ac.nz>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis" <***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Monday, 4 July, 2011, 19:50
Post by Stassa Patsantzis
Post by Paulo Moura
What problems did you found when trying to use it?
Cheers,
Paulo
Ooops! Sorry Paulo, it seems I've missed a bunch of emails to the list (and also at least half a thread). Indeed I had no idea that this syntax is supported in Swi, or that it has a name! It's not in the Swi documentation and the LPA documentation doesn't call it a "push-back list", or, indeed, anything (so google wasn't my friend).
The problem I've had with it, well, here's the following snippet, this time taken verbatim from my code (I'm compiling it separately from the rest of my program, just to make sure): 
     deals_or(Z), [target] --> target(Z),
         { player(Z) }.
     target(X) --> ([target];['Target']), player(X).
     player(X) --> [player], {player(X)}.
     player('us').
     player('them').
Let me show you one valid translation here, done manually,
assuming everything is pure (so we can use a more intuitive
direct translation).

    deals_or(Z, S0, [target|S1]) :-
        target(Z, S0, S1),
        player(Z).

    target(X, S0, S) :-
        ( S0 = [target|S1]
        ; S0 = ['Target'|S1]
        ),
        player(X, S1, S).

    player(X, [player|S], S) :-
        player(X).

    player(us).
    player(them).

And let's see a call to that:

    ?- deals_or(X, Y, []).

It is immediately obvious that this *cannot* have any solutions,
because there is no way whatever that [] can be made to match [target|S1].

Never mind the exact translation.  It's intuitively obvious that
a grammar rule that explicitly pushes something back into the input
CANNOT leave the input empty!

If we try the query

    ?- deals_or(X, S0, S).

we get the answers

    (X = us ; X = them),
    S0 = [T,player|R],
    (T = target ; T = 'Target'),
    S = [target|R].

Let's see what translation we actually get in SWI Prolog:

deals_or(Z, S0, S) :-
    target(Z, S0, S1),
    player(Z),
    S2 = S1,
    S = [target|S2].         % This is where the pushback happens

target(X, S0, S) :-
    (   S0 = [target|S1]
    ;   S0 = ['Target'|S1]
    ),
    player(X, S1, S).

player(us).
player(them).

player(X, [player|S1], S) :-
    player(X),
    S = S1.

This is a perfectly good translation.
gprolog produces

player(X, [player|S], S) :-
    player(X).

deals_or(Z, S0, S) :-
    target(Z, S0, S1),
    player(Z),
    S = [target|S1].


It is also _exactly_ the translation produced by gprolog.
Ciao produces

deals_or(Z. S0, S) :-
    'C'(S, target, S1),  % equivalent to S = [target|S1]
    target(Z, S0, S1),
    player(Z).

which is OK for pure code but was abandoned in other Prologs years ago
because of the problems it has with impure code.  However, it makes no
difference here.  In this context, it produces exactly the same *results*
as SWI Prolog and GProlog.

Yap produces

player(us).
player(them).

player(X, S0, S) :-
   'C'(S0, player, S),  % equivalent to S0 = [player|S]
   player(A).

target(X, S0, S) :-
   (  'C'(S0, target, S1
   ;  'C'(S0, 'Target', S1)
   ),
   player(X, S1, S).

deals_or(Z, S0, S) :-
   target(Z, S0, S1),
   player(Z),
   'C'(S, target, S1). % pushback here

and once again

    | ?- phrase(deals_or(X), Y).

just quietly fails.
Post by Stassa Patsantzis
     | ?- phrase(deals_or(X), Y).
     X = us ,
     Y = [player] ;
     X = them ,
     Y = [player] ;
     no
Then LPA is alone in this, because DEC-10 Prolog, C Prolog, and Quintus Prolog would have
produced, and SICStus Prolog does produce, exactly the same results here as SWI Prolog,
YAP, ciao, and GProlog.

The simplest bug in LPA that could explain this would be if

    phrase(NT, S0) :- phrase(NT, S0, _).

instead of the correct

    phrase(NT, S0) :- phrase(NT, S0, []).


-------------- next part --------------
HTML attachment scrubbed and removed
Richard O'Keefe
2011-07-06 00:18:29 UTC
Permalink
Post by Stassa Patsantzis
deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or], deals_or(A).
deals_or(X) --> skipping(target), target(X).
skipping(X), [X] --> [].
skipping(_) --> [].
I am confused here by the words. skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
Post by Stassa Patsantzis
target(X) --> [target], player(X).
target(X) --> [target], creature(X).
player(X) --> {isa_player(X)}, [player].
isa_player('us').
isa_player('them').
creature(X) --> {isa_creature(X)}, [creature].
isa_creature('Goblin').
isa_creature('Demon').
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*. I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.

deals(Actor, Amount, [Target1,Target2]) -->
[Actor, deals, Amount, damage, to, target],
simple_target(Target1),
[or], optional(target),
simple_target(Target2).

optional(X) --> [X].
optional(_) --> [].

simple_target(Target) --> player(Target).
simple_target(Target) --> creature(Target).

Push-back lists are there to handle movement.
For example,
is John sick
could be parsed by
sentence --> np, vp.

np, [Aux] --> aux(Aux), noun.
np --> noun.

vp --> aux(_), verb.
vp --> verb.

where the first rule for np picks up the moved auxiliary and then
puts it back after the "real" noun phrase.
Stassa Patsantzis
2011-07-06 13:07:07 UTC
Permalink
Richard,

Hi again. I can't believe the time you're putting into this and I am very grateful.
I am confused here by the words.  skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
Indeed, an unfortunate choice of functor name and I thought I'd better rename it to something like "implied". The intention is to mark a token as implied, as in "target creature or (target) player", where the second "target" can be left out.
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*. 
Ah, it's not exactly optional- it's basically a type declaration. Without getting into the particulars of the language too much, a game entity is a target only if the word "target" is in the text that refers to it, even if it's only implied. So "deals x damage to target y" targets "x", but "deals x damage to y" doesn't target anything. Both phrases are valid in the language, so I need to know when I have which. The example is such a pain because "target" is implied. I can't just parse it the way you say or I'll catch cases where target is absent and not implied. I know because I started with a less strict definition and it wasn't enough.

For example, the query:

?- phrase(simple_target(X), Y).
X = us,
Y = [player] ;

- is not right because "player" is not a target- "target player" is. I use the grammar to collect targets and present them to the players, so I need the strict definition.
I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.
My greatest strength is to create confusion with the way I present my questions. The last bit of code I sent was again just a sketch. In the full application I need to pass back a reference to the target. This is the actual code I use to target creatures, or objects of any type (but, note: not players):

    target(X,Y) --> ([target];['Target']), [Y], 

        {zone('Battlefield', Cards),

         X = object(Name -_Id,_State),

        member(X, Cards),  

        check_type(Name, _, [T], _) , 

        invert_case(Y, T)}.

where the creature is an object/2 term in the Cards list.

Queries using this may take the form, eg:

    | ?- phrase(target(X,Y), Z).

    X = object('Goblin Balloon Brigade'-1,[]) ,

    Y = creature ,

    Z = [target,creature]

So basically, the input includes the reference to the object/2 term. It's simpler for players because those are not actually of the type "object" (bad choice, but it wasn't mine). There are also only two players, so it's no big deal to find them and target them.

Sorry for posting full code one moment and only sketches the other! I know this can create confusion, but that's the fault of Prolog, for being so good at letting you take bits out of a context without breaking too much of the meaning...

Also, my grammar is a big fat mess that I wrote with a strict deadline looming. It does not look good. I'll have to rewrite most of it because I'd like to open-source my code (there may be some interest to it though Prolog puts gamers off) and as it is now it is a little embarrassing.

Again, I must say I'm very grateful for your continued interest and support, Richard. Thanks, really.
 
Regards,
- Stassa

--- On Tue, 5/7/11, Richard O'Keefe <***@cs.otago.ac.nz> wrote:

From: Richard O'Keefe <***@cs.otago.ac.nz>
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
To: "Stassa Patsantzis" <***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Tuesday, 5 July, 2011, 20:18
     deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or], deals_or(A).
     deals_or(X) --> skipping(target), target(X).
     skipping(X), [X] --> [].
     skipping(_) --> [].
I am confused here by the words.  skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
     target(X) --> [target], player(X).
     target(X) --> [target], creature(X).
     
     player(X) --> {isa_player(X)}, [player].
     isa_player('us').
     isa_player('them').
     creature(X) --> {isa_creature(X)}, [creature].
     isa_creature('Goblin').
     isa_creature('Demon').
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*.  I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.

    deals(Actor, Amount, [Target1,Target2]) -->
        [Actor, deals, Amount, damage, to, target],
        simple_target(Target1),
        [or], optional(target),
        simple_target(Target2).

    optional(X) --> [X].
    optional(_) --> [].

    simple_target(Target) --> player(Target).
    simple_target(Target) --> creature(Target).

Push-back lists are there to handle movement.
For example,
    is John sick
could be parsed by
    sentence --> np, vp.

    np, [Aux] --> aux(Aux), noun.
    np        -->           noun.

    vp --> aux(_), verb.
    vp --> verb.

where the first rule for np picks up the moved auxiliary and then
puts it back after the "real" noun phrase.


-------------- next part --------------
HTML attachment scrubbed and removed
Feliks Kluzniak
2011-07-06 16:06:15 UTC
Permalink
Post by Richard O'Keefe
Push-back lists are there to handle movement.
Yes, but lest confusion arise we should point out that they can be used for
other purposes, too.

The most obvious, of course, is to provide lookahead (and this might be
considered a special case of movement, where the displacement distance is
zero):

exp --> [ '(' ], names( ')' ), [ ')' ] .

names( Terminator ), [ Terminator ] -->
[ Termninator ], !.

names( Terminator ) -->
name, !, names( Terminator ) .

names( Terminator ), [ What ] -->
[ What ],
% What \= Terminator,
{ write( 'Expected name or "' ),
write( Terminator ),
write( '", not "' ),
write( What ), write( '"' ), nl
}.

(I omit the other arguments that would normally be there: we seldom need
just a yes/no parser. I apologize for any minor mistakes: I did not test
this.)


But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all. And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!

If memory serves, the "non-push-back mode" is how the feature was used in
some of the original examples for Colmearauer's Metamorphosis Grammars. In
my mind the term "metamorphosis" was associated with the fact that the
analyzed string could be changed into something else while the analysis was
going on. Since there are also the arguments, and since a suitably-written
grammar can also be used for synthesis, the whole mechanism truly impressed
with its generality and expressive power.

So-called DCGs are, of course, a very slightly simplified version of
Metamorphosis Grammars. The nature of the simplification escapes me at the
moment.

Regards,
-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Richard O'Keefe
Sent: Tuesday, July 05, 2011 7:18 PM
To: Stassa Patsantzis
Cc: swi-***@lists.iai.uni-bonn.de
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
Post by Richard O'Keefe
deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or], deals_or(A).
deals_or(X) --> skipping(target), target(X).
skipping(X), [X] --> [].
skipping(_) --> [].
I am confused here by the words. skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
Post by Richard O'Keefe
target(X) --> [target], player(X).
target(X) --> [target], creature(X).
player(X) --> {isa_player(X)}, [player].
isa_player('us').
isa_player('them').
creature(X) --> {isa_creature(X)}, [creature].
isa_creature('Goblin').
isa_creature('Demon').
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*. I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.

deals(Actor, Amount, [Target1,Target2]) -->
[Actor, deals, Amount, damage, to, target],
simple_target(Target1),
[or], optional(target),
simple_target(Target2).

optional(X) --> [X].
optional(_) --> [].

simple_target(Target) --> player(Target).
simple_target(Target) --> creature(Target).

Push-back lists are there to handle movement.
For example,
is John sick
could be parsed by
sentence --> np, vp.

np, [Aux] --> aux(Aux), noun.
np --> noun.

vp --> aux(_), verb.
vp --> verb.

where the first rule for np picks up the moved auxiliary and then
puts it back after the "real" noun phrase.
Richard O'Keefe
2011-07-07 00:23:18 UTC
Permalink
Post by Feliks Kluzniak
Post by Richard O'Keefe
Push-back lists are there to handle movement.
Yes, but lest confusion arise we should point out that they can be used for
other purposes, too.
Since the OP *was* using push-back lists for another purpose,
I thought that went without saying.

Lookahead can be very simply handled using

peek(Token, Tokens, Tokens) :- Tokens = [Token|_].

What *should* be mentioned is that there are old and good arguments
that making use of push-backs can change the language that is accepted
in unintended ways: the parser will accept push-back tokens that were
not in fact pushed back.
Post by Feliks Kluzniak
But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all. And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!
"push-back" does not mean that something is *returning* to the token stream,
it means that something is being pushed backwards against the normal flow.
The classic use of push-back lists for movement never did push back the
original tokens but something closer to an AST node.
Post by Feliks Kluzniak
So-called DCGs are, of course, a very slightly simplified version of
Metamorphosis Grammars. The nature of the simplification escapes me at the
moment.
Colmerauer's paper defining Metamorphosis Grammars is on line at
http://www.springerlink.com/content/58188166u5723547/fulltext.pdf
but you need a Springer subscription to read it.

Definition : A metamorphosis grammar G is defined by a quintuplet
{F,VT,VN,VS,->}
(1) F is a set of functional symbols csntaining "." and "nil"
(2) VT is a vocabulary said to be terminal with VT c H [F]
(3) VN is a vocabulary said to be non-terminal with VN c H [F].
We suppose that VN \cap VT = \empty
and write V = VT \cup VN
(4) VS c VN . The elements of VS are termed starting non-terminals.
(5) -> is a re-writing relation on V* with the restriction that
x -> y implies x ~= nil

Let -> be a binary relation between the elements of H and let V be
a vocabulary without variables, i.e. V c H. The relation -> is said
to be a re-writing relation on V* iff
for each x,y \in H x -> y implies x,y \in V*

Definition : A metamorphosis grammar is said to be in normal form
if it satisfies the restriction ax -> y implies a \in VN and x \in VT*

The key point here is that the left hand side of an MG rule can be
an arbitrary non-empty sequence of terminals and non-terminals.

It appears that "DCG" is just a shorthand for "metamorphosis grammar
in normal form".

Colmerauer presented an algorithm for converting any MG to normal form
and devised the standard translation of DCGs to Horn clauses (although
he added the extra "sequence position" arguments at the front).

Fernando Pereira's eXtraposition Grammars were clearly influenced by
MGs but are neither a special case of MGs nor a generalisation of them.
Feliks Kluzniak
2011-07-07 15:32:54 UTC
Permalink
Post by Richard O'Keefe
Post by Feliks Kluzniak
And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!
"push-back" does not mean that something is *returning* to the token stream,
it means that something is being pushed backwards against the normal flow.
Hmm, I wouldn't have thought of that. I must yield to your judgment, since
you are a native speaker. (I must confess I don't quite understand "normal
flow" in this context, but that's a minor point.)

I (and presumably others) appreciate your providing the definition and
clarification about MGs. (My library is slowly rotting in some far-away
storage space...).

-- Feliks




-----Original Message-----
From: Richard O'Keefe [mailto:***@cs.otago.ac.nz]
Sent: Wednesday, July 06, 2011 7:23 PM
To: Feliks Kluzniak
Cc: 'Stassa Patsantzis'; swi-***@lists.iai.uni-bonn.de
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
Post by Richard O'Keefe
Post by Feliks Kluzniak
Push-back lists are there to handle movement.
Yes, but lest confusion arise we should point out that they can be used for
other purposes, too.
Since the OP *was* using push-back lists for another purpose,
I thought that went without saying.

Lookahead can be very simply handled using

peek(Token, Tokens, Tokens) :- Tokens = [Token|_].

What *should* be mentioned is that there are old and good arguments
that making use of push-backs can change the language that is accepted
in unintended ways: the parser will accept push-back tokens that were
not in fact pushed back.
Post by Richard O'Keefe
But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all. And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!
"push-back" does not mean that something is *returning* to the token stream,
it means that something is being pushed backwards against the normal flow.
The classic use of push-back lists for movement never did push back the
original tokens but something closer to an AST node.
Post by Richard O'Keefe
So-called DCGs are, of course, a very slightly simplified version of
Metamorphosis Grammars. The nature of the simplification escapes me at the
moment.
Colmerauer's paper defining Metamorphosis Grammars is on line at
http://www.springerlink.com/content/58188166u5723547/fulltext.pdf
but you need a Springer subscription to read it.

Definition : A metamorphosis grammar G is defined by a quintuplet
{F,VT,VN,VS,->}
(1) F is a set of functional symbols csntaining "." and "nil"
(2) VT is a vocabulary said to be terminal with VT c H [F]
(3) VN is a vocabulary said to be non-terminal with VN c H [F].
We suppose that VN \cap VT = \empty
and write V = VT \cup VN
(4) VS c VN . The elements of VS are termed starting non-terminals.
(5) -> is a re-writing relation on V* with the restriction that
x -> y implies x ~= nil

Let -> be a binary relation between the elements of H and let V be
a vocabulary without variables, i.e. V c H. The relation -> is said
to be a re-writing relation on V* iff
for each x,y \in H x -> y implies x,y \in V*

Definition : A metamorphosis grammar is said to be in normal form
if it satisfies the restriction ax -> y implies a \in VN and x \in VT*

The key point here is that the left hand side of an MG rule can be
an arbitrary non-empty sequence of terminals and non-terminals.

It appears that "DCG" is just a shorthand for "metamorphosis grammar
in normal form".

Colmerauer presented an algorithm for converting any MG to normal form
and devised the standard translation of DCGs to Horn clauses (although
he added the extra "sequence position" arguments at the front).

Fernando Pereira's eXtraposition Grammars were clearly influenced by
MGs but are neither a special case of MGs nor a generalisation of them.
Stassa Patsantzis
2011-07-06 18:44:16 UTC
Permalink
Feliks,

Hi.
Post by Feliks Kluzniak
But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all.
Do you mean something like this? 

     move --> moved, [token].
     moved, [X, abc, def] --> [moved].
    
    ?- move(X,Y).
    X = [moved|_G288],
    Y = [abc, def|_G288].
   
(again, sorry for the hasty naming).

I think I can see how that works, but I couldn't get your code to output its error message. How do you run it?

Sorry, I know this is not about my code anymore but I'm interested nonetheless.

Regards,
-Stassa

--- On Wed, 6/7/11, Feliks Kluzniak <***@utdallas.edu> wrote:

From: Feliks Kluzniak <***@utdallas.edu>
Subject: RE: [SWIPL] How to hide implied tokens in DCG rules?
To: "'Richard O'Keefe'" <***@cs.otago.ac.nz>, "'Stassa Patsantzis'" <***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Wednesday, 6 July, 2011, 12:06
Post by Feliks Kluzniak
Push-back lists are there to handle movement.
Yes, but lest confusion arise we should point out that they can be used for
other purposes, too.

The most obvious, of course, is to provide lookahead (and this might be
considered a special case of movement, where the displacement distance is
zero):

    exp -->  [ '(' ],  names( ')' ),  [ ')' ] .

    names( Terminator ), [ Terminator ]  --> 
            [ Termninator ],  !.

    names( Terminator )  --> 
          name, !,  names( Terminator ) .

    names( Terminator ), [ What ]  --> 
          [ What ],   
          % What \= Terminator,
          { write( 'Expected name or "' ),
            write( Terminator ),
            write( '", not "' ),
            write( What ),  write( '"' ),   nl
          }.

(I omit the other arguments that would normally be there: we seldom need
just a yes/no parser.  I apologize for any minor mistakes: I did not test
this.)


But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all.  And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!

If memory serves, the "non-push-back mode" is how the feature was used in
some of the original examples for Colmearauer's Metamorphosis Grammars. In
my mind the term "metamorphosis" was associated with the fact that the
analyzed string could be changed into something else while the analysis was
going on.  Since there are also the arguments, and since a suitably-written
grammar can also be used for synthesis, the whole mechanism truly impressed
with its generality and expressive power.

So-called DCGs are, of course, a very slightly simplified version of
Metamorphosis Grammars.  The nature of the simplification escapes me at the
moment.

Regards,
-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Richard O'Keefe
Sent: Tuesday, July 05, 2011 7:18 PM
To: Stassa Patsantzis
Cc: swi-***@lists.iai.uni-bonn.de
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
Post by Feliks Kluzniak
     deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or],
deals_or(A).
Post by Feliks Kluzniak
     deals_or(X) --> skipping(target), target(X).
     skipping(X), [X] --> [].
     skipping(_) --> [].
I am confused here by the words.  skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
Post by Feliks Kluzniak
     target(X) --> [target], player(X).
     target(X) --> [target], creature(X).
     
     player(X) --> {isa_player(X)}, [player].
     isa_player('us').
     isa_player('them').
     creature(X) --> {isa_creature(X)}, [creature].
     isa_creature('Goblin').
     isa_creature('Demon').
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*.  I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.

    deals(Actor, Amount, [Target1,Target2]) -->
        [Actor, deals, Amount, damage, to, target],
        simple_target(Target1),
        [or], optional(target),
        simple_target(Target2).

    optional(X) --> [X].
    optional(_) --> [].

    simple_target(Target) --> player(Target).
    simple_target(Target) --> creature(Target).

Push-back lists are there to handle movement.
For example,
    is John sick
could be parsed by
    sentence --> np, vp.

    np, [Aux] --> aux(Aux), noun.
    np        -->           noun.

    vp --> aux(_), verb.
    vp --> verb.

where the first rule for np picks up the moved auxiliary and then
puts it back after the "real" noun phrase.


_______________________________________________
SWI-Prolog mailing list
SWI-***@lists.iai.uni-bonn.de
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog

-------------- next part --------------
HTML attachment scrubbed and removed
Feliks Kluzniak
2011-07-06 22:39:13 UTC
Permalink
Hi Stassa,



Yes. But one would normally do

?- phrase( moved, [ moved ], Remainder ).

Remainder = [ X, abc, def ].



My code was just a schema. One would have to add some definition of name,
e.g.,



name --> [ v ].



Then

?- phrase( exp, [ '(', v, v, v, ')' ).



should succeed, while



?- phrase( exp, [ '(', v, v, ? ] ).



should bitterly complain about the question mark.



I have used this schema countless times, but this particular fragment of
code is untested.



Regards,

-- Feliks



From: Stassa Patsantzis [mailto:***@yahoo.com]
Sent: Wednesday, July 06, 2011 1:44 PM
To: 'Richard O'Keefe'; Feliks Kluzniak
Cc: swi-***@lists.iai.uni-bonn.de
Subject: RE: [SWIPL] How to hide implied tokens in DCG rules?




Feliks,

Hi.
Post by Feliks Kluzniak
But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all.
Do you mean something like this?

move --> moved, [token].
moved, [X, abc, def] --> [moved].

?- move(X,Y).
X = [moved|_G288],
Y = [abc, def|_G288].

(again, sorry for the hasty naming).

I think I can see how that works, but I couldn't get your code to output its
error message. How do you run it?

Sorry, I know this is not about my code anymore but I'm interested
nonetheless.

Regards,
-Stassa

--- On Wed, 6/7/11, Feliks Kluzniak <***@utdallas.edu> wrote:


From: Feliks Kluzniak <***@utdallas.edu>
Subject: RE: [SWIPL] How to hide implied tokens in DCG rules?
To: "'Richard O'Keefe'" <***@cs.otago.ac.nz>, "'Stassa Patsantzis'"
<***@yahoo.com>
Cc: swi-***@lists.iai.uni-bonn.de
Date: Wednesday, 6 July, 2011, 12:06
Post by Feliks Kluzniak
Push-back lists are there to handle movement.
Yes, but lest confusion arise we should point out that they can be used for
other purposes, too.

The most obvious, of course, is to provide lookahead (and this might be
considered a special case of movement, where the displacement distance is
zero):

exp --> [ '(' ], names( ')' ), [ ')' ] .

names( Terminator ), [ Terminator ] -->
[ Termninator ], !.

names( Terminator ) -->
name, !, names( Terminator ) .

names( Terminator ), [ What ] -->
[ What ],
% What \= Terminator,
{ write( 'Expected name or "' ),
write( Terminator ),
write( '", not "' ),
write( What ), write( '"' ), nl
}.

(I omit the other arguments that would normally be there: we seldom need
just a yes/no parser. I apologize for any minor mistakes: I did not test
this.)


But in general, it is very much worth noting that the terminals on the
left-hand side of a grammar rule need not be extracted from the right-hand
side: they can be any terms at all. And this is why I have a fundamental
objection to the name "push-back list": it is something much more than that!

If memory serves, the "non-push-back mode" is how the feature was used in
some of the original examples for Colmearauer's Metamorphosis Grammars. In
my mind the term "metamorphosis" was associated with the fact that the
analyzed string could be changed into something else while the analysis was
going on. Since there are also the arguments, and since a suitably-written
grammar can also be used for synthesis, the whole mechanism truly impressed
with its generality and expressive power.

So-called DCGs are, of course, a very slightly simplified version of
Metamorphosis Grammars. The nature of the simplification escapes me at the
moment.

Regards,
-- Feliks



-----Original Message-----
From: swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.de
[mailto:swi-prolog-bounces+feliks.kluzniak=***@lists.iai.uni-bonn.d
e] On Behalf Of Richard O'Keefe
Sent: Tuesday, July 05, 2011 7:18 PM
To: Stassa Patsantzis
Cc: swi-***@lists.iai.uni-bonn.de
Subject: Re: [SWIPL] How to hide implied tokens in DCG rules?
Post by Feliks Kluzniak
deals(X, Y, Z, A) --> [X, deals, Y, damage, to], target(Z), [or],
deals_or(A).
Post by Feliks Kluzniak
deals_or(X) --> skipping(target), target(X).
skipping(X), [X] --> [].
skipping(_) --> [].
I am confused here by the words. skipping(X) does not skip anything.
It may (first clause) or may not (second clause) push something back.
Post by Feliks Kluzniak
target(X) --> [target], player(X).
target(X) --> [target], creature(X).
player(X) --> {isa_player(X)}, [player].
isa_player('us').
isa_player('them').
creature(X) --> {isa_creature(X)}, [creature].
isa_creature('Goblin').
isa_creature('Demon').
It looks to me very much as if what you want to do is to treat the word
'target' as *optional*. I am also puzzled by the fact that creature//1
requires the word 'creature' in the input, and nothing else, but
*reports* either Goblin or Demon, and similarly player//1 requires
'player' in the input but *reports* us or them.

deals(Actor, Amount, [Target1,Target2]) -->
[Actor, deals, Amount, damage, to, target],
simple_target(Target1),
[or], optional(target),
simple_target(Target2).

optional(X) --> [X].
optional(_) --> [].

simple_target(Target) --> player(Target).
simple_target(Target) --> creature(Target).

Push-back lists are there to handle movement.
For example,
is John sick
could be parsed by
sentence --> np, vp.

np, [Aux] --> aux(Aux), noun.
np --> noun.

vp --> aux(_), verb.
vp --> verb.

where the first rule for np picks up the moved auxiliary and then
puts it back after the "real" noun phrase.


_______________________________________________
SWI-Prolog mailing list
SWI-***@lists.iai.uni-bonn.de
https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog



-------------- next part --------------
HTML attachment scrubbed and removed
Loading...