| 1 |
data Op = Op String Prec Fixity deriving Eq |
|---|
| 2 |
data Fixity = Leftfix | Rightfix | Nonfix deriving Eq |
|---|
| 3 |
data Exp = Var Var | OpApp Exp Op Exp deriving Eq |
|---|
| 4 |
type Prec = Int |
|---|
| 5 |
type Var = String |
|---|
| 6 |
|
|---|
| 7 |
data Tok = TVar Var | TOp Op |
|---|
| 8 |
|
|---|
| 9 |
parse :: [Tok] -> Exp |
|---|
| 10 |
parse (TVar x : rest) = fst (parse1 (Var x) (-1) Nonfix rest) |
|---|
| 11 |
|
|---|
| 12 |
parse1 :: Exp -> Int -> Fixity -> [Tok] -> (Exp, [Tok]) |
|---|
| 13 |
parse1 e p f [] = (e, []) |
|---|
| 14 |
parse1 e p f inp@(TOp op@(Op _ p' f') : TVar x : rest) |
|---|
| 15 |
| p' == p && (f /= f' || f == Nonfix) |
|---|
| 16 |
= error "ambiguous infix expression" |
|---|
| 17 |
| p' < p || p' == p && (f == Leftfix || f' == Nonfix) |
|---|
| 18 |
= (e, inp) |
|---|
| 19 |
| otherwise |
|---|
| 20 |
= let (r,rest') = parse1 (Var x) p' f' rest in |
|---|
| 21 |
parse1 (OpApp e op r) p f rest' |
|---|
| 22 |
|
|---|
| 23 |
-- Printing |
|---|
| 24 |
|
|---|
| 25 |
instance Show Exp where |
|---|
| 26 |
showsPrec _ (Var x) = showString x |
|---|
| 27 |
showsPrec p e@(OpApp l (Op op _ _) r) = |
|---|
| 28 |
showParen (p > 0) $ showsPrec 9 l . showString op . showsPrec 9 r |
|---|
| 29 |
|
|---|
| 30 |
-- Testing |
|---|
| 31 |
|
|---|
| 32 |
plus = TOp (Op "+" 6 Leftfix) |
|---|
| 33 |
times = TOp (Op "*" 7 Leftfix) |
|---|
| 34 |
divide = TOp (Op "/" 7 Leftfix) |
|---|
| 35 |
gt = TOp (Op ">" 4 Nonfix) |
|---|
| 36 |
ex = TOp (Op "^" 8 Rightfix) |
|---|
| 37 |
|
|---|
| 38 |
lookupop '+' = plus |
|---|
| 39 |
lookupop '*' = times |
|---|
| 40 |
lookupop '/' = divide |
|---|
| 41 |
lookupop '>' = gt |
|---|
| 42 |
lookupop '^' = ex |
|---|
| 43 |
|
|---|
| 44 |
fromstr [x] = [TVar [x]] |
|---|
| 45 |
fromstr (x:y:z) = TVar [x] : lookupop y : fromstr z |
|---|
| 46 |
|
|---|
| 47 |
test1 = fromstr "a+b+c" |
|---|
| 48 |
test2 = fromstr "a+b+c*d" |
|---|
| 49 |
test3 = fromstr "a/b/c" |
|---|
| 50 |
test4 = fromstr "a/b+c" |
|---|
| 51 |
test5 = fromstr "a/b*c" |
|---|
| 52 |
test6 = fromstr "1^2^3+4" |
|---|
| 53 |
test7 = fromstr "a/1^2^3" |
|---|
| 54 |
test8 = fromstr "a*b/c" |
|---|