[m-users.] parsing, seeking advice on simple combinator project and also operators.

Sean Charles (emacstheviking) objitsu at gmail.com
Sun Oct 30 03:23:16 AEDT 2022


Hi,

I have spent a goodly few days on and off reading the xml.parser.m file in the extras folder for some insights but whoever wrote that is light years ahead of me, it's been hard to follow at best.

I also returned to reading the code for mmc-doc, another good source of inspiration, in particular I tried to adapt this code but I don't think I filly understand yet how Mercury does higher-order functions, nor do I fully understand modes/insts when related to HOP.

Here is the code, it provides (file: config.m) a function '//' that allows chaining, which is what I am trying to do:

:- type maybeio == (pred(maybe(string), io, io)).
:- inst maybeio == (pred(out, di, uo) is det).
:- func (maybeio::in(maybeio)) // (maybeio::in(maybeio))
    = (maybeio::out(maybeio)).
A // B = C :-
    C = (pred(Res::out, !.IO::di, !:IO::uo) is det :-
        A(Res1, !IO),
        (
            Res1 = Res @ yes(_)
        ;
            Res1 = no,
            B(Res, !IO)
        )).

I can see that the chain is started further down:

        GetConfig = get_environment_var("XDG_CONFIG_HOME")
            // get_environment_var("APPDATA")
		:
		:

I see that the definition of '//' is such that it expects predicates on both sides and that they are executed -inside- the implementation of the function i.e. the get_environment_var() is not called at that point in the code but is in fact passed in as an argument to '//', and then executed by the line 'A(Res1, !IO)' or 'B(Res,!IO)', that much I have understood. Hope resigns supreme.

How did the author know to use '//'?  Given that Mercury doesn't allow arbitrary strings of non-alpha characters to be used as a function/operator name like Prolog. On page 6, section 2 'Operators' (reference manual), there is a huge list of operators but it isn't obvious where to look for the module that defines them, I am assuming that '//' is used in a module NOT imported into the source file but is recognised by the parser? How does one know what operators can be used for ones own purposes, I managed to find that '//' and '**' worked for me but I am not sure what they do, I am guessing that '**' is 'power' or 'exponential' ?

My own dilemma...

In my transpiler project I have a lot of structural syntax checking to do, 84 reserved words actually, and I thought that writing a simple parser combinator would be the way to go, except in Mercury I lack the experience. I've used Haskell and Parsec before a few times so I kind of know how I think my code should go, something like this

	let Args = list of AST nodes, nested as dictated by source

so, given Args, I was hoping to do something like creating a parser, then calling a combinator for each of the expected things I want to see, for example, defining a function is (DEFUN fname (ARGS) [BODY]), so my hypothetical code would be:

	parse_init(Args) // fn_name // fn_sig // remainder

and then for each matching term, I would store in the parser state, the actual node that matched, and if errors are detected then I want to catch those and also short circuit any remaining calls, so in the previous example, if fn_name failed, then fn_sig and remainder would just do nothing. Once I get that much I think extending it would be mentally easier, handling alternatives, repetitions etc although my grammar is quite simple.

I am just now at a loss as how to proceed, I am taking a step back and reading the HOP section again and just practicing with some simple code to get my sea legs but any advice etc would be greatly appreciated! Again I feel this is a good learning opportunity for me, and would also lead to less boiler plate, I hope.

Thanks
Sean




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


More information about the users mailing list