All,
I'm trying to write a parser using parsec. The goal is to eventually be able to parse a toy language.
Right now I'm struggling to make parsec recognise two different possible options, for example assignment and function invocation.
How would one write a "parseCode" function to parse the following:
x = 3
y = 4
plus(x,y)
into:
(Assignment "x" "3")
(Assignment "y" "4")
(Invocation "plus" ["x","y"])
Thanks
EDIT:
** omitted for brevity **
EDIT 2:
I built a bit upon your suggestions and now have the following problem
Running parse parseTester "bla" "{plus(3,4)\nmin(2,3)\nx=3\n"
gives the expected solution: Right (Body [Invocation "plus",Invocation "min",Assignment "x" "3"])
.
But running the functionally (almost) equivalent parse parseBody "bla" "{plus(3,4)\nmin(2,3)\nx=3\n}"
results in an error:
Left "bla" (line 4, column 2):
unexpected end of input
expecting white space or "="
I don't see the problem. Is the parser suddenly looking for an assignment where it should be looking for an invocation? Any suggestions?
Code:
data Body = Body [Statement]
deriving (Show)
data Arguments = Arguments [String]
deriving (Show)
data Statement = Assignment String String
| Invocation String
deriving (Show)
parseBody :: Parser Body
parseBody = do
char '{'
statements <- many1 parseStatement
char '}'
return $ Body statements
parseTester :: Parser Body
parseTester = do
char '{'
x <- many1 parseStatement
return $ Body x
parseStatement :: Parser Statement
parseStatement = do
x <- try parseInvocation <|> parseAssignment <?> "statement"
return x
parseInvocation :: Parser Statement
parseInvocation = do
spaces
name <- many1 (noneOf " (")
spaces
char '('
spaces
bla <- many1 (noneOf " )")
spaces
char ')'
char '\n'
return $ Invocation name
parseAssignment :: Parser Statement
parseAssignment = do
spaces
var <- many1 (noneOf " =")
spaces
char '=' <?> "equal in assignment"
spaces
value <- many1 (noneOf "\n")
char '\n'
spaces
return $ Assignment var value