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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
-----------------------------------------------------------
-- Daan Leijen (c) 2000, daan@cs.uu.nl
-----------------------------------------------------------
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..."
|