Permalink
Browse files

improved parser

  • Loading branch information...
1 parent b8366b8 commit cb51a5dbacb5a9d0b80545964be0de3f9168765d Alexander Bernauer committed Nov 3, 2011
View
@@ -0,0 +1,10 @@
+OP_TRUE
+OP_TRUE;OP_FALSE
+
+
+;
+ ;
+
+; ;
+
+OP_TRUE
@@ -7,13 +7,15 @@ module Language.Bitcoin.Parser
-- import {{{1
import Language.Bitcoin.Types
import Language.Bitcoin.Utils (b2i, bsLength)
-import Text.ParserCombinators.Parsec (Parser, parse, spaces, endBy, eof, many, (<|>), (<?>), alphaNum, char, hexDigit, newline, unexpected)
+import Text.ParserCombinators.Parsec (Parser, parse, sepEndBy, eof, many, (<|>), (<?>), alphaNum, char, hexDigit, newline, unexpected, satisfy)
import Text.Parsec.Prim (parserFail)
import Control.Monad (liftM, when)
import qualified Data.ByteString as B
import qualified Data.Char as C
import Data.Word (Word8)
import Data.Int (Int32)
+import Data.Char (isSpace)
+import Data.Maybe (catMaybes)
-- run_parser :: String -> Code -> Either String Script {{{1
run_parser :: String -> Code -> Either String Script
@@ -24,24 +26,30 @@ run_parser source code =
script :: Parser Script
script = do
- spaces
- ops <- endBy operation separator
- eof
+ ops <- liftM catMaybes $ sepEndBy operation separator
+ spaces >> eof
return ops
-operation :: Parser Command
-operation = do
- command <- many (alphaNum <|> char '_' <?> "opcode")
- case command of
- "DATA" -> spaces >> liftM DATA hexString
- "KEY" -> keyOrSig KEY
- "SIG" -> keyOrSig SIG
- "OP_PUSHDATA" -> push
- "OP_PUSHDATA1" -> push1
- "OP_PUSHDATA2" -> push2
- "OP_PUSHDATA4" -> push4
- x -> opcode x
+separator :: Parser Char
+separator = spaces >> (newline <|> char ';')
+
+spaces :: Parser String
+spaces = many (satisfy (\c -> isSpace c && not (c =='\n')))
+operation :: Parser (Maybe Command)
+operation = do
+ command <- spaces >> many (alphaNum <|> char '_' <?> "opcode")
+ if command == ""
+ then return Nothing
+ else liftM Just $ case command of
+ "DATA" -> spaces >> liftM DATA hexString
+ "KEY" -> keyOrSig KEY
+ "SIG" -> keyOrSig SIG
+ "OP_PUSHDATA" -> push
+ "OP_PUSHDATA1" -> push1
+ "OP_PUSHDATA2" -> push2
+ "OP_PUSHDATA4" -> push4
+ x -> opcode x
keyOrSig :: (Int32 -> Command) -> Parser Command
keyOrSig createCommand = do
@@ -101,9 +109,6 @@ hexByte = do
lowerNibble <- hexDigit
return $ fromIntegral $ (C.digitToInt upperNibble) * 16 + (C.digitToInt lowerNibble)
-separator :: Parser Char
-separator = newline <|> char ';'
-
liftReadS :: ReadS a -> String -> Parser a
liftReadS f s =
let readings = f s in
@@ -14,18 +14,19 @@ import qualified Data.List as List
tests = TestLabel "Parser" $ TestList $ good ++ bad
goodCases = [
- ("OP_FALSE\n", [CmdOpcode OP_FALSE])
+ ("OP_FALSE", [CmdOpcode OP_FALSE])
+ , ("OP_FALSE\n", [CmdOpcode OP_FALSE])
, ("OP_FALSE;", [CmdOpcode OP_FALSE])
- , (" OP_FALSE;", [CmdOpcode OP_FALSE])
- , ("OP_FALSE;OP_TRUE;", [CmdOpcode OP_FALSE, CmdOpcode OP_TRUE])
- , ("OP_FALSE\nOP_TRUE;", [CmdOpcode OP_FALSE, CmdOpcode OP_TRUE])
- , ("OP_PUSHDATA 01 23;", [CmdOpcode $ OP_PUSHDATA Direct (bs 0x23)])
- , ("OP_PUSHDATA1 06 040815162342;", [CmdOpcode $ OP_PUSHDATA OneByte (bs 0x40815162342)])
- , ("OP_PUSHDATA2 0006 040815162342;", [CmdOpcode $ OP_PUSHDATA TwoBytes (bs 0x40815162342)])
- , ("OP_PUSHDATA4 00000006 040815162342;", [CmdOpcode $ OP_PUSHDATA FourBytes (bs 0x40815162342)])
- , ("DATA 040815162342;", [DATA $ bs 0x40815162342])
- , ("KEY 01;", [KEY 1])
- , ("SIG 01;", [SIG 1])
+ , (" OP_FALSE ; ", [CmdOpcode OP_FALSE])
+ , (" ; \n ;", [])
+ , ("OP_FALSE;OP_TRUE", [CmdOpcode OP_FALSE, CmdOpcode OP_TRUE])
+ , ("OP_PUSHDATA 01 23", [CmdOpcode $ OP_PUSHDATA Direct (bs 0x23)])
+ , ("OP_PUSHDATA1 06 040815162342", [CmdOpcode $ OP_PUSHDATA OneByte (bs 0x40815162342)])
+ , ("OP_PUSHDATA2 0006 040815162342", [CmdOpcode $ OP_PUSHDATA TwoBytes (bs 0x40815162342)])
+ , ("OP_PUSHDATA4 00000006 040815162342", [CmdOpcode $ OP_PUSHDATA FourBytes (bs 0x40815162342)])
+ , ("DATA 040815162342", [DATA $ bs 0x40815162342])
+ , ("KEY 01", [KEY 1])
+ , ("SIG 01", [SIG 1])
]
badCases = [
@@ -14,29 +14,29 @@ sig number = pad 64 $ bs $ -1 * number
testCases = [
(
- "OP_FALSE;", ([OP_FALSE], [])
+ "OP_FALSE", ([OP_FALSE], [])
),(
- "KEY 01;", (
+ "KEY 01", (
[OP_PUSHDATA Direct (key 1)],
[Keypair (key 1) (sig 1)]
)
),(
- "KEY 01;KEY 01;", (
+ "KEY 01;KEY 01", (
[OP_PUSHDATA Direct (key 1), OP_PUSHDATA Direct (key 1)],
[Keypair (key 1) (sig 1)]
)
),(
- "KEY 01;SIG 01;", (
+ "KEY 01;SIG 01", (
[OP_PUSHDATA Direct (key 1), OP_PUSHDATA Direct (sig 1)],
[Keypair (key 1) (sig 1)]
)
),(
- "KEY 01;KEY 02;", (
+ "KEY 01;KEY 02", (
[OP_PUSHDATA Direct (key 1), OP_PUSHDATA Direct (key 2)],
[Keypair (key 1) (sig 1), Keypair (key 2) (sig 2)]
)
),(
- "DATA 1234;", (
+ "DATA 1234", (
[OP_PUSHDATA Direct (bs 0x1234)],
[]
)

0 comments on commit cb51a5d

Please sign in to comment.