Calling DCG with catch...stumped!

How do I call one DCG rule from inside another but be able to catch any exceptions it may throw ? I/ve tried a few things but I am getting just a little confused

foo(In,Out) -->
    % do some stuff but decide you need to
    {throw(...)}.

bar(In,Out) -
  {catch(foo(In,Out), Error, --deal with Error --)}.

I have tried both manually listing the coed and attempting to add the extra parameters when making bar NOT use --> and also I have tried writing a normal predicate that calls phrase on the rule that throws the exception but I am not succeeding yet!

Thanks in advance…I am still trying stuff…
:man_facepalming:

I was able to make this work by putting the catch around the call to phrase/3

foo -->
    [0'a],
    { throw(nope) }.
foo --> [X].

bar --> foo.

test_dcg :-
    catch(phrase(bar, `a`, Rest),
          Ex,
          format("Caught ~w", [Ex])
    ),
    format("Rest ~w", [Rest]).
1 Like

Solved!

I was calling the auxiliary predicate in the phrase :man_facepalming: indeed.

What I have is this, which is exactly how I thought it should be! But is it doing what I think it’s doing hahaha…

matchesF(In, Out, A, B) :-
    catch(phrase(matches(In, Out), A, B),
          ast_error(syntax(_, unexpected_token(_,_))),
          fail).

Is there another way to do this, out of curiosity?

Is it that you really want to throw an exception or just log a message and continue with the parsing, e.g. think of the input as source code and the messages as warnings for such as missing operators, etc.

If you goal is to record info from a stream while parsing the stream using DCGs then using prolog_wrap.pl – Wrapping predicates may be the way to go. I have not tried this yet but it is on my to do list.

Search here for prolog_wrap for the noted post to get more history on this.

Thanks for the link @EricGT …not what I was after but I will read that later as it looks interesting. Reminiscent of Lisp CLOS :before, :after and :around I guess.

At that point in the parsing process, the clause has reached a point where it knows there is either a syntax error or a premature end of buffer error mid-parse and so I want to fail and bail right there and then and throw() seemed like the way to do it.

It is the way I am doing it…I have ripped apart a lot of stuff today and it’s put me behind a little as to where I wanted to be today but hell, I have learned loads more and still got back to where I was last night and it’s only 6PM in the UK!

1 Like

I would also suggest to look at the brand new library(intercept) which seems to match your use cases nicely.

EDIT: And it probably has much less overhead than throwing an exception.

3 Likes

Interesting! Feels like a mix of the edcg library and IOC pattern.
Still not quite what I needed but more stuff to read “later”, I just love the sheer amount of libraries and support for SWI Prolog!

:slight_smile:

Was looking at SWI-Prolog library(quasi_quotations): Define Quasi Quotation syntax which might give you some ideas. Specifically look at the source code.