3a_asm: 'sum.s' is parseable now :)
[calu.git] / 3a_asm / Main.hs
1 -- as for deep thoughts ISA
2 -----------------------------------------------------------------------------
3
4
5 import DT
6 import DTFormat
7
8 import Control.Applicative hiding ((<|>),many)
9
10 import System.IO
11 import System.Environment
12 import Text.Printf
13 import Text.Parsec
14 import Text.Parsec.String
15 import Text.Parsec.Combinator
16 import qualified Data.Map as M
17 import Data.List
18 import Data.Word
19 import qualified Data.ByteString.Lazy as BL
20 import Control.Monad
21
22
23 main :: IO ()
24 main = do
25         args <- getArgs
26         content <- getContents
27         let src = (filter (((/=) "") . snd) $ (zip [1..] (lines content)))
28         let (dict,formatedsrc) = convertDTF src NoState 0x00 0x00 []
29         printf "\nlabels:\n"
30         sequence_ [printf "%10s @ 0x%08x\n" l a | (l,a) <- (reverse dict)]
31         printf "\nparsed asm:\n"
32         sequence_ [printf "%s" (show x) | x <- formatedsrc]
33         let parsed = parseInstr dict formatedsrc
34         printf "\nafter parsing the instructions:\n"
35         sequence_ [printf "%s" (show x) | x <- parsed]
36
37
38 parseInstr :: [DictLabel] -> [DTF] -> [DTF]
39 parseInstr _ [] = []
40 parseInstr dict ((DTF_InstrToParse a instr c l s):xs) =
41         (DTF_Instr a bytecode c l s):(parseInstr dict xs)
42         where
43         bytecode = case (parse (instruction dict) "" (instr++"\n")) of
44                 Left err -> error ("couldn't parse Instruction: " ++ instr ++ "\n" ++ show err)
45                 Right x -> x
46 parseInstr dict (x:xs) = x:(parseInstr dict xs)
47
48
49 type Counter = Word32
50
51 inc :: Counter -> Counter
52 inc = ((+) 4)
53
54
55 convertDTF :: [(Int,String)] -> DT_State -> Counter -> Counter -> [DictLabel] -> ([DictLabel], [DTF])
56 convertDTF [] _ _ _ d = (d,[])
57 convertDTF ((lno,str):xs) state datacnt instrcnt dict = (newdict, (actlist newdtf))
58         where
59         actlist (DTF_Org _) = next
60         actlist (DTF_State _) = next
61         actlist y = y:next
62
63         (newdict,next) = convertDTF xs (nstate newdtf) (ndatacnt newdtf) (ninstrcnt newdtf) (ndict newdtf)
64
65         ndatacnt (DTF_Org adr)
66                 | state == InData = adr
67                 | otherwise = datacnt
68         ndatacnt (DTF_Data _ _ _ _ _) = inc datacnt
69         ndatacnt _ = datacnt
70
71         ninstrcnt (DTF_Org adr)
72                 | state == InText = adr
73                 | otherwise = instrcnt
74         ninstrcnt (DTF_Instr _ _ _ _ _) = inc instrcnt
75         ninstrcnt (DTF_InstrToParse _ _ _ _ _) = inc instrcnt
76         ninstrcnt _ = instrcnt
77
78         nstate (DTF_State s) = s
79         nstate _ = state
80
81         ndict (DTF_Label l _ a) = dict `add_label` (l,a)
82         ndict (DTF_SectionToDet a _ _ l _) = dict `add_label` (l,a)
83         ndict (DTF_InstrToParse a _ _ l _) = dict `add_label` (l,a)
84         ndict (DTF_Data a _ _ l _) = dict `add_label` (l,a)
85         ndict (DTF_Instr a _ _ l _) = dict `add_label` (l,a)
86         ndict _ = dict
87
88         newdtf = case (parse parseDTFLine "" (str++"\n")) of
89                 Left err -> error ("couldn't parse line " ++ (show lno) ++ ": " ++ (show err))
90                 Right (DTF_SectionToDet _ v c l s) ->
91                         case state of
92                                 NoState -> error "missing .data or .text"
93                                 InData -> (DTF_Data datacnt v c l s)
94                                 InText -> (DTF_Instr instrcnt v c l s)
95                 Right (DTF_InstrToParse _ v c l s) ->
96                         (DTF_InstrToParse instrcnt v c l s)
97                 Right y@(DTF_Org _) ->
98                         case state of
99                                 NoState -> error "missing .data or .text"
100                                 _ -> y
101                 Right (DTF_Label l c _) ->
102                         case state of
103                                 NoState -> error "missing .data or .text"
104                                 InData -> (DTF_Label l c datacnt)
105                                 InText -> (DTF_Label l c instrcnt)
106                 Right z -> z -- DTF_Comment, DTF_State
107
108
109
110 testDTF :: String -> IO ()
111 testDTF input =
112         case (parse parseDTFLine "" (input++"\n")) of
113                 Left err -> do { putStr "failz ;(\n"; print err}
114                 Right x -> do { print x }
115
116 parseDTFLine :: Parser DTF
117 parseDTFLine = foldl1 (<|>) (fmap try lineFormats) <* char '\n'
118
119 lineFormats = [lf_sdata, lf_stext, lf_org, lf_data, lf_comment, lf_toparse, lf_label]
120
121 -- helper
122 parseLabel :: Parser String
123 parseLabel = do
124         label <- letter 
125         labels <- many $ (letter <|> digit <|> char '_')
126         char ':'
127         return $ (label:labels)
128
129 parseComment :: Parser String
130 parseComment = do
131         skipMany space
132         char ';'
133         comment <- many $ noneOf "\n"
134         return $ comment
135
136 parseConst :: Parser Word32
137 parseConst = do
138         skipMany space
139         -- TODO: only decimal and hex (since this is supported by read)
140         -- TODO: howto check too big values? atm they get truncated
141         str <- try(do pref <- string "0x"; z <- many1 hexDigit; return $ (pref ++ z)) <|> (many1 digit)
142         let val = read str
143         return $ val
144
145 -- teh pars0rs
146 lf_data = do
147         l <- try (parseLabel) <|> string ""
148         skipMany space
149         fill <- string ".fill "
150         -- TODO: atm 32bit imm only
151         code <- many1 $ noneOf "\n;"
152         -- TODO: this is quite ugly here :/
153         let (Right val) = parse parseConst "" code
154         comment <- try(parseComment) <|> parseMySpaces
155         return $ DTF_SectionToDet 0 val (fill ++ code) l comment
156
157 lf_comment = do
158         comment <- parseComment
159         return $ DTF_Comment comment
160
161 lf_label = do
162         l <- parseLabel
163         comment <- try(parseComment) <|> parseMySpaces
164         return $ DTF_Label l comment 0
165
166 lf_toparse = do
167         l <- try(parseLabel) <|> string ""
168         skipMany space
169         code <- many1 $ noneOf "\n;"
170         comment <- try(parseComment) <|> parseMySpaces
171         return $ DTF_InstrToParse 0 code code l comment
172
173 lf_org = do
174         skipMany space
175         string ".org"
176         val <- parseConst
177         parseMySpaces
178         return $ DTF_Org val
179
180 lf_sdata = do
181         skipMany space
182         string ".data"
183         parseMySpaces
184         return $ DTF_State InData
185
186 lf_stext = do
187         skipMany space
188         string ".text"
189         parseMySpaces
190         return $ DTF_State InText
191