Beginnings of Parsec parser.
Chris Pressey
11 months ago
0 | 0 | module Language.ZOWIE.Parser where |
1 | ||
2 | import Text.ParserCombinators.Parsec | |
1 | 3 | |
2 | 4 | import Language.ZOWIE.State |
3 | 5 | |
7 | 9 | splitLines ('\n':rest) line = [reverse line] ++ (splitLines rest []) |
8 | 10 | splitLines (char:rest) line = splitLines rest (char:line) |
9 | 11 | |
12 | -- | |
13 | -- The grammar of a line is | |
14 | -- | |
15 | -- Line ::= Comment | "MOV" Operand "," Operand [Comment]. | |
16 | -- Operand ::= "R[R" Number "]" | "R" Number | Number. | |
17 | -- Comment ::= ";" anything. | |
18 | -- | |
19 | ||
20 | zowieLine = commentLine <|> instrLine | |
21 | ||
22 | commentLine :: Parser (Maybe Instruction) | |
23 | commentLine = do | |
24 | spaces | |
25 | string ";" | |
26 | many $ satisfy (\x -> x /= '\n') | |
27 | return Nothing | |
28 | ||
29 | instrLine :: Parser (Maybe Instruction) | |
30 | instrLine = do | |
31 | spaces | |
32 | string "MOV" | |
33 | dest <- operand | |
34 | spaces | |
35 | string "," | |
36 | src <- operand | |
37 | optional commentLine | |
38 | return $ Just $ Mov dest src | |
39 | ||
40 | operand = do | |
41 | spaces | |
42 | r <- indirect <|> direct <|> immediate | |
43 | return r | |
44 | ||
45 | indirect = do | |
46 | string "R[R" | |
47 | n <- number | |
48 | string "]" | |
49 | return $ Indirect n | |
50 | ||
51 | direct = do | |
52 | string "R" | |
53 | n <- number | |
54 | return $ Direct n | |
55 | ||
56 | immediate = do | |
57 | n <- number | |
58 | return $ Direct n | |
59 | ||
60 | number = do | |
61 | c <- digit | |
62 | cs <- many digit | |
63 | num <- return (read (c:cs) :: Integer) | |
64 | return num | |
65 | ||
66 | ||
10 | 67 | parseLines [] = [] |
11 | 68 | parseLines (line:lines) = |
12 | case parseLine line of | |
13 | Just instr -> | |
14 | (instr:parseLines lines) | |
15 | Nothing -> | |
69 | case parse zowieLine "" line of | |
70 | Left err -> | |
16 | 71 | parseLines lines |
17 | ||
18 | parseLine [] = Nothing | |
19 | parseLine (' ':rest) = parseLine rest | |
20 | parseLine ('M':'O':'V':rest) = Just $ Mov (Direct 0) (Immediate 0) | |
21 | ||
72 | Right result -> | |
73 | case result of | |
74 | Just instr -> | |
75 | (instr:parseLines lines) | |
76 | Nothing -> | |
77 | parseLines lines | |
22 | 78 | |
23 | 79 | parseZOWIE text = |
24 | 80 | let |