Skip to content

Instantly share code, notes, and snippets.

@samrat
Created August 13, 2016 16:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samrat/9480c374c879848e5c73a7992a7de492 to your computer and use it in GitHub Desktop.
Save samrat/9480c374c879848e5c73a7992a7de492 to your computer and use it in GitHub Desktop.
import Data.Char
-- Grammar
-- =======
-- expr -> id | num | list
-- list -> '(' seq ')'
-- seq -> {expr}
data Exp = EIdent String
| EInt String
| List [Exp]
| Seq Exp Exp
| NoMatch
deriving (Show)
data Token = TIdent String
| TInt String
| LParen | RParen
| Other
| EndOfString
deriving (Show, Eq)
segregate _ [] = ([], [])
segregate pred (x:xs)
| pred x = let (satisfies, not_satisfies) = segregate pred xs
in (x:satisfies, not_satisfies)
| otherwise = ([], x:xs)
getToken :: [Char] -> (Token, [Char])
getToken [] = (EndOfString, [])
getToken (' ' : xs) = getToken xs -- skip blanks
getToken ('(' : xs) = (LParen, xs)
getToken (')' : xs) = (RParen, xs)
getToken (x : xs)
| isAlpha x =
let (rest_ident, rest_string) =
segregate (\c -> isAlpha c || isDigit c) xs
in (TIdent (x:rest_ident), rest_string)
| isDigit x = let (rest_digit, rest_string) =
segregate isDigit xs
in (TInt (x:rest_digit), rest_string)
| otherwise = (Other, xs)
-- Parser
getExpr :: [Char] -> (Exp, [Char])
getExpr cs =
case getToken cs of
(TIdent str, rest) -> (EIdent str, rest)
(TInt str, rest) -> (EInt str, rest)
(LParen, r1) -> getList cs -- let getList consume '('
(_, rest) -> (NoMatch, rest)
getList cs =
let (LParen, r1) = getToken cs
(es, r2) = getSeq r1
(RParen, r3) = getToken r2
in (List es, r3)
getSeq cs =
case getExpr cs of
(NoMatch, rest) -> ([], cs)
(exp, rest) -> let (e2, r2) = getToken rest
in if e2 /= RParen
then let (exp2, r3) = getSeq rest
in ([exp] ++ exp2, r3)
else ([exp], rest)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment