[m-users.] DCG and optional whitespace term

Sean Charles (emacstheviking) objitsu at gmail.com
Sun May 9 00:37:46 AEST 2021


Hello,
I am having trouble with DCG rules. I have a relatively good understanding of them in Prolog world. I’ve read the calculator.m sample many times now but it only got me so far (thank you Julien) and now the determinism error messages have me stumped as to how to proceed. I have a toy example, I built a REPL for my system, so far it supports three commands, and I wanted to add an optional second token to the help command for specific help to be shown, here is the code, plus if the user enters any whitespace then hits return the other two matches fail, so handling whitespace is a must:

    % DCG Command Parser, case sensitive for now...
    %
:- type command ---> help ; lex ; ast.

:- pred parse_cmd(command::out, list(char)::in, list(char)::out) is semidet.

parse_cmd(CMD) -->
    (
        ['h','e','l','p'],
        skip_ws, eol,
        {CMD=help}
    ;
        ['l','e','x'], eol,
        {CMD=lex}
    ;
        ['a','s','t'], eol,
        {CMD=ast}
    ).

:- pred skip_ws(list(char)::in, list(char)::out) is semidet.
skip_ws --> [C],{char.is_whitespace(C)}, skip_ws.
skip_ws --> [].

:- pred eol(list(char)::in, list(char)::out) is semidet.
eol --> ['\n'].
eol --> ['\r'], ['\n’].

The compiler outputs the following error message:

repl.m:118: In `skip_ws'(in, out):
repl.m:118:   error: determinism declaration not satisfied.
repl.m:118:   Declared `semidet', inferred `multi'.
repl.m:120:   Disjunction has multiple clauses with solutions.

I can understand —why— but there is not cut, my original code in Prolog was like this:

skip_ws --> ws(_), !, skip_ws.
skip_ws --> [].

In my Mercury version I can see that having called skip_ws, it will pull of a char into C, if that is whitespace then it will loop until that predicate fails but I can’t see how to tell it to commit and allow the ‘transform’ to transform V1 into V2  (from the DCG section of the manual), as I understand it, what will happen is that the first predicate will consume whitespace until it hits a character that isn’t whitespace (assuming buffer data still available) but then it will fail at which point the input list will revert to the value it had before, then the second predicate will execute succeed meaning that I haven’t actually skipped anything at all?!?

I just cannot yet figure out how to do this in Mercury! Stumped thus far.

Any advice or explanations would be very welcomed from this quarter about now.
Thank you.
Sean

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20210508/accf0a92/attachment.html>


More information about the users mailing list