Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog DCG: Match different symbols on a chain

I'm trying to match some sentences (e.g. 001 [0,0,1], (1+(1/0)) ['(',1,+,'(',1,/,0,')',')'], and so on.

I've made myself following small DCG.

g3 --> s3.
s3 --> e3.

e3 --> eAdd.
e3 --> eMin.
e3 --> eMul.
e3 --> eDiv.
e3 --> n3.

eAdd --> ['('],e3,['+'],e3,[')'].
eMin --> ['('],e3,['-'],e3,[')'].
eMul --> ['('],e3,['*'],e3,[')'].
eDiv --> ['('],e3,['/'],e3,[')'].


n3 --> d3.
n3 --> n3,d3.
d3 --> [0].
d3 --> [1].

Now my problem is, it won't match with sentences using -,* or / but it works for recursive sentences using only +.

E.g:

phrase(g3,['(',1,'+','(',1,'+',1,')',')']).

Will work, but

phrase(g3,['(',1,'+','(',1,'/',1,')',')']).

Won't work.

Any help would be appreciated, thanks!

like image 626
user452306 Avatar asked Jan 03 '23 13:01

user452306


1 Answers

First of all, whenever you are using DCGs, consider to

:- set_prolog_flag(double_quotes, chars).

This permits to use a much more readable syntax. Here are the rules and queries that change due to this convention.

:- set_prolog_flag(double_quotes, chars).

eAdd --> "(", e3, "+", e3, ")".
eMin --> "(", e3, "-", e3, ")".
eMul --> "(", e3, "*", e3, ")".
eDiv --> "(", e3, "/", e3, ")".

d3 --> "0".
d3 --> "1".

?- phrase(g3,"(1+(1+1))").

?- phrase(g3,"(1+(1/1))").

Note that already your first query has a problem, even if it succeeds. This can be easily seen on the toplevel:

?- phrase(g3,"(1+(1+1))").
   true
;  resource_error(_). % ERROR: Out of local stack

So the toplevel insisted that there is something else apart from the actual success. To narrow this down in a systematic manner I will use a failure-slice which adds false to regular goals and {false} within the grammar.

:- set_prolog_flag(double_quotes, chars).

g3 --> s3, {false}.

s3 --> e3, {false}.

e3 --> {false}, eAdd.
e3 --> {false}, eMin.
e3 --> {false}, eMul.
e3 --> {false}, eDiv.
e3 --> n3, {false}.

n3 --> {false}, d3.
n3 --> n3, {false}, d3.

?- phrase(g3,"(1+(1+1))"), false.

Because this tiny fragment loops, the entire program loops, too. Note that + is no longer part of the program! The problem had nothing to do with + at all.

like image 155
false Avatar answered Jan 08 '23 04:01

false