Mr.Bloom
Mr.Bloom

Reputation: 365

Haskell: How to integrate semantic whitespacing into a parser?

I'm currently writing a language in Haskell, https://github.com/EdONeill1/HENRYGCL, and I'm having trouble in figuring out how to allow for a program to be written on multiple lines. Take the following loop that adds 1 onto x until it reaches 10.

Henry > x := 1
Henry > if <x<10> [] x := <x+1> [] x := <x+10>

I would like the program to be somewhat in the form of:

Henry > x := 1
Henry > if <x<10>
[] x := <x+1>
[] x := <x+10>

I thought about using the function space or newline from the Text.ParserCombinators.Parsec.Char module. This would allow me to recognise (I think) the newline token \n. Upon using it the following parser function:

ifStmt :: Parser HenryVal
ifStmt =
  do 
     reserved "if"
     cond  <- bExpression <|>
              do 
                _ <- char '<'
                x <- try parseBinary
                _ <- char '>'
                return x
    some (space <|> newline)
    reserved "[]"
    stmt1 <- statement
    some (space <|> newline)
    reserved " []"
    stmt2 <- statement
    return $ If cond stmt1 stmt2

I receive the following error when I try following:

Henry > x:=1
1
Henry > if <x<10>
Parse error at "Henry" (line 1, column 10):
unexpected end of input
expecting space or lf new-line
Henry > if <x<10>
Parse error at "Henry" (line 1, column 12):
unexpected end of input
expecting space, lf new-line or "[]"
Henry >

The first error arises from pressing Enter when I finish typing > and the second error arises from pressing Space once then pressing Enter. In both instances a newline wasn't corrected. I'm not sure as well as to what lf in lf new-line actually means because to my understanding, shouldn't hitting Enter give you a newline?

In another section of my code I have the following, whiteSpace = Token.whiteSpace lexer. When I replace the some (space <|> newline) with this and press enter after if <x<10>, a newline is actually created. However despite being able to write a full if-statement, there's no termination and it just allows me to keep writing as much as I want indefinitely.

I'm quite confused in how to proceed from here. I think my logic using some (space <|> newline) is correct insofar as if the program encounters at least one space or newline, a space or newline is made but I know my implementation is incorrect. I thought that maybe whiteSpace would lead to somewhere but it seems as if that's another dead end.

Upvotes: 0

Views: 61

Answers (1)

Li-yao Xia
Li-yao Xia

Reputation: 33519

The parser looks fine. The problem here is that main currently runs the parser on a single line at a time. You need to accumulate the whole input before running the parser.

Upvotes: 1

Related Questions