<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>