-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParser.hs
More file actions
54 lines (46 loc) · 1.26 KB
/
Copy pathParser.hs
File metadata and controls
54 lines (46 loc) · 1.26 KB
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
module Parser (parseInstruction, parseProgram) where
import Programs
import Text.ParserCombinators.ReadP
import Data.Char (isDigit)
nat :: ReadP Int
nat = read <$> munch1 isDigit
ws :: ReadP ()
ws = () <$ munch (\c -> c == ' ' || c == '\t')
instruction :: ReadP Instruction
instruction = halt +++ inc +++ dec
where
halt = H <$ string "HALT"
inc = do
_ <- char 'R'
r <- nat
_ <- string "+ -> L"
l <- nat
return (I r l)
dec = do
_ <- char 'R'
r <- nat
_ <- string "- -> L"
l <- nat
_ <- string ", L"
l' <- nat
return (D r l l')
labelledLine :: ReadP Instruction
labelledLine = do
_ <- char 'L'
_ <- nat
_ <- char ':'
ws
instruction
runParser :: ReadP a -> String -> Either String a
runParser p s = case readP_to_S (p <* eof) s of
[(x, "")] -> Right x
_ -> Left ("parse error: " ++ s)
parseInstruction :: String -> Either String Instruction
parseInstruction = runParser instruction
parseProgram :: String -> Either String Program
parseProgram "NULL" = Right (fromInstructions [])
parseProgram s = fmap fromInstructions (mapM (runParser labelledLine) ls)
where
ls = filter (not . null) $ case lines s of
("PROGRAM:" : rest) -> rest
other -> other