<html><head><meta http-equiv="content-type" content="text/html; charset=us-ascii"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">Hi,<div><br><div>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.</div></div><div><br></div><div>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.</div><div><br></div><div>Here is the code, it provides (file: config.m) a function '//' that allows chaining, which is what I am trying to do:</div><div><br></div><div><div><font face="APL385"><span style="font-style: normal;">:- type maybeio == (pred(maybe(string), io, io)).</span></font></div><div><font face="APL385"><span style="font-style: normal;">:- inst maybeio == (pred(out, di, uo) is det).</span></font></div><div><font face="APL385"><span style="font-style: normal;">:- func (maybeio::in(maybeio)) // (maybeio::in(maybeio))</span></font></div><div><font face="APL385"><span style="font-style: normal;"> = (maybeio::out(maybeio)).</span></font></div><div><font face="APL385"><span style="font-style: normal;">A // B = C :-</span></font></div><div><font face="APL385"><span style="font-style: normal;"> C = (pred(Res::out, !.IO::di, !:IO::uo) is det :-</span></font></div><div><font face="APL385"><span style="font-style: normal;"> A(Res1, !IO),</span></font></div><div><font face="APL385"><span style="font-style: normal;"> (</span></font></div><div><font face="APL385"><span style="font-style: normal;"> Res1 = Res @ yes(_)</span></font></div><div><font face="APL385"><span style="font-style: normal;"> ;</span></font></div><div><font face="APL385"><span style="font-style: normal;"> Res1 = no,</span></font></div><div><font face="APL385"><span style="font-style: normal;"> B(Res, !IO)</span></font></div><div><font face="APL385"><span style="font-style: normal;"> )).</span></font></div></div><div><br></div><div>I can see that the chain is started further down:</div><div><br></div><div><div><font face="APL385"><span style="font-style: normal;"> GetConfig = get_environment_var("XDG_CONFIG_HOME")</span></font></div><div><font face="APL385"><span style="font-style: normal;"> // get_environment_var("APPDATA")</span></font></div></div><div><font face="APL385"><span style="font-style: normal;"><span class="Apple-tab-span" style="white-space:pre"> </span>:</span></font></div><div><font face="APL385"><span style="font-style: normal;"><span class="Apple-tab-span" style="white-space:pre"> </span>:</span></font></div><div><br></div><div>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.</div><div><br></div><div>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' ?</div><div><br></div><div>My own dilemma...</div><div><br></div><div>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</div><div><br></div><div><font face="APL385"><span style="font-style: normal;"><span class="Apple-tab-span" style="white-space:pre"> </span>let Args = list of AST nodes, nested as dictated by source</span></font></div><div><br></div><div>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:</div><div><font face="APL385"><span style="font-style: normal;"><br></span></font></div><div><font face="APL385"><span style="font-style: normal;"><span class="Apple-tab-span" style="white-space:pre"> </span>parse_init(Args) // fn_name // fn_sig // remainder</span></font></div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>Thanks</div><div>Sean</div><div><br></div><div><br></div><div><br></div><div><br></div></body></html>