X-Git-Url: http://git.lukelau.me/?a=blobdiff_plain;f=AST.hs;h=b019a2a2078f91c18a5046f63e10676f2c40d5aa;hb=refs%2Fheads%2Ftutorial-3;hp=5628e7c7cd74c8d0f04d5b4e9c908e245e5696f6;hpb=7d4a5a11fdf751673d3f1a62e3f19fd6e2587af0;p=kaleidoscope-hs.git diff --git a/AST.hs b/AST.hs index 5628e7c..b019a2a 100644 --- a/AST.hs +++ b/AST.hs @@ -1,23 +1,89 @@ module AST where +import Data.Char import Text.Read -import Text.ParserCombinators.ReadP hiding ((+++)) +import Text.ParserCombinators.ReadP hiding ((+++), (<++), choice) -data Expr = Num Float - | Add Expr Expr +data Expr = Num Double + | Var String + | BinOp BinOp Expr Expr + | Call String [Expr] + | If Expr Expr Expr + | For String Expr Expr (Maybe Expr) Expr + deriving Show + +data BinOp = Add | Sub | Mul | Cmp Ordering deriving Show instance Read Expr where - readPrec = parseNum +++ parseAdd + readPrec = parens $ choice [ parseNum + , parseVar + , parseCall + , parseIf + , parseFor + , parseBinOp "<" 10 (Cmp LT) + , parseBinOp ">" 10 (Cmp GT) + , parseBinOp "==" 10 (Cmp EQ) + , parseBinOp "+" 20 Add + , parseBinOp "-" 20 Sub + , parseBinOp "*" 40 Mul + ] where parseNum = Num <$> readPrec - -- use 'prec 1' and 'step' so that parsing 'a' - -- can only go one step deep, to prevent ininfite - -- recursion - parseAdd = prec 1 $ do + parseVar = Var <$> lift (munch1 isAlpha) + parseBinOp s prc op = prec prc $ do a <- step readPrec - lift $ do - skipSpaces - char '+' - skipSpaces + spaced $ string s b <- readPrec - return (Add a b) + return (BinOp op a b) + parseCall = do + func <- lift (munch1 isAlpha) + params <- lift $ between (char '(') (char ')') $ + sepBy (readS_to_P reads) + (skipSpaces >> char ',' >> skipSpaces) + return (Call func params) + parseIf = do + spaced $ string "if" + cond <- readPrec + spaced $ string "then" + thenE <- readPrec + spaced $ string "else" + elseE <- readPrec + return (If cond thenE elseE) + parseFor = do + spaced $ string "for" + identifier <- lift (munch1 isAlpha) + spaced $ char '=' + start <- readPrec + spaced $ char ',' + cond <- readPrec + stp <- (spaced (char ',') >> Just <$> step readPrec) + <++ pure Nothing + spaced $ string "in" + body <- readPrec + return (For identifier start cond stp body) + spaced f = lift $ skipSpaces >> f >> skipSpaces + +data Prototype = Prototype String [String] + deriving Show + +instance Read Prototype where + readPrec = lift $ do + name <- munch1 isAlpha + params <- between (char '(') (char ')') $ + sepBy (munch1 isAlpha) skipSpaces + return (Prototype name params) + +data AST = Function Prototype Expr + | Extern Prototype + | TopLevelExpr Expr + deriving Show + +instance Read AST where + readPrec = parseFunction +++ parseExtern +++ parseTopLevel + where parseFunction = do + lift $ string "def" >> skipSpaces + Function <$> readPrec <*> readPrec + parseExtern = do + lift $ string "extern" >> skipSpaces + Extern <$> readPrec + parseTopLevel = TopLevelExpr <$> readPrec