From d99e5d3cb1e3f0fb10f4221e32bc211c9d46fb37 Mon Sep 17 00:00:00 2001 From: Kamil Adam Date: Sat, 9 May 2020 22:12:01 +0200 Subject: [PATCH] Add Lexer for BrainFuck --- docs/CHANGELOG.md | 6 +- docs/NEWS.md | 2 +- docs/README.md | 6 +- docs/TODO.md | 2 +- helcam.cabal | 5 +- src/main/eta/helvm/helcam/BrainFuck/Token.hs | 35 ++++++++++ src/main/eta/helvm/helcam/BrainFuck/Tokens.hs | 30 +++++++++ src/test/eta/Test.hs | 3 + .../eta/helvm/helcam/BrainFuck/TokensTest.hs | 65 +++++++++++++++++++ 9 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 src/main/eta/helvm/helcam/BrainFuck/Token.hs create mode 100644 src/main/eta/helvm/helcam/BrainFuck/Tokens.hs create mode 100644 src/test/eta/helvm/helcam/BrainFuck/TokensTest.hs diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7209daa5d..431b070d4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,4 +1,8 @@ -# Revision history for helcam +# Revision history for HelCam + +## 0.2.0.0 -- 2020-05-16 + +* Add BrainFuck Lexer ## 0.1.0.0 -- 2020-05-09 diff --git a/docs/NEWS.md b/docs/NEWS.md index 702928e88..1be548b11 100644 --- a/docs/NEWS.md +++ b/docs/NEWS.md @@ -2,6 +2,6 @@ **New features.** -*We do not have **news** now.* +* Add BrainFuck Lexer For more see [CHANGELOG](CHANGELOG.md). diff --git a/docs/README.md b/docs/README.md index de17140c2..7492af170 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,11 +1,11 @@ # HELCAM -HELCAM - Heavenly Esoteric Little Concrete Absolute Machine for esoteric languages implemented in Haskell/Eta +**HELCAM** - Heavenly Esoteric Little Concrete Absolute Machine for Esoteric Languages implemented in Haskell/Eta ``` FOR everyone WHO want to run esoteric languages -THE HELCAM IS a Heavenly Esoteric Little Concrete Absolute Machine for esoteric languages implemented in Haskell/Eta -THAT is an Evaluator and an Interpreter for esoteric languages +THE HELCAM IS a Heavenly Esoteric Little Concrete Absolute Machine for Esoteric Languages implemented in Haskell/Eta +THAT is an Evaluator and an Interpreter for Esoteric Languages (EsoLangs) ``` ## For User diff --git a/docs/TODO.md b/docs/TODO.md index a6a04d9f3..9a608fada 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -3,7 +3,7 @@ **Future Features** Features to do: -* [ ] BrainFuck Tokenizer +* [x] BrainFuck Lexer * [ ] BrainFuck Evaluator * [ ] BrainFuck Interpreter diff --git a/helcam.cabal b/helcam.cabal index bdcadd837..db3dfbe01 100644 --- a/helcam.cabal +++ b/helcam.cabal @@ -2,7 +2,7 @@ -- documentation, see http://eta-lang.org/docs/ name: helcam -version: 0.0.0.0 +version: 0.2.0.0 synopsis: Heavenly Esoteric Little Concrete Absolute Machine description: Please see the README on GitHub at @@ -26,7 +26,9 @@ source-repository head library other-modules: + HelVM.HelCam.BrainFuck.Token exposed-modules: + HelVM.HelCam.BrainFuck.Tokens other-extensions: build-depends: base >=4.11 && <4.12 hs-source-dirs: src/main/eta @@ -37,6 +39,7 @@ test-suite helcam-test type: exitcode-stdio-1.0 main-is: Test.hs other-modules: + HelVM.HelCam.BrainFuck.TokensTest exposed-modules: other-extensions: build-depends: diff --git a/src/main/eta/helvm/helcam/BrainFuck/Token.hs b/src/main/eta/helvm/helcam/BrainFuck/Token.hs new file mode 100644 index 000000000..e533ccf7f --- /dev/null +++ b/src/main/eta/helvm/helcam/BrainFuck/Token.hs @@ -0,0 +1,35 @@ +module HelVM.HelCam.BrainFuck.Token where + +data Token = MoveR + | MoveL + | Inc + | Dec + | Output + | Input + | JmpPast + | JmpBack + deriving (Eq, Ord, Enum) + +type TokenList = [Token] + +instance Show Token where + show MoveR = ">" + show MoveL = "<" + show Inc = "+" + show Dec = "-" + show Output = "." + show Input = "," + show JmpPast = "[" + show JmpBack = "]" + +instance Read Token where + readsPrec _ ">" = [( MoveR , "")] + readsPrec _ "<" = [( MoveL , "")] + readsPrec _ "+" = [( Inc , "")] + readsPrec _ "-" = [( Dec , "")] + readsPrec _ "." = [( Output , "")] + readsPrec _ "," = [( Input , "")] + readsPrec _ "[" = [( JmpPast, "")] + readsPrec _ "]" = [( JmpBack, "")] + readsPrec _ _ = [] + diff --git a/src/main/eta/helvm/helcam/BrainFuck/Tokens.hs b/src/main/eta/helvm/helcam/BrainFuck/Tokens.hs new file mode 100644 index 000000000..12fcc3f6b --- /dev/null +++ b/src/main/eta/helvm/helcam/BrainFuck/Tokens.hs @@ -0,0 +1,30 @@ +module HelVM.HelCam.BrainFuck.Tokens where + +import HelVM.HelCam.BrainFuck.Token + +import Data.Maybe +import Text.Read + +newtype Tokens = Tokens TokenList + +-- + +instance Show Tokens where + show (Tokens tokens) = tokens >>= show + +charToString :: Char -> String +charToString = (:[]) + +instance Read Tokens where + readsPrec _ text = [( Tokens $ text >>= maybeToList . readMaybe . charToString, "")] + +-- + +tokenList :: Tokens -> TokenList +tokenList (Tokens tokens) = tokens + +readTokens :: String -> Tokens +readTokens text = read text :: Tokens + +tokenize :: String -> TokenList +tokenize = tokenList . readTokens diff --git a/src/test/eta/Test.hs b/src/test/eta/Test.hs index 698bf3db0..db25fbed5 100644 --- a/src/test/eta/Test.hs +++ b/src/test/eta/Test.hs @@ -1,5 +1,7 @@ module Main(main) where +import HelVM.HelCam.BrainFuck.TokensTest + import Test.HUnit testExample :: Test @@ -7,6 +9,7 @@ testExample = TestCase (assertEqual "test" "test" "test") testList :: Test testList = TestList [ TestLabel "testExample" testExample + , TestLabel "testsOfTokens" testsOfTokens ] main :: IO () diff --git a/src/test/eta/helvm/helcam/BrainFuck/TokensTest.hs b/src/test/eta/helvm/helcam/BrainFuck/TokensTest.hs new file mode 100644 index 000000000..478f36ab9 --- /dev/null +++ b/src/test/eta/helvm/helcam/BrainFuck/TokensTest.hs @@ -0,0 +1,65 @@ +module HelVM.HelCam.BrainFuck.TokensTest where + +import HelVM.HelCam.BrainFuck.Tokens + +import Test.HUnit + +helloWorldWithComments :: String +helloWorldWithComments = " \ +\ 1 +++++ +++ Set Cell #0 to 8 \ +\ 2 [ \ +\ 3 >++++ Add 4 to Cell #1; this will always set Cell #1 to 4 \ +\ 4 [ as the cell will be cleared by the loop \ +\ 5 >++ Add 4*2 to Cell #2 \ +\ 6 >+++ Add 4*3 to Cell #3 \ +\ 7 >+++ Add 4*3 to Cell #4 \ +\ 8 >+ Add 4 to Cell #5 \ +\ 9 <<<<- Decrement the loop counter in Cell #1 \ +\10 ] Loop till Cell #1 is zero \ +\11 >+ Add 1 to Cell #2 \ +\12 >+ Add 1 to Cell #3 \ +\13 >- Subtract 1 from Cell #4 \ +\14 >>+ Add 1 to Cell #6 \ +\15 [<] Move back to the first zero cell you find; this will \ +\16 be Cell #1 which was cleared by the previous loop \ +\17 <- Decrement the loop Counter in Cell #0 \ +\18 ] Loop till Cell #0 is zero \ +\19 \ +\20 The result of this is: \ +\21 Cell No : 0 1 2 3 4 5 6 \ +\22 Contents: 0 0 72 104 88 32 8 \ +\23 Pointer : ^ \ +\24 \ +\25 >>. Cell #2 has value 72 which is 'H' \ +\26 >---. Subtract 3 from Cell #3 to get 101 which is 'e' \ +\27 +++++ ++..+++. Likewise for 'llo' from Cell #3 \ +\28 >>. Cell #5 is 32 for the space \ +\29 <-. Subtract 1 from Cell #4 for 87 to give a 'W' \ +\30 <. Cell #3 was set to 'o' from the end of 'Hello' \ +\31 +++.----- -.----- ---. Cell #3 for 'rl' and 'd' \ +\32 >>+. Add 1 to Cell #5 gives us an exclamation point \ +\33 >++. And finally a newline from Cell #6 \ +\" + +helloWorld :: String +helloWorld = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++." + +helloWorldAsList :: String +helloWorldAsList = "[+,+,+,+,+,+,+,+,[,>,+,+,+,+,[,>,+,+,>,+,+,+,>,+,+,+,>,+,<,<,<,<,-,],>,+,>,+,>,-,>,>,+,[,<,],<,-,],>,>,.,>,-,-,-,.,+,+,+,+,+,+,+,.,.,+,+,+,.,>,>,.,<,-,.,<,.,+,+,+,.,-,-,-,-,-,-,.,-,-,-,-,-,-,-,-,.,>,>,+,.,>,+,+,.]" + +-------------------------------------------------------------------------------- + +testHelloWorld :: Test +testHelloWorld = TestCase (assertEqual "testHelloWorld" helloWorld (show $ readTokens helloWorld)) + +testHelloWorldWithComments :: Test +testHelloWorldWithComments = TestCase (assertEqual "testHelloWorldWithComments" helloWorld (show $ readTokens helloWorldWithComments)) + +testTokenAsList :: Test +testTokenAsList = TestCase (assertEqual "testTokenAsList" helloWorldAsList (show $ tokenList $ readTokens helloWorldWithComments)) + +testsOfTokens :: Test +testsOfTokens = TestList [ TestLabel "testHelloWorld" testHelloWorld + , TestLabel "testHelloWorldWithComments" testHelloWorldWithComments + , TestLabel "testTokenAsList" testTokenAsList + ] \ No newline at end of file