Create Assembler module and implement some basic tokenizers
This commit is contained in:
@@ -26,6 +26,7 @@ executable MVM
|
|||||||
-- Modules included in this executable, other than Main.
|
-- Modules included in this executable, other than Main.
|
||||||
other-modules:
|
other-modules:
|
||||||
VirtualMachine
|
VirtualMachine
|
||||||
|
Assembler
|
||||||
Util
|
Util
|
||||||
|
|
||||||
-- LANGUAGE extensions used by modules in this package.
|
-- LANGUAGE extensions used by modules in this package.
|
||||||
|
|||||||
41
app/Assembler.hs
Normal file
41
app/Assembler.hs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
module Assembler (
|
||||||
|
tokenize
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Monoid as Monoid
|
||||||
|
import qualified VirtualMachine as VM (Op(..), Instruction, Command, instructionByOp)
|
||||||
|
import qualified Util as U
|
||||||
|
|
||||||
|
data Token = Operator VM.Op | KeywordLiteral String | IntLiteral Int deriving (Eq, Show)
|
||||||
|
|
||||||
|
type ConsumedChars = Int
|
||||||
|
data TokenizeResult = TokenizeResult Token ConsumedChars deriving (Eq, Show)
|
||||||
|
|
||||||
|
type Tokenizer = String -> Maybe TokenizeResult
|
||||||
|
|
||||||
|
type CaseSensitive = Bool
|
||||||
|
tokenizeKeyword :: CaseSensitive -> String -> Tokenizer
|
||||||
|
tokenizeKeyword _ _ [] = Nothing
|
||||||
|
tokenizeKeyword cs kwd input
|
||||||
|
| matches = Just $ TokenizeResult (KeywordLiteral . take len $ input) len
|
||||||
|
| otherwise = Nothing
|
||||||
|
where
|
||||||
|
len = length kwd
|
||||||
|
mapper = if cs then id else U.toLowerCase
|
||||||
|
zipped = zipWith (==) (mapper kwd) (mapper . take len $ input)
|
||||||
|
matches = and zipped && len == length zipped
|
||||||
|
|
||||||
|
tokenizeOperator :: VM.Op -> Tokenizer
|
||||||
|
tokenizeOperator op input = case keywordToken of
|
||||||
|
(Just (TokenizeResult _ consumed)) -> Just $ TokenizeResult (Operator op) consumed
|
||||||
|
Nothing -> Nothing
|
||||||
|
where keywordToken = tokenizeKeyword False (U.toLowerCase . show $ op) input
|
||||||
|
|
||||||
|
anyTokenizer :: [Tokenizer] -> Tokenizer
|
||||||
|
anyTokenizer tokenizers input = Monoid.getFirst . Monoid.mconcat . map Monoid.First $ sequenceA tokenizers input
|
||||||
|
|
||||||
|
tokenizeOperators :: Tokenizer
|
||||||
|
tokenizeOperators = anyTokenizer $ map tokenizeOperator [VM.Push ..]
|
||||||
|
|
||||||
|
tokenize :: Tokenizer
|
||||||
|
tokenize = tokenizeOperators
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
module Util (
|
module Util (
|
||||||
|
toLowerCase,
|
||||||
byteStr,
|
byteStr,
|
||||||
bytesStr
|
bytesStr
|
||||||
) where
|
) where
|
||||||
@@ -6,6 +7,10 @@ module Util (
|
|||||||
import Data.List
|
import Data.List
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Numeric (showHex)
|
import Numeric (showHex)
|
||||||
|
import qualified Data.Char as Char
|
||||||
|
|
||||||
|
toLowerCase :: String -> String
|
||||||
|
toLowerCase = map Char.toLower
|
||||||
|
|
||||||
bytesStr :: Int -> [Word8] -> String
|
bytesStr :: Int -> [Word8] -> String
|
||||||
bytesStr sparse = insertAtN '\n' (sparse*3) . intercalate " " . map byteStr
|
bytesStr sparse = insertAtN '\n' (sparse*3) . intercalate " " . map byteStr
|
||||||
|
|||||||
Reference in New Issue
Block a user