Ticket #4180: Resolve.hs

File Resolve.hs, 1.8 KB (added by maeder, 3 years ago)

clearer version that separates prefix from infix resolution

Line 
1import Tok
2
3-- | resolve all tokens to an expression
4resolve :: [Tok] -> Maybe Exp
5resolve ts = do
6 (e, rs) <- resolveExpr Nothing ts
7 if null rs then return e else error "trailing tokens"
8
9-- | resolve tokens following an optional operator
10resolveExpr :: Maybe Op -> [Tok] -> Maybe (Exp, [Tok])
11resolveExpr op1 ts = case ts of
12  [] -> error "missing right argument"
13  t : r -> case t of
14    TNeg -> do
15      (n, s) <- resolveNegExpr r
16      resolveInfix op1 n s
17    TExp e1 -> resolveInfix op1 e1 r
18    _ -> error "two consecutive operators"
19
20-- | resolve tokens following prefix minus
21resolveNegExpr :: [Tok] -> Maybe (Exp, [Tok])
22resolveNegExpr ts = do
23  -- take all tokens as long as infix operators have higher precedence than -
24  let (nts, rs) = span (\ t -> case t of
25        TOp (Op _ prec _) -> prec > 6
26        _ -> True) ts
27  e <- resolve nts
28  return (Neg e, rs)
29
30-- | try to extend an expression by looking at the next infix operator
31resolveInfix :: Maybe Op -> Exp -> [Tok] -> Maybe (Exp, [Tok])
32resolveInfix mop1 e1 ts = case ts of
33  [] -> Just (e1, [])
34  t : r -> case t of
35    TOp op2@(Op _ prec2 fix2) ->
36       let cmp = case mop1 of
37            Nothing -> GT
38            Just (Op _ prec1 fix1) -> case compare prec2 prec1 of
39              EQ -> if fix1 == fix2 then
40                case fix1 of
41                  Leftfix -> LT    -- finish
42                  Nonfix -> EQ     -- fail
43                  Rightfix -> GT   -- recurse
44                else EQ
45              c -> c
46       in case cmp of
47            LT -> Just (e1, ts) -- finished with expression
48            EQ -> Nothing       -- illegal expression
49            GT -> do            -- enlarge left expression
50              (e2, r') <- resolveExpr (Just op2) r
51              resolveInfix mop1 (OpApp e1 op2 e2) r'
52    _ -> error $ "unexpected expression: " ++ show t
53
54main = test resolve