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
|
{-
Solution to the dangling-else problem:
frown --trace IfThenElse.g
Try
start (lexer "if a then if a then a=b else a=c")
-}
module Dangling
where
import Char
import Monad
type Result = []
instance MonadPlus IO where
mzero = fail "mzero"
m `mplus` n = putStrLn "** choice" >> m >> putStrLn "** backtrack" >> n
--frown ts = putStrLn "*** syntax error" >> return undefined
frown ts = fail "syntax error"
%{
Terminal = IF | THEN | ELSE | EQU | IDENT {String} | *EOF;
Nonterminal = start | stat | matched | unmatched | expr;
start : stat;
stat : matched;
| unmatched;
matched : IF, expr, THEN, matched, ELSE, matched;
| expr, EQU, expr;
unmatched : IF, expr, THEN, stat;
| IF, expr, THEN, matched, ELSE, unmatched;
expr : IDENT {s};
}%
data Terminal = IF | THEN | ELSE | EQU | IDENT String | EOF
deriving (Show)
lexer :: String -> [Terminal]
lexer [] = [EOF]
lexer ('=' : cs) = EQU : lexer cs
lexer (c : cs)
| isAlpha c = let (n, cs') = span isAlphaNum cs
in (case (c : n) of
"if" -> IF
"then" -> THEN
"else" -> ELSE
s -> IDENT s) : lexer cs'
| otherwise = lexer cs
|