-----------------------------------------------------------
-- Daan Leijen (c) 2000, [email protected]
-----------------------------------------------------------
module Main where
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec.Token
import Text.ParserCombinators.Parsec.Language
-----------------------------------------------------------
--
-----------------------------------------------------------
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> do{ putStr "parse error at "
; print err
}
Right x -> print x
runLex :: Show a => Parser a -> String -> IO ()
runLex p
= run (do{ whiteSpace lang
; x <- p
; eof
; return x
}
)
-----------------------------------------------------------
-- Sequence and choice
-----------------------------------------------------------
simple :: Parser Char
simple = letter
openClose :: Parser Char
openClose = do{ char '('
; char ')'
}
matching:: Parser ()
matching= do{ char '('
; matching
; char ')'
; matching
}
<|> return ()
-- Predictive parsing
testOr = do{ char '('; char 'a'; char ')' }
<|> do{ char '('; char 'b'; char ')' }
testOr1 = do{ char '('
; char 'a' <|> char 'b'
; char ')'
}
testOr2 = try (do{ char '('; char 'a'; char ')' })
<|> do{ char '('; char 'b'; char ')' }
-- Semantics
nesting :: Parser Int
nesting = do{ char '('
; n <- nesting
; char ')'
; m <- nesting
; return (max (n+1) m)
}
<|> return 0
word1 :: Parser String
word1 = do{ c <- letter
; do{ cs <- word1
; return (c:cs)
}
<|> return [c]
}
-----------------------------------------------------------
--
-----------------------------------------------------------
word :: Parser String
word = many1 (letter <?> "") <?> "word"
sentence :: Parser [String]
sentence = do{ words <- sepBy1 word separator
; oneOf ".?!" <?> "end of sentence"
; return words
}
separator :: Parser ()
separator = skipMany1 (space <|> char ',' <?> "")
-----------------------------------------------------------
-- Tokens
-----------------------------------------------------------
lang = makeTokenParser
(haskellStyle{ reservedNames = ["return","total"]})
-----------------------------------------------------------
--
-----------------------------------------------------------
expr = buildExpressionParser table factor
<?> "expression"
table = [[op "*" (*) AssocLeft, op "/" div AssocLeft]
,[op "+" (+) AssocLeft, op "-" (-) AssocLeft]
]
where
op s f assoc
= Infix (do{ symbol lang s; return f} <?> "operator") assoc
factor = parens lang expr
<|> natural lang
<?> "simple expression"
test1 = do{ n <- natural lang
; do{ symbol lang "+"
; m <- natural lang
; return (n+m)
}
<|> return n
}
-----------------------------------------------------------
--
-----------------------------------------------------------
{-
receipt ::= product* total
product ::= "return" price ";"
| identifier price ";"
total ::= price "total"
price ::= natural "." digit digit
-}
receipt :: Parser Bool
receipt = do{ ps <- many produkt
; p <- total
; return (sum ps == p)
}
produkt = do{ reserved lang "return"
; p <- price
; semi lang
; return (-p)
}
<|> do{ identifier lang
; p <- price
; semi lang
; return p
}
<?> "product"
total = do{ p <- price
; reserved lang "total"
; return p
}
price :: Parser Int
price = lexeme lang (
do{ ds1 <- many1 digit
; char '.'
; ds2 <- count 2 digit
; return (convert 0 (ds1 ++ ds2))
})
<?> "price"
where
convert n [] = n
convert n (d:ds) = convert (10*n + digitToInt d) ds
digitToInt :: Char -> Int
digitToInt d = fromEnum d - fromEnum '0'
main :: IO ()
main = putStrLn "I'm only a dummy..."
|