1

I am having trouble with nested indented blocks swallowing new lines. I want to parse a function definition (or rather skip the entire body, func. def. is not necessarily top-level).

Example:

func F() -> void: pass

func m():
  pass

func f(a:= 4, b, c:X) -> Y:
    if a >= 0:
        if b > 4:
            return b
        else:
            return c.y(-b)
    else: return c.y(b)

My code:

pFunc :: Parser Node
pFunc = (try pMultiline <|> pOneline) & dbg "pFunc"
  where
    pOneline = do
      (name, args, ret) <- pFuncHead
      pStatement
      return $ NFuncDef name args ret
    pMultiline = (L.indentBlock scn pMultilineIB) & dbg "pMultiline"
    pMultilineIB = do
      (name, args, ret) <- pFuncHead & dbg "pMultilineIB pFuncHead"
      return $ L.IndentSome Nothing (\_ -> return $ NFuncDef name args ret) body
    body = (try nested <|> void pSomeTillEol) & dbg "body"
    nested = (L.indentBlock scn nestedIB) & dbg "nested"
    nestedIB = do
      pStatement
      return $ L.IndentSome Nothing (const skip) body

pFuncHead, pStatement and pSomeTillEol don't consume trailing new lines (only scn does, I was using this tutorial as a template).

Ran with "func m():\n pass\n\n":

pMultilineIB pFuncHead> IN: "func m():<newline>  pass<newline><newli <…>
pMultilineIB pFuncHead> MATCH (COK): "func m():"
pMultilineIB pFuncHead> VALUE: ("m",[],Nothing)

nested> IN: "pass<newline><newline>"
nested> MATCH (CERR): "pass<newline><newline>"
nested> ERROR:
nested> offset=18:
nested> incorrect indentation (got 1, should be greater than 3)

pSomeTillEol> IN: "pass<newline><newline>"
pSomeTillEol> MATCH (COK): "pass"
pSomeTillEol> VALUE: "pass"

body> IN: "pass<newline><newline>"
body> MATCH (COK): "pass"
body> VALUE: ()

pMultiline> IN: "func m():<newline>  pass<newline><newli <…>
pMultiline> MATCH (COK): "func m():<newline>  pass<newline><newli <…>
pMultiline> VALUE: NFuncDef "m" [] Nothing

pFunc> IN: "func m():<newline>  pass<newline><newli <…>
pFunc> MATCH (COK): "func m():<newline>  pass<newline><newli <…>
pFunc> VALUE: NFuncDef "m" [] Nothing

Why is pMultiline, so I guess the indentBlock, eating the trailing new lines? How to fix it?

menfon
  • 1,587
  • 1
  • 11
  • 28
  • It seems pretty reasonable that indentBlock consumes the trailing newlines, because normally you wouldn't want them anyway. I would suggest looking at the source for indentBlock and using it as a guide to write your own version that does what you want. – 8n8 Feb 17 '20 at 21:25
  • @5ndG Yes, you are right, it just follows other megaparsec parsers (consuming white space after). I rewrote my top parser to not use `sepByEnd` on `eol` and instead I am using simpler `many`. So far it seems to work well :). – menfon Feb 18 '20 at 10:17

0 Answers0