29 lines
1020 B
Haskell
29 lines
1020 B
Haskell
module Parser (
|
|
parse
|
|
) where
|
|
|
|
import Data.Word
|
|
import qualified Data.ByteString as B
|
|
import qualified Data.Map as Map
|
|
|
|
import qualified Command as C
|
|
import qualified Instruction as I
|
|
import qualified Util as U
|
|
|
|
parse :: B.ByteString -> Either String [C.Command]
|
|
parse = parseCommands . B.unpack
|
|
|
|
parseCommands :: [Word8] -> Either String [C.Command]
|
|
parseCommands [] = Right []
|
|
parseCommands code@(x:_) = case parseCommand code of
|
|
Just (cmd, rest) -> parseCommands rest >>= (\r -> return $ cmd : r)
|
|
Nothing -> Left $ "Unparseable byte: " ++ U.byteStr x ++ "\nIn following sequence:\n" ++ U.bytesStr 16 code
|
|
|
|
parseCommand :: [Word8] -> Maybe (C.Command, [Word8])
|
|
parseCommand [] = Nothing
|
|
parseCommand (opByte:xs) = do
|
|
let op = toEnum . fromIntegral $ opByte :: I.Op
|
|
instruction <- Map.lookup op I.instructionByOp
|
|
let noParams = I.noParams instruction
|
|
let params = map fromIntegral $ take noParams xs :: [Int]
|
|
return (C.Command instruction params, drop noParams xs) |