-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExp.hs
123 lines (103 loc) · 3.19 KB
/
Exp.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
module Exp where
import Control.Concurrent
import Control.Monad hiding (forM)
import System.IO
import Control.Monad.State hiding (forM)
import Text.PrettyPrint.HughesPJ
import ParserAux
import Text.Megaparsec
import Text.Megaparsec.String
import qualified Text.Megaparsec.Lexer as L
type Op = String
type Var = String
type Name = String
type NEnv a = [(Name,a)]
type VEnv a = [(Var,a)]
data Exp = EBinOp Exp Op Exp
| EUnOp Op Exp
| EInt Int
| EBool Bool
| EString String
| EVar Var
| EUnit
| EPrint Exp
| EName Name
data Val = VInt Int
| VString String
| VBool Bool
| VUnit
| VName Name
liftNum2 :: (Int -> Int -> Int) -> Val -> Val -> Val
liftNum2 f (VInt i) (VInt j) = VInt $ f i j
liftNum2 _ _ _ = error "type error"
liftNumBool2 :: (Int -> Int -> Bool) -> Val -> Val -> Val
liftNumBool2 f (VInt i) (VInt j) = VBool $ f i j
liftNumBool2 _ _ _ = error "type error"
liftStr2 :: (String -> String -> String) -> Val -> Val -> Val
liftStr2 f (VString s) (VString s') = VString $ f s s'
liftStr2 _ _ _ = error "type error"
binOpTable :: [(String,Val -> Val -> Val)]
binOpTable = [("+",liftNum2 (+)),
("-",liftNum2 (-)),
("<",liftNumBool2 (<)),
("*",liftStr2 (++))]
liftNum :: (Int -> Int) -> Val -> Val
liftNum f (VInt i) = VInt $ f i
liftNum _ _ = error "type error"
unOpTable :: [(String,Val -> Val)]
unOpTable = [("inv",liftNum $ \x -> -x)]
ppVal :: Val -> Doc
ppVal (VInt i) = int i
ppVal (VString s) = quotes $ text s
ppVal (VBool True) = text "true"
ppVal (VBool False) = text "false"
ppVal VUnit = lparen <> rparen
ppVal (VName n) = text "@" <> text n
instance Show Val where
show = render . ppVal
ppExp :: Exp -> Doc
ppExp (EBinOp e1 op e2) = parens $ ppExp e1 <+> text op <+> ppExp e2
ppExp (EUnOp op e) = parens $ text op <+> ppExp e
ppExp (EInt i) = int i
ppExp (EBool True) = text "true"
ppExp (EBool False) = text "false"
ppExp (EVar v) = text v
ppExp (EString s) = quotes $ text s
ppExp EUnit = lparen <> rparen
ppExp (EPrint e) = text "print" <> parens (ppExp e)
ppExp (EName n) = text "@" <> text n
instance Show Exp where
show = render . ppExp
parseExp = tries [parsePrint,
parseString,
parseName,
parseInt,
parseBool,
parseVar,
parseBin,
parseUn,
parseUnit]
parseBin = paren $ do
e1 <- parseExp
op <- lexeme (oneOf "+-*<")
e2 <- parseExp
return $ EBinOp e1 [op] e2
parseUn = paren $ do
op <- symbol "inv"
e <- parseExp
return $ EUnOp op e
parseInt = fmap (EInt . read) num
parseBool = parseTrue <|> parseFalse
where parseTrue = symbol "true" >> return (EBool True)
parseFalse = symbol "false" >> return (EBool False)
parseString = fmap EString $ between (symbol "\"") (symbol "\"") (many1 (alphaNumChar <|> spaceChar))
parseVar = fmap EVar name
parseUnit = symbol "()" >> return EUnit
parseName = do
string "@"
n <- name
return $ EName n
parsePrint = do
symbol "print"
e <- paren $ parseExp
return $ EPrint e