From 8850934eaa1cfdc698181abe1a9c9011a090bc5a Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Wed, 3 Jan 2024 17:08:30 +0100 Subject: [PATCH 01/14] feat(parsing): beginning of function parsing --- LobsterLang/src/Parse.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 83ebe38..b678214 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -303,3 +303,11 @@ interpretateLisp value stack = case AstEval.sexprToAst value of -- Just (res, _) -> case AstEval.sexprToAst res of -- Nothing -> (Left "Cannot convert input in AST", []) -- Just value -> AstEval.evalAst stack value + +parseFunc :: Parser AST.Define +parseFunc = Parser f + where + f :: Position -> String -> Either String (AST.Define, String, Position) + f pos s = case runParser (parseAnyString "func") pos s of + Left err -> Left err + Right (_, s', pos') -> Right ((AST.Define (parseElem parseString) (parseFuncValue)), s', pos') From 3c8be58dc06575634d04475818e4544eae2fae2b Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Mon, 8 Jan 2024 12:04:07 +0100 Subject: [PATCH 02/14] feat(parsing): parsing for function name --- LobsterLang/src/Parse.hs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index b678214..d2d3bf2 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -31,7 +31,7 @@ module Parse ( parseSpace, parseLine, interpretateLisp, - -- parseTuple, + parseDefineFn, ) where import SExpr @@ -304,10 +304,24 @@ interpretateLisp value stack = case AstEval.sexprToAst value of -- Nothing -> (Left "Cannot convert input in AST", []) -- Just value -> AstEval.evalAst stack value -parseFunc :: Parser AST.Define -parseFunc = Parser f +parseDefineFn :: Parser AST.Ast +parseDefineFn = (Parser parseFn) *> (Parser defineFn) where - f :: Position -> String -> Either String (AST.Define, String, Position) - f pos s = case runParser (parseAnyString "func") pos s of + parseFn :: Position -> String -> Either String (String, String, Position) + parseFn pos s = case runParser (parseAnyString "fn") pos s of Left err -> Left err - Right (_, s', pos') -> Right ((AST.Define (parseElem parseString) (parseFuncValue)), s', pos') + Right (res, s', pos') -> Right (res, s', pos') + defineFn :: Position -> String -> Either String (AST.Ast, String, Position) + defineFn s pos = case runParser parseString s pos of + Left err -> Left err + Right (res, s', pos') -> Right (AST.Define res (AST.Value 1), s', pos') + + + + + + -- defineFn pos s = AST.Define <$> (Parser res) (AST.Value <$> 1) + -- where + -- (res, s', pos') = parseString + -- -- parseFnValue :: AST.FunctionValue + -- -- parseFnValue = From 1583309e55140c18a522dd99789c06bfb732f958 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Mon, 8 Jan 2024 15:24:49 +0100 Subject: [PATCH 03/14] feat(parsing): parsing of function parameters --- LobsterLang/src/Parse.hs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index d2d3bf2..22f7c91 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -216,9 +216,9 @@ parseValue = Value <$> parseElem parseInt parseList :: Parser a -> Parser [a] parseList parser = parseStart *> parseListValue <* parseEnd where - parseEnd = parseChar ')' <* parseSpace <* parseLine + parseEnd = parseAnyString "|)" <* parseSpace <* parseLine parseListValue = parseSpace *> parseMany (parseElem parser) <* parseSpace - parseStart = parseSpace *> parseChar '(' + parseStart = parseSpace *> parseAnyString "(|" -- | Parse any character from a String -- Return a Parser that parse every character from a String @@ -314,11 +314,17 @@ parseDefineFn = (Parser parseFn) *> (Parser defineFn) defineFn :: Position -> String -> Either String (AST.Ast, String, Position) defineFn s pos = case runParser parseString s pos of Left err -> Left err - Right (res, s', pos') -> Right (AST.Define res (AST.Value 1), s', pos') - - - + Right (res, s', pos') -> case runParser parseFunctionValue pos' s' of + Left err -> Left err + Right (res', s'', pos'') -> Right (AST.Define res res', s'', pos'') +parseFunctionValue :: Parser AST.Ast +parseFunctionValue = Parser parseParams + where + parseParams :: Position -> String -> Either String (AST.Ast, String, Position) + parseParams s pos = case runParser (parseList parseString) s pos of + Left err -> Left err + Right (res, s', pos') -> Right (AST.FunctionValue res (AST.Value 1) Nothing, s', pos') -- defineFn pos s = AST.Define <$> (Parser res) (AST.Value <$> 1) -- where From ce9ab6e41907665aa5f488d96396c909916324c8 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Tue, 9 Jan 2024 15:39:58 +0100 Subject: [PATCH 04/14] refactor(parsing): change lists separator to comma --- LobsterLang/src/Parse.hs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 22f7c91..3f1800a 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -211,13 +211,33 @@ parseSymbol = Symbol <$> parseElem parseString parseValue :: Parser SExpr parseValue = Value <$> parseElem parseInt +parseListElem :: Parser a -> Parser [a] +parseListElem parserA = Parser (parseFirst parserA) + where + parseFirst :: Parser a -> Position -> String -> Either String ([a], String, Position) + parseFirst parser pos s = case runParser parser pos s of + Left _ -> Right ([], s, pos) + Right (res, s', pos') -> case runParser (parseChar ',') pos' s' of + Left _ -> Right ([res], s, pos) + Right _ -> case (parseOthers parser pos' s') of + Left err -> Left err + Right (res', s'', pos'') -> Right(res : res', s'', pos'') + parseOthers :: Parser a -> Position -> String -> Either String ([a], String, Position) + parseOthers parser pos s = case runParser (parseChar ',') pos s of + Left _ -> Right ([], s, pos) + Right (_, s', pos') -> case runParser parser pos' s' of + Left err -> Left err + Right (res, s'', pos'') -> case (parseOthers parser pos'' s'') of + Left err -> Left err + Right (res', s''', pos''') -> Right (res : res', s''', pos''') + -- | Parse a list of element -- Return a Parser of list `element` that start with a '(' and end with a ')' parseList :: Parser a -> Parser [a] parseList parser = parseStart *> parseListValue <* parseEnd where parseEnd = parseAnyString "|)" <* parseSpace <* parseLine - parseListValue = parseSpace *> parseMany (parseElem parser) <* parseSpace + parseListValue = parseSpace *> parseListElem parser <* parseSpace parseStart = parseSpace *> parseAnyString "(|" -- | Parse any character from a String From 47c024eeb04526ab9b1729e1301f16b66eb2fa06 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Wed, 10 Jan 2024 10:43:49 +0100 Subject: [PATCH 05/14] fix(parsing): remove useless condition in parseListElem --- LobsterLang/src/Parse.hs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 3f1800a..64707f0 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -217,11 +217,9 @@ parseListElem parserA = Parser (parseFirst parserA) parseFirst :: Parser a -> Position -> String -> Either String ([a], String, Position) parseFirst parser pos s = case runParser parser pos s of Left _ -> Right ([], s, pos) - Right (res, s', pos') -> case runParser (parseChar ',') pos' s' of - Left _ -> Right ([res], s, pos) - Right _ -> case (parseOthers parser pos' s') of - Left err -> Left err - Right (res', s'', pos'') -> Right(res : res', s'', pos'') + Right (res, s', pos') -> case (parseOthers parser pos' s') of + Left err -> Left err + Right (res', s'', pos'') -> Right(res : res', s'', pos'') parseOthers :: Parser a -> Position -> String -> Either String ([a], String, Position) parseOthers parser pos s = case runParser (parseChar ',') pos s of Left _ -> Right ([], s, pos) @@ -345,9 +343,3 @@ parseFunctionValue = Parser parseParams parseParams s pos = case runParser (parseList parseString) s pos of Left err -> Left err Right (res, s', pos') -> Right (AST.FunctionValue res (AST.Value 1) Nothing, s', pos') - - -- defineFn pos s = AST.Define <$> (Parser res) (AST.Value <$> 1) - -- where - -- (res, s', pos') = parseString - -- -- parseFnValue :: AST.FunctionValue - -- -- parseFnValue = From d93355cb5de3c55fe87fde8c60d3480c85281aaa Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Wed, 10 Jan 2024 11:19:47 +0100 Subject: [PATCH 06/14] test(parsing): tests for the parseList --- LobsterLang/src/Parse.hs | 8 ++++---- LobsterLang/test/ParseSpec.hs | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 LobsterLang/test/ParseSpec.hs diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 64707f0..3d0b874 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -106,9 +106,9 @@ parseChar :: Char -> Parser Char parseChar c = Parser (f c) where f :: Char -> Position -> String -> Either String (Char, String, Position) - f '\n' (row, col) (x:xs) = if '\n' == x then Right ('\n', xs, (row + 1, 0)) else Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col) - f char (row, col) (x:xs) = if char == x then Right (char, xs, (row, col + 1)) else Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col) - f _ (row, col) _ = Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col) + f '\n' (row, col) (x:xs) = if '\n' == x then Right ('\n', xs, (row + 1, 0)) else Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col ++ "'") + f char (row, col) (x:xs) = if char == x then Right (char, xs, (row, col + 1)) else Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col ++ "'") + f _ (row, col) _ = Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col ++ "'") -- | Parse with the first or the second parser -- Takes two parsers @@ -244,7 +244,7 @@ parseAnyChar :: String -> Parser Char parseAnyChar s = Parser (f s) where f :: String -> Position -> String -> Either String (Char, String, Position) - f [] (row, col) _ = Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col) + f [] (row, col) _ = Left ("Error on parsing on '" ++ show row ++ "' '" ++ show col ++ "'") f (x:xs) pos s' = case parsed of Left _ -> runParser (parseAnyChar xs) pos s' _ -> parsed diff --git a/LobsterLang/test/ParseSpec.hs b/LobsterLang/test/ParseSpec.hs new file mode 100644 index 0000000..f26f195 --- /dev/null +++ b/LobsterLang/test/ParseSpec.hs @@ -0,0 +1,27 @@ +{- +-- EPITECH PROJECT, 2024 +-- GLaDOS +-- File description: +-- ParseSpec +-} + +module ParseSpec where + +import Test.Hspec +import Parse + +spec :: Spec +spec = do + describe "Parser Tests" $ do + it "Check parseList String Success" $ do + runParser (parseList parseString) (0,0) "(| a, b ,c, d |)" `shouldBe` Right(["a", "b", "c", "d"], "", (0,17)) + it "Check parseList Error missing comma" $ do + runParser (parseList parseString) (0,0) "(| a b |)" `shouldBe` Left "Error on parsing on '0' '5'" + it "Check parseList Error end with comma" $ do + runParser (parseList parseString) (0,0) "(|a, |)" `shouldBe` Left "Error on parsing on '0' '5'" + it "Check parseList Error starting with comma" $ do + runParser (parseList parseString) (0,0) "(|,a|)" `shouldBe` Left "Error on parsing on '0' '2'" + it "Check parseList Error missing starting bracket" $ do + runParser (parseList parseString) (0,0) "a, b|)" `shouldBe` Left "Error on parsing on '0' '0'" + it "Check parseList Error missing ending bracket" $ do + runParser (parseList parseString) (0,0) "(|a, b" `shouldBe` Left "Error on parsing on '0' '6'" From cb1423d343876a1ea1de35c0899e1075065c60a0 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Fri, 12 Jan 2024 09:51:06 +0100 Subject: [PATCH 07/14] feat(parsing): parser for conditions --- LobsterLang/src/Parse.hs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 3d0b874..5766d39 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -343,3 +343,27 @@ parseFunctionValue = Parser parseParams parseParams s pos = case runParser (parseList parseString) s pos of Left err -> Left err Right (res, s', pos') -> Right (AST.FunctionValue res (AST.Value 1) Nothing, s', pos') + +-- parseBracket :: Parser AST.Ast +-- parseBracket = parseStart *> parseLobster <* parseEnd +-- where +-- parseEnd = parseAnyChar '}' <* parseSpace <* parseLine +-- parseStart = parseSpace *> parseAnyChar '{' + +parseCond :: Parser AST.Ast +parseCond = parseAnyString "if" *> Parser p + where + parseIf :: Position -> String -> Either String (AST.Ast, String, Position) + parseIf pos s = case runParser parseExpression pos s of + Left err -> Left err + Right (res, s', pos') -> case parseLobster pos' s' of + Left err -> Left err + Right (res', s'', pos'') -> case runParser parseElse pos'' s'' of + Left err -> Left err + Right (res'', s''', pos''') -> Right ((AST.Cond res res' res''), s''', pos''') + parseElse :: Position -> String -> Either String ((Maybe AST.Ast), String, Position) + parseElse pos s = case runParser (parseAnyString "else") pos s of + Left _ -> Right (Nothing, s, pos) + Right (_, s', pos') -> case runParser parseBracket of + Left err -> Left err + Right (res, s'', pos') -> Right ((Just res), s'', pos'') From 76537ca3521207d8650b4bcf8ef44fc1e8433e4a Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Fri, 12 Jan 2024 10:19:10 +0100 Subject: [PATCH 08/14] feat(parsing): parsing fonction definition in brackets --- LobsterLang/src/Parse.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 73ccc6b..03b5f01 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -425,7 +425,9 @@ parseFunctionValue = Parser parseParams parseParams :: Position -> String -> Either String (AST.Ast, String, Position) parseParams s pos = case runParser (parseList parseString) s pos of Left err -> Left err - Right (res, s', pos') -> Right (AST.FunctionValue res (AST.Value 1) Nothing, s', pos') + Right (res, s', pos') -> case runParser parseBracket pos' s' of + Left err -> Left err + Right (res', s'', pos'') -> Right (AST.FunctionValue res res' Nothing, s'', pos'') parseBracket :: Parser AST.Ast parseBracket = parseStart *> parseAst <* parseEnd From 695fba1c1ce7ba015330f359407c7a38c7608532 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Fri, 12 Jan 2024 10:23:42 +0100 Subject: [PATCH 09/14] feat(parsing): add the function and condition parsing to parseAst --- LobsterLang/src/Parse.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 03b5f01..b50b5e2 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -396,7 +396,9 @@ parseUnaryOperation = Parser f parseAst :: Parser AST.Ast parseAst = parseWhiteSpace *> ( - parseDefineValue + parseDefineFn + <|> parseCond + <|> parseDefineValue <|> parseExpr <|> parseBool <|> parseUnaryOperation From 6b49da89d860782ce3f4f5ec413e3ec7987a4347 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Fri, 12 Jan 2024 15:15:13 +0100 Subject: [PATCH 10/14] feat(parsing): parseCond now handle else if --- LobsterLang/src/Parse.hs | 41 ++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index b50b5e2..0abde35 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -38,7 +38,8 @@ module Parse ( parseWhiteSpace, errorParsing, parseDefineFn, - parseCond + parseCond, + parseCmpString ) where import qualified AST @@ -343,6 +344,14 @@ parseAnyString s = Parser (f s s) Right (_, s'', pos') -> f xs str pos' s'' f [] str pos s' = Right (str, s', pos) +parseCmpString :: String -> Parser String +parseCmpString s = parseWhiteSpace *> Parser (f s) <* parseWhiteSpace + where + f :: String -> Position -> String -> Either String (String, String, Position) + f str pos s' = case runParser parseString pos s' of + Left err -> Left err + Right (res, s'', pos') -> if str == res then Right (res, s'', pos') else Left (errorParsing pos') + -- | Return a Parser that parse a Bool (#f or #t) parseBool :: Parser AST.Ast parseBool = AST.Boolean <$> (parseTrue <|> parseFalse) <* parseWhiteSpace @@ -408,12 +417,8 @@ parseAst = parseWhiteSpace *> ) parseDefineFn :: Parser AST.Ast -parseDefineFn = (Parser parseFn) *> (Parser defineFn) +parseDefineFn = parseCmpString "fn" *> (Parser defineFn) where - parseFn :: Position -> String -> Either String (String, String, Position) - parseFn pos s = case runParser (parseAnyString "fn") pos s of - Left err -> Left err - Right (res, s', pos') -> Right (res, s', pos') defineFn :: Position -> String -> Either String (AST.Ast, String, Position) defineFn s pos = case runParser parseString s pos of Left err -> Left err @@ -434,11 +439,11 @@ parseFunctionValue = Parser parseParams parseBracket :: Parser AST.Ast parseBracket = parseStart *> parseAst <* parseEnd where - parseEnd = parseChar '}' <* parseWhiteSpace - parseStart = parseWhiteSpace *> parseChar '{' + parseEnd = parseWhiteSpace *> parseChar '}' <* parseWhiteSpace + parseStart = parseWhiteSpace *> parseChar '{' <* parseWhiteSpace parseCond :: Parser AST.Ast -parseCond = parseAnyString "if" *> Parser parseIf +parseCond = parseCmpString "if" *> Parser parseIf where parseIf :: Position -> String -> Either String (AST.Ast, String, Position) parseIf pos s = case runParser parseExpr pos s of @@ -446,17 +451,17 @@ parseCond = parseAnyString "if" *> Parser parseIf Right (res, s', pos') -> case runParser parseBracket pos' s' of Left err -> Left err Right (res', s'', pos'') -> case runParser parseElse pos'' s'' of - Left err -> Left err - Right (res'', s''', pos''') -> Right ((AST.Cond res res' res''), s''', pos''') - parseElse :: Parser (Maybe AST.Ast) - parseElse = Parser f + Left _ -> Right ((AST.Cond res res' Nothing), s'', pos'') + Right (res'', s''', pos''') -> Right ((AST.Cond res res' (Just res'')), s''', pos''') + parseElse :: Parser AST.Ast + parseElse = parseCmpString "else" *> Parser p where - f :: Position -> String -> Either String ((Maybe AST.Ast), String, Position) - f pos s = case runParser (parseAnyString "else") pos s of - Left _ -> Right (Nothing, s, pos) - Right (_, s', pos') -> case runParser parseBracket pos' s' of + p :: Position -> String -> Either String (AST.Ast, String, Position) + p pos s = case runParser parseCond pos s of + Left _ -> case runParser parseBracket pos s of Left err -> Left err - Right (res, s'', pos'') -> Right ((Just res), s'', pos'') + Right (res, s', pos') -> Right (res, s', pos') + Right (res, s', pos') -> Right (res, s', pos') parseLobster :: Parser [AST.Ast] parseLobster = parseSome (parseWhiteSpace *> parseAst) From 4c3d5b44b0e748c99e35fc87f9544d4e2b498d17 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Fri, 12 Jan 2024 15:28:47 +0100 Subject: [PATCH 11/14] test(parsing): update tests for parseList --- LobsterLang/src/Parse.hs | 2 +- LobsterLang/test/ParserSpec.hs | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 0abde35..2abb535 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -345,7 +345,7 @@ parseAnyString s = Parser (f s s) f [] str pos s' = Right (str, s', pos) parseCmpString :: String -> Parser String -parseCmpString s = parseWhiteSpace *> Parser (f s) <* parseWhiteSpace +parseCmpString s = Parser (f s) where f :: String -> Position -> String -> Either String (String, String, Position) f str pos s' = case runParser parseString pos s' of diff --git a/LobsterLang/test/ParserSpec.hs b/LobsterLang/test/ParserSpec.hs index a14f74f..40692a2 100644 --- a/LobsterLang/test/ParserSpec.hs +++ b/LobsterLang/test/ParserSpec.hs @@ -80,18 +80,20 @@ spec = do runParser (parseElem parseString) (0,0) "hello la " `shouldBe` Right ("hello", "la ", (0,6)) it "Check parseValue Success" $ do runParser parseValue (0,0) "432 la " `shouldBe` Right (AST.Value 432, "la ", (0,14)) - it "Check parseList with parseInt Success" $ do - runParser (parseList parseInt) (0,0) "(1 2 3 4 5)" `shouldBe` Right ([1, 2 ,3 , 4, 5], "", (0, 13)) - it "Check parseList with parseInt Failure (without a number inside)" $ do - runParser (parseList parseInt) (0,0) "(1 2 3 d 4 5) (0,0) " `shouldBe` Left (errorParsing (0,8)) - it "Check parseList with parseInt Failure (without a ending ')')" $ do - runParser (parseList parseInt) (0,0) "(1 2 3 4 5 " `shouldBe` Left (errorParsing (0,12)) - it "Check parseList with parseInt Failure (without a starting '(')" $ do - runParser (parseList parseInt) (0,0) "1 2 3 4 5)" `shouldBe` Left (errorParsing (0,0)) - it "Check parseList with parseString Success" $ do - runParser (parseList parseString) (0,0) "(buenos owow k ye )1 2 3 4 5)" `shouldBe` Right (["buenos", "owow", "k", "ye"], "1 2 3 4 5)", (0, 22)) + it "Check parseList String Success" $ do + runParser (parseList parseString) (0,0) "(| a, b ,c, d |)" `shouldBe` Right(["a", "b", "c", "d"], "", (0,19)) + it "Check parseList Error missing comma" $ do + runParser (parseList parseString) (0,0) "(| a b |)" `shouldBe` Left "Error on parsing on '0' '5'" + it "Check parseList Error end with comma" $ do + runParser (parseList parseString) (0,0) "(|a, |)" `shouldBe` Left "Error on parsing on '0' '5'" + it "Check parseList Error starting with comma" $ do + runParser (parseList parseString) (0,0) "(|,a|)" `shouldBe` Left "Error on parsing on '0' '2'" + it "Check parseList Error missing starting bracket" $ do + runParser (parseList parseString) (0,0) "a, b|)" `shouldBe` Left "Error on parsing on '0' '0'" + it "Check parseList Error missing ending bracket" $ do + runParser (parseList parseString) (0,0) "(|a, b" `shouldBe` Left "Error on parsing on '0' '6'" it "Check parseList with parseString Failure" $ do - runParser (parseList parseString) (0,0) "(buenos 3 owow k ye )1 2 3 4 5)" `shouldBe` Left (errorParsing (0,8)) + runParser (parseList parseString) (0,0) "(|buenos, 3, owow, k, ye |)" `shouldBe` Left (errorParsing (0,10)) it "Check parseBool true Success" $ do runParser parseBool (0,0) "true lp" `shouldBe` Right (AST.Boolean True, "lp", (0,5)) it "Check parseBool false Success" $ do From f19a45d184556b4d05dcbcd8df5727bc518cd793 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Sat, 13 Jan 2024 14:11:09 +0100 Subject: [PATCH 12/14] feat(parsing): add parser for symbols and lambdas --- LobsterLang/src/Parse.hs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 2abb535..4f4d51d 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -27,6 +27,7 @@ module Parse ( parseValue, parseLobster, parseAnyString, + parseCmpString, parseDefineValue, parseUnaryOperation, parseProduct, @@ -38,8 +39,8 @@ module Parse ( parseWhiteSpace, errorParsing, parseDefineFn, - parseCond, - parseCmpString + parseLambda, + parseCond ) where import qualified AST @@ -289,6 +290,7 @@ parseValue = parseWhiteSpace *> ( parseWhiteSpace *> parseAnyString "(|" *> parseExpr <* parseAnyString "|)" <* parseWhiteSpace <|> AST.Value <$> parseElem parseInt <|> parseBool + <|> parseSymbol ) parseListElem :: Parser a -> Parser [a] @@ -401,19 +403,27 @@ parseUnaryOperation = Parser f Left err' -> Left err' Right (res', s'', pos'') -> Right (AST.Call res [res'], s'', pos'') +parseSymbol :: Parser AST.Ast +parseSymbol = do + name <- parseString + args <- optional (parseWhiteSpace *> parseList parseAst + >>= \res -> return $ AST.Symbol name (Just res)) + return $ fromMaybe (AST.Symbol name Nothing) args + -- | Return a Parser that parse a SExpr parseAst :: Parser AST.Ast parseAst = parseWhiteSpace *> ( - parseDefineFn + parseDefineFn <|> parseCond <|> parseDefineValue - <|> parseExpr + <|> parseLambda <|> parseBool + <|> parseExpr <|> parseUnaryOperation <|> parseAstString <|> parseValue - <|> parseAstString + <|> parseSymbol ) parseDefineFn :: Parser AST.Ast @@ -426,6 +436,11 @@ parseDefineFn = parseCmpString "fn" *> (Parser defineFn) Left err -> Left err Right (res', s'', pos'') -> Right (AST.Define res res', s'', pos'') +parseLambda :: Parser AST.Ast +parseLambda = lambda *> parseFunctionValue + where + lambda = parseCmpString "lambda" <|> parseAnyString "λ" + parseFunctionValue :: Parser AST.Ast parseFunctionValue = Parser parseParams where From e42832de40ba97c2b51a171411c3c3b70a6ca3d8 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Sat, 13 Jan 2024 14:17:38 +0100 Subject: [PATCH 13/14] feat(parsing): add parse unary operator to parse value --- LobsterLang/src/Parse.hs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/LobsterLang/src/Parse.hs b/LobsterLang/src/Parse.hs index 4f4d51d..edee976 100644 --- a/LobsterLang/src/Parse.hs +++ b/LobsterLang/src/Parse.hs @@ -29,7 +29,6 @@ module Parse ( parseAnyString, parseCmpString, parseDefineValue, - parseUnaryOperation, parseProduct, parseSum, parseExpr, @@ -291,8 +290,16 @@ parseValue = parseWhiteSpace *> ( <|> AST.Value <$> parseElem parseInt <|> parseBool <|> parseSymbol + <|> parseUnaryOperator ) +parseUnaryOperator :: Parser AST.Ast +parseUnaryOperator = parseWhiteSpace *> parseAnyString "!"<|> + parseWhiteSpace *> parseAnyString "@" <|> + parseWhiteSpace *> parseAnyString "~ " + >>= \op -> parseValue + >>= \value -> return $ AST.Call op [value] + parseListElem :: Parser a -> Parser [a] parseListElem parserA = Parser (parseFirst parserA) where @@ -388,21 +395,6 @@ parseDefineValue = Parser f Left err'' -> Left err'' Right (res'', s''', pos''') -> Right (AST.Define res res'', s''', pos''') -parseUnaryOperator :: Parser String -parseUnaryOperator = parseWhiteSpace *> parseAnyString "!"<|> - parseWhiteSpace *> parseAnyString "@" <|> - parseWhiteSpace *> parseAnyString "~" - -parseUnaryOperation :: Parser AST.Ast -parseUnaryOperation = Parser f - where - f :: Position -> String -> Either String (AST.Ast, String, Position) - f pos s = case runParser parseUnaryOperator pos s of - Left err -> Left err - Right (res, s', pos') -> case runParser parseAst pos' s' of - Left err' -> Left err' - Right (res', s'', pos'') -> Right (AST.Call res [res'], s'', pos'') - parseSymbol :: Parser AST.Ast parseSymbol = do name <- parseString @@ -420,7 +412,6 @@ parseAst = parseWhiteSpace *> <|> parseLambda <|> parseBool <|> parseExpr - <|> parseUnaryOperation <|> parseAstString <|> parseValue <|> parseSymbol From ebca942c727ef0305c40bff8550fae4476989611 Mon Sep 17 00:00:00 2001 From: Mathieu MARQUES Date: Sat, 13 Jan 2024 14:27:08 +0100 Subject: [PATCH 14/14] test(parsing): update unary operation tests --- LobsterLang/test/ParseSpec.hs | 27 --------------------------- LobsterLang/test/ParserSpec.hs | 12 ++++++------ 2 files changed, 6 insertions(+), 33 deletions(-) delete mode 100644 LobsterLang/test/ParseSpec.hs diff --git a/LobsterLang/test/ParseSpec.hs b/LobsterLang/test/ParseSpec.hs deleted file mode 100644 index f26f195..0000000 --- a/LobsterLang/test/ParseSpec.hs +++ /dev/null @@ -1,27 +0,0 @@ -{- --- EPITECH PROJECT, 2024 --- GLaDOS --- File description: --- ParseSpec --} - -module ParseSpec where - -import Test.Hspec -import Parse - -spec :: Spec -spec = do - describe "Parser Tests" $ do - it "Check parseList String Success" $ do - runParser (parseList parseString) (0,0) "(| a, b ,c, d |)" `shouldBe` Right(["a", "b", "c", "d"], "", (0,17)) - it "Check parseList Error missing comma" $ do - runParser (parseList parseString) (0,0) "(| a b |)" `shouldBe` Left "Error on parsing on '0' '5'" - it "Check parseList Error end with comma" $ do - runParser (parseList parseString) (0,0) "(|a, |)" `shouldBe` Left "Error on parsing on '0' '5'" - it "Check parseList Error starting with comma" $ do - runParser (parseList parseString) (0,0) "(|,a|)" `shouldBe` Left "Error on parsing on '0' '2'" - it "Check parseList Error missing starting bracket" $ do - runParser (parseList parseString) (0,0) "a, b|)" `shouldBe` Left "Error on parsing on '0' '0'" - it "Check parseList Error missing ending bracket" $ do - runParser (parseList parseString) (0,0) "(|a, b" `shouldBe` Left "Error on parsing on '0' '6'" diff --git a/LobsterLang/test/ParserSpec.hs b/LobsterLang/test/ParserSpec.hs index 40692a2..7743700 100644 --- a/LobsterLang/test/ParserSpec.hs +++ b/LobsterLang/test/ParserSpec.hs @@ -178,9 +178,9 @@ spec = do runParser parseString (0,0) "_Lob3ster*" `shouldBe` Right ("_Lob3ster","*",(0,9)) it "Check parseMany Success" $ do runParser (parseMany (parseChar ' ')) (0,0) " p" `shouldBe` Right (" ","p",(0,1)) - it "Check parseUnaryOperation Success" $ do - runParser parseUnaryOperation (0,0) "! true" `shouldBe` Right (AST.Call "!" [AST.Boolean True],"",(0,6)) - it "Check parseUnaryOperation Failure (incorrect AST)" $ do - runParser parseUnaryOperation (0,0) "! *" `shouldBe` Left (errorParsing (0,2)) - it "Check parseUnaryOperation Failure (missing operator)" $ do - runParser parseUnaryOperation (0,0) "error" `shouldBe` Left (errorParsing (0,0)) + it "Check parseExpr Unary Operation Success" $ do + runParser parseExpr (0,0) "! true" `shouldBe` Right (AST.Call "!" [AST.Boolean True],"",(0,6)) + it "Check parseExpr Unary Operation Failure (incorrect AST)" $ do + runParser parseExpr (0,0) "! *" `shouldBe` Left (errorParsing (0,2)) + it "Check parseExpr Unary Operation Failure (missing operator)" $ do + runParser parseExpr (0,0) "error" `shouldBe` Right (AST.Symbol "error" Nothing, "", (0, 5))