diff --git a/RainParse.hs b/RainParse.hs index 6398b5d..c92a116 100644 --- a/RainParse.hs +++ b/RainParse.hs @@ -180,15 +180,16 @@ stringLiteral where testToken (L.TokStringLiteral str) = Just str testToken _ = Nothing - replaceEscapes :: String -> String - replaceEscapes [] = [] - replaceEscapes ('\\':(c:cs)) = if c == 'n' then ('\n':replaceEscapes cs) else (c:replaceEscapes cs) - replaceEscapes (c:cs) = (c:replaceEscapes cs) + +replaceEscapes :: String -> String +replaceEscapes [] = [] +replaceEscapes ('\\':(c:cs)) = if c == 'n' then ('\n':replaceEscapes cs) else (c:replaceEscapes cs) +replaceEscapes (c:cs) = (c:replaceEscapes cs) literalCharacter :: RainParser A.LiteralRepr literalCharacter = do (m,c) <- getToken testToken - return $ A.ByteLiteral m c + return $ A.ByteLiteral m (replaceEscapes c) where testToken (L.TokCharLiteral c) = Just c testToken _ = Nothing @@ -206,6 +207,7 @@ integerLiteral = do {i <- integer ; return $ A.Literal (findMeta i) A.Int i} literal :: RainParser A.Expression literal = do {(lr, dim) <- stringLiteral ; return $ A.Literal (findMeta lr) (A.Array [dim] A.Byte) lr } + <|> do {c <- literalCharacter ; return $ A.Literal (findMeta c) A.Byte c} <|> integerLiteral <|> do {m <- reserved "true" ; return $ A.True m} <|> do {m <- reserved "false" ; return $ A.False m} diff --git a/RainParseTest.hs b/RainParseTest.hs index 9dfd485..8c98180 100644 --- a/RainParseTest.hs +++ b/RainParseTest.hs @@ -42,7 +42,7 @@ fail x = ExpFail x --Runs a parse test, given a tuple of: (source text, parser function, assert) testParsePass :: Show a => (String, RP.RainParser a , (a -> Assertion)) -> Assertion testParsePass (text,prod,test) - = do lexOut <- (L.runLexer "" text) + = do lexOut <- (L.runLexer "" text) case lexOut of Left m -> assertFailure $ "Parse error in:\n" ++ text ++ "\n***at: " ++ (show m) Right toks -> case (runParser parser emptyState "" toks) of @@ -166,6 +166,8 @@ testExprs = Cast (A.Chan A.DirInput nonShared $ A.UserDataType $ typeName "c") $ Var "b") ,failE ("?c:") ,failE (":?c") + + ,passE ("(48 + (uint8: src % 10)) + r",300,Dy (Dy (Lit $ intLiteral 48) A.Plus (Cast A.Byte $ Dy (Var "src") A.Rem (Lit $ intLiteral 10))) A.Plus (Var "r")) ] where passE :: (String,Int,ExprHelper) -> ParseTest A.Expression @@ -214,6 +216,17 @@ testLiteral = ,fail ("\"\"a",RP.literal) ,fail ("\"\\\"",RP.literal) + --Characters: + + ,pass ("'0'", RP.literal, assertPatternMatch "testLiteral 300" $ makeLiteralCharPattern '0') + ,pass ("'\\''", RP.literal, assertPatternMatch "testLiteral 300" $ makeLiteralCharPattern '\'') + ,pass ("'\\n'", RP.literal, assertPatternMatch "testLiteral 300" $ makeLiteralCharPattern '\n') + ,pass ("'\\\\'", RP.literal, assertPatternMatch "testLiteral 300" $ makeLiteralCharPattern '\\') + ,fail ("''",RP.literal) + ,fail ("'",RP.literal) + ,fail ("'\\",RP.literal) + ,fail ("'ab'",RP.literal) + ,fail ("'\\n\\n'",RP.literal) ] testRange :: [ParseTest A.Expression] diff --git a/TestUtil.hs b/TestUtil.hs index 18acf85..2327ef2 100644 --- a/TestUtil.hs +++ b/TestUtil.hs @@ -167,6 +167,11 @@ makeLiteralString str = A.Literal emptyMeta (A.Array [A.Dimension (length str)] makeLiteralStringPattern :: String -> Pattern makeLiteralStringPattern = (stopCaringPattern emptyMeta) . mkPattern . makeLiteralString +-- | Creates a 'Pattern' to match an 'A.Expression' instance. +-- All meta tags are ignored +makeLiteralCharPattern :: Char -> Pattern +makeLiteralCharPattern c = tag3 A.Literal DontCare A.Byte (tag2 A.ByteLiteral DontCare [c]) + -- | Asserts a comparison using a custom comparison function. -- @'assertCompareCustom' msg (==) x y@ will function the same (except for slightly different messages on failure) as @'assertEqual' msg x y@. assertCompareCustom ::