Parsec続き
代入式らしいものは書けるようになった.あと型クラスを使って toCode (コードを生成する関数)を実装してみる.うーんやっぱり 型なのに「instance」と書くのはまだ抵抗がある.
あと Foo {bar:: Int} という記法は扱いがすごい面倒なことがわかった.特に関数を書くときに
hoge Foo {bar:: b} = fuga b
みたいに書かないといけないから.やっぱりこう書かせてよー(まだ言っている)
hoge f::Foo = fuga (f.bar)
module Parse where import Text.ParserCombinators.Parsec --main r :: String -> String r input = case parse source "lisp" input of Left err -> "No match: " ++ show err Right val -> "Found value" ++ (show $ map toCode val) --util mny :: Parser a -> Parser [a] mny p = many (do { spc; p } ) toks1 :: Parser Char -> Parser String toks1 p = do {res<-many1 p ; spc; return res } spc :: Parser () spc = skipMany space tok :: String -> Parser String tok str = do { s <- string str; spc ; return s } --grammar source :: Parser [Decl] source = do { bodies <- mny ( vardecl <|> statement) ; return bodies } vardecl :: Parser Decl vardecl = do { tok "var" ; name <- symbol; tok ";" ; return $ VarDecl {vdName = name } } statement :: Parser Decl statement = do { e <- expr ; tok ";" ; return $ StmtDecl $ ExprStmt e } expr :: Parser Expr expr = do { left <- add ; option left (do { tok "=" ; a<-add ; return (BinOp left "=" a) }) } add = do { left <- element ; rights <- mny (do { op <- operators ; e <- element ; return (op,e) } ) ; return (makeBinOp left rights) } operators :: Parser String operators = tok "+" <|> tok "-" element :: Parser Expr element = intConst <|> varRef varRef :: Parser Expr varRef = do { n <- symbol ; return VarRef {vrName=n} } intConst :: Parser Expr intConst = do { v <- digits ; return $ IntConst v } symbol :: Parser String symbol = toks1 letter digits :: Parser Int digits = do { d <- toks1 (oneOf "0123456789") ; return (read d::Int) -- ??? } --semantics makeBinOp :: Expr -> [(String,Expr)] -> Expr makeBinOp left [] = left makeBinOp left ((op,elem):rest) = makeBinOp (BinOp left op elem) rest data Decl = VarDecl { vdName:: String } | StmtDecl Statement -- ! deriving Show data Statement = ExprStmt Expr deriving Show data Expr = BinOp Expr String Expr | IntConst Int | VarRef { vrName:: String } deriving Show class (Show a)=> Codable a where toCode:: a -> String toCode a=show a instance Codable Statement where toCode (ExprStmt e) = "STM "++ (toCode e) ++";" instance Codable Expr where toCode (BinOp l o r) = (toCode l) ++ (toCode r) ++ o toCode a=show a instance Codable Decl where toCode (StmtDecl st) = toCode st toCode a=show a