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
|
module Dimacs.Scanner where
import Data.Char (isAlpha, isDigit, toLower)
import Numeric
data Token
= KW_sat
| KW_unsat
| VarNum Int
| VarNot
| EOF
deriving (Eq, Show)
keywords :: [(String, Token)]
keywords =
[ ("sat" , KW_sat)
, ("satisfiable" , KW_sat)
, ("unsat" , KW_unsat)
, ("unsatisfiable" , KW_unsat)
]
keyword :: String -> Token
keyword k = maybe (error $ "unknown keyword: " ++ k) id (lookup (map toLower k) keywords)
scan :: String -> [Token]
scan str = case str of
"" -> [EOF]
('-':s) -> VarNot : scan s
('0':s) -> scan s
('s':' ':s) -> scan s
('v':' ':s) -> scan s
('c':' ':s) -> scan $ tail $ dropWhile (\c -> c /= '\n') s
_ -> scan' str
where
scan' :: String -> [Token]
scan' "" = [EOF]
scan' x@(c:cs) | isDigit c = scanNum x
| isAlpha c = scanKeyword x
| otherwise = scan cs
scanKeyword :: String -> [Token]
scanKeyword cs =
let (key, rest) = span isAlpha cs
in keyword key : scan rest
scanNum :: String -> [Token]
scanNum cs =
let v = readInt cs
in case v of
[(num, rest)] -> VarNum num : scan rest
_ -> error "should not be possible"
|