module SExpr where import Prelude hiding (fmap, pure, (<*>), (<*), (*>), (>>=)) import ParserLib import SExprDef -- [6 marks] -- Lisp and Scheme use S-expressions. A basic version of the grammar in EBNF is: -- -- S ::= var -- | "(" S { S } ")" -- -- `var` can be done by `identifier` in ParserLib.hs for simplicity, and we -- don't have reserved words in this lab. -- -- Implement `sexpr` below for this grammar. Produce an AST of type `SExpr` -- (defined in SExprDef.hs). -- -- How (code structure): Since this grammar does not have left recursion, your -- code structure can closely follow the recursive structure of the grammar: -- -- * Call sexpr (recursive call) to read one S. -- -- * `S { S }` means "one or more S's". We have a connective for exactly that. -- -- * Review what these can do for you: `<|>`, `<*`, `*>`, `fmap`. -- -- Spaces: Follow our convention for token-level parsers: Assume no spaces -- before, skip spaces after. If you stick to the token-level parsers (rather -- than examining individual characters yourself), you're set. Note that -- ParserLib.hs has `openParen` and `closeParen` too. -- -- Example: -- -- runParser sexpr "( f ( g x1 y1) (h)) junk" -- = Just (List [Ident "f",List [Ident "g",Ident "x1",Ident "y1"],List [Ident "h"]]) -- -- (If you're curious about initial leading spaces, see `mainParser` below.) sexpr :: Parser SExpr sexpr = error "TODO" -- If you're interested: Initial leading spaces, as well as (lack of) trailing -- junk, are handled by having a "main parser": mainParser :: Parser SExpr mainParser = whitespaces *> sexpr <* eof