diff options
author | Yuchen Pei <me@ypei.me> | 2017-12-20 15:41:29 +0100 |
---|---|---|
committer | Yuchen Pei <me@ypei.me> | 2017-12-20 15:41:29 +0100 |
commit | e91518a763157acad4ed3542ac16a46223038c87 (patch) | |
tree | 0b068673be90d4797400eebe3ebb0682f6e02568 /projects/06/Assembler.hs | |
parent | 4e2796decd37f5b07a1be0da08aaa6f5b28142b5 (diff) |
finished Project 6
Diffstat (limited to 'projects/06/Assembler.hs')
-rw-r--r-- | projects/06/Assembler.hs | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/projects/06/Assembler.hs b/projects/06/Assembler.hs index 3583121..fb69f07 100644 --- a/projects/06/Assembler.hs +++ b/projects/06/Assembler.hs @@ -3,14 +3,15 @@ import Data.Char (intToDigit) import Data.Map (Map) import qualified Data.Map as Map import Data.List.Split (splitOn, splitOneOf) +import System.Environment (getArgs) parseLine :: Map [Char] [Char] -> [Char] -> [Char] parseLine table (x:xs) - | x == '@' && (head xs `elem` ['0'..'9']) = (int2Bin16 $ read xs) ++ "\n" - | x == '@' = table Map.! xs ++ "\n" - | '=' `elem` (x:xs) && ';' `elem` (x:xs) = let [dest, comp, jump] = splitOneOf "=;" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ (parseJump jump) ++ "\n" - | '=' `elem` (x:xs) = let [dest, comp] = splitOn "=" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ "000" ++ "\n" - | ';' `elem` (x:xs) = let [comp, jump] = splitOn ";" (x:xs) in "111" ++ (parseComp comp) ++ "000" ++ (parseJump jump) ++ "\n" + | x == '@' && (head xs `elem` ['0'..'9']) = (int2Bin16 $ read xs) + | x == '@' = table Map.! xs + | '=' `elem` (x:xs) && ';' `elem` (x:xs) = let [dest, comp, jump] = splitOneOf "=;" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ (parseJump jump) + | '=' `elem` (x:xs) = let [dest, comp] = splitOn "=" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ "000" + | ';' `elem` (x:xs) = let [comp, jump] = splitOn ";" (x:xs) in "111" ++ (parseComp comp) ++ "000" ++ (parseJump jump) parseComp xs = case xs of "0" -> "0101010" @@ -71,25 +72,35 @@ initTable = Map.fromList $ (\(x, y) -> (x, int2Bin16 y)) <$> ("SP", 0):("LCL", 1 where rs = zipWith (,) ((\x -> 'R':(show x)) <$> [0..15]) [0..15] stripJunk :: [Char] -> [[Char]] -stripJunk xs = filter (not . null) $ (filter (not . (flip elem " \t")) . head . (splitOn "//")) <$> splitOn "\n" xs +stripJunk xs = filter (not . null) $ (filter (not . (flip elem " \t")) . head . (splitOn "//")) <$> lines (replCrWithNl xs) stripLabels :: [[Char]] -> [[Char]] stripLabels = filter (not . (elem '(')) +addLabels :: [[Char]] -> Int -> Map [Char] [Char] -> Map [Char] [Char] +addLabels [] _ table = table +addLabels ((hd:tl):rest) addr table + | hd == '(' = addLabels rest addr (Map.insert (init tl) (int2Bin16 addr) table) + | otherwise = addLabels rest (addr + 1) table + addSyms :: [[Char]] -> Int -> Int -> Map [Char] [Char] -> Map [Char] [Char] addSyms [] _ _ table = table addSyms ((hd:tl):rest) addr vaddr table | hd == '(' = addSyms rest addr vaddr (Map.insert (init tl) (int2Bin16 addr) table) - | hd == '@' && tl `Map.notMember` table = addSyms rest (addr + 1) (vaddr + 1) (Map.insert tl (int2Bin16 vaddr) table) + | hd == '@' && head tl `notElem` ['0'..'9'] && tl `Map.notMember` table = addSyms rest (addr + 1) (vaddr + 1) (Map.insert tl (int2Bin16 vaddr) table) | otherwise = addSyms rest (addr + 1) vaddr table parseCode :: [Char] -> [Char] -parseCode code = mconcat $ parseLine (addSyms codeWithoutJunk 0 16 initTable) <$> codeWithoutLabels +parseCode code = unlines $ parseLine (addSyms codeWithoutLabels 0 16 (addLabels codeWithoutJunk 0 initTable)) <$> codeWithoutLabels where codeWithoutJunk = stripJunk code codeWithoutLabels = stripLabels codeWithoutJunk -code0 = "// This file is part of www.nand2tetris.org\n// and the book \"The Elements of Computing Systems\"\n// by Nisan and Schocken, MIT Press.\n// File name: projects/06/add/Add.asm\n\n// Computes R0 = 2 + 3 (R0 refers to RAM[0])\n\n@2\nD=A\n@3\nD=D+A\n@0\nM=D" +replCrWithNl = fmap cr2nl + where cr2nl '\r' = '\n' + cr2nl c = c ---main = do - --code <- getContents - --putStr $ parseCode code +main = do + args <- getArgs + let filename = head args + code <- readFile $ filename + writeFile (head (splitOn "." filename) ++ ".hack") (parseCode code) |