<div dir="ltr">Thank you Edward for your reply. <div><br></div><div>It took some time for me to understand a formal description (translation function L) of</div><div>the Haskell layout rule in Section 10.3 of Haskell 2010 language report. :)</div><div><div><br></div><div>I myself tried to write an example with the Haskell layout rule for me to understand it. </div><div>I am sharing this for those who are curious about the Haskell layout rules.</div></div><div><br></div><div> - <a href="http://lazyswamp.blogspot.com/2021/10/on-haskell-layout-rule.html">http://lazyswamp.blogspot.com/2021/10/on-haskell-layout-rule.html</a><br></div><div><br></div><div>Kwanghoon</div><div><br></div><div>PS.</div><div>To be honest, however, I still don't know how Haskell parser (Parser.y) and lexer (Lexer.x) interact with each other</div><div>to implement the following rule on the insertion of a closing brace on a parse error. </div><div><br></div><div> [Sec. 10.3] </div><div><div> - L (t : ts) (m : ms) = } : (L (t : ts) ms) if m /= 0 and parse-error(t)<br></div></div><div><br></div><div>It seems that Happy's error recover is relevant to the interaction via a production rule:</div><div><br></div><div> [ Parser.y ]</div><div> - close :: { () }<br> : vccurly { () } -- context popped in lexer.<br> | error {% popContext }<br></div><div><br></div><div>Is it enough for a Haskell lexer just to pop the top context? It is not clear to me how vccurly is inserted just </div><div>by having such a production rule and an error recovery. </div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 18 Aug 2021 at 17:05, Edward Kmett <<a href="mailto:ekmett@gmail.com">ekmett@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Unfortunately, the current parsing rules for Haskell aren't fully phase-separable like this.<br><br>If you look at the rules for Layout token insertion in the Haskell report the 9th rule requires that in the event the parser encounters a parse error it should insert a virtual close brace and continue on!<div><br></div><div>Otherwise you couldn't parse things like <b>let </b><i>{</i><b> foo = bar </b><i>}</i><b> in baz </b>where the {}'s are virtual without reframing <b>let</b> and <b>in</b> as a different kind of paired opening and closing brace or using other hacks in the grammar. It is quite difficult to hack around all the ways parses can go wrong.</div><div><br></div><div>The main downside this has from a language standpoint is you simply can't properly lex Haskell without more or less fully parsing Haskell.</div><div><br></div><div>-Edward</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Aug 18, 2021 at 7:22 AM Kwanghoon Choi <<a href="mailto:lazyswamp@gmail.com" target="_blank">lazyswamp@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div>Hi,<br><div><br></div><div>I have recently been playing with GHC's Lexer.lexer in the ghc-parser-lib package.</div><div><br></div><div>Given</div><div><br></div><div> module HelloWorld where<br><br> main = putStrLn "Hello World!\n"<br></div><div><br></div><div>it produces</div><div><br></div><div> stack exec -- lexer-exe ./examples/HelloWorld.hs <br> Lexing&Parsing: ./examples/HelloWorld.hs<br> module at (1, 1): module<br> CONID at (1, 8): CONID<br> where at (1, 19): where<br> vocurly at (3, 1): vocurly <==== { is inserted automatically!!<br> VARID at (3, 1): VARID<br> = at (3, 6): =<br> VARID at (3, 8): VARID<br> STRING at (3, 17): STRING<br> ; at (4, 1): ;<br></div><div><br></div><div>By the example above, the lexer automatically inserts an opening brace (i.e. vocurly) right after 'where'. But it does not insert a matching closing brace (i.e., vccurly), which would lead to a failure in parsing a list of tokens produced by the lexer. </div><div><br></div><div>My question is how to use the GHC lexer to produce closing braces as well. </div><div><br></div><div>All my code is available </div><div> - <a href="https://github.com/kwanghoon/hslexer" target="_blank">https://github.com/kwanghoon/hslexer</a></div><div><br></div><div>To save your time, the relevant part of the code is as follows:</div><div><br></div><div>In app/HaskellLexer.hs,</div><div><br></div><div> singleHaskellToken :: P (Located Token)<br> singleHaskellToken =<br> Lexer.lexer False<br> (\locatedToken -> P (\pstate -> POk pstate locatedToken))<br><br> tokInfos :: [Terminal Token] -> P (Line, Column, [Terminal Token])<br> tokInfos s = do<br> locatedToken <- singleHaskellToken<br> case locatedToken of<br> L srcspan ITeof -><br> let (start_line, start_col, end_line, end_col) = srcSpanToLineCol srcspan in<br> return (end_line, end_col, s)<br> <br> L srcspan tok -><br> let (start_line, start_col, end_line, end_col) = srcSpanToLineCol srcspan in<br> tokInfos (Terminal (fromToken tok) start_line start_col (Just tok) : s)<br></div><div><br></div><div>Thanks in advance</div><div><br></div><div>Best regards,</div><div><br></div><div>Kwanghoon</div><div><br></div><div><br></div><div><br></div><div><br></div></div>
_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
</blockquote></div>
</blockquote></div>