diff --git a/bower.json b/bower.json index 4284b1b..a98673c 100644 --- a/bower.json +++ b/bower.json @@ -20,19 +20,20 @@ "package.json" ], "dependencies": { - "purescript-arrays": "^4.0.0", - "purescript-either": "^3.0.0", - "purescript-foldable-traversable": "^3.0.0", - "purescript-identity": "^3.0.0", - "purescript-integers": "^3.0.0", - "purescript-lists": "^4.0.0", - "purescript-maybe": "^3.0.0", - "purescript-strings": "^3.0.0", - "purescript-transformers": "^3.0.0", - "purescript-unicode": "^3.0.0" + "purescript-arrays": "^5.0.0", + "purescript-either": "^4.0.0", + "purescript-foldable-traversable": "^4.0.0", + "purescript-identity": "^4.0.0", + "purescript-integers": "^4.0.0", + "purescript-lists": "^5.0.0", + "purescript-maybe": "^4.0.0", + "purescript-strings": "^4.0.0", + "purescript-transformers": "^4.1.0", + "purescript-unicode": "^4.0.0" }, "devDependencies": { - "purescript-assert": "^3.0.0", - "purescript-console": "^3.0.0" + "purescript-assert": "^4.0.0", + "purescript-console": "^4.1.0", + "purescript-psci-support": "^4.0.0" } } diff --git a/package.json b/package.json index e6343ef..7a19913 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "build": "pulp build && pulp test" }, "devDependencies": { - "pulp": "^11.0.0", - "purescript-psa": "^0.5.0", - "purescript": "^0.11.1", - "rimraf": "^2.5.4" + "pulp": "^12.3.0", + "purescript-psa": "^0.6.0", + "purescript": "^0.12.0", + "rimraf": "^2.6.2" } } diff --git a/psc-package.json b/psc-package.json new file mode 100644 index 0000000..ef8e887 --- /dev/null +++ b/psc-package.json @@ -0,0 +1,19 @@ +{ + "name": "purescript-parsing", + "set": "psc-0.12.0", + "source": "https://github.com/purescript/package-sets.git", + "depends": [ + "arrays", + "either", + "foldable-traversable", + "identity", + "integers", + "lists", + "maybe", + "prelude", + "psci-support", + "strings", + "transformers", + "unicode" + ] +} diff --git a/src/Text/Parsing/Parser.purs b/src/Text/Parsing/Parser.purs index 77a132c..55204ad 100644 --- a/src/Text/Parsing/Parser.purs +++ b/src/Text/Parsing/Parser.purs @@ -16,18 +16,18 @@ module Text.Parsing.Parser ) where import Prelude + import Control.Alt (class Alt) import Control.Apply (lift2) import Control.Lazy (defer, class Lazy) import Control.Monad.Error.Class (class MonadThrow, throwError) import Control.Monad.Except (class MonadError, ExceptT(..), runExceptT, mapExceptT) import Control.Monad.Rec.Class (class MonadRec) -import Control.Monad.State (runStateT, class MonadState, StateT(..), gets, evalStateT, mapStateT, modify) +import Control.Monad.State (class MonadState, StateT(..), evalStateT, gets, mapStateT, modify_, runStateT) import Control.Monad.Trans.Class (class MonadTrans, lift) import Control.MonadPlus (class Alternative, class MonadZero, class MonadPlus, class Plus) import Data.Either (Either(..)) import Data.Identity (Identity) -import Data.Monoid (class Monoid, mempty) import Data.Newtype (class Newtype, unwrap, over) import Data.Tuple (Tuple(..)) import Text.Parsing.Parser.Pos (Position, initialPos) @@ -122,7 +122,7 @@ instance monadTransParserT :: MonadTrans (ParserT s) where -- | Set the consumed flag. consume :: forall s m. Monad m => ParserT s m Unit -consume = modify \(ParseState input pos _) -> +consume = modify_ \(ParseState input pos _) -> ParseState input pos true -- | Returns the current position in the stream. diff --git a/src/Text/Parsing/Parser/Combinators.purs b/src/Text/Parsing/Parser/Combinators.purs index d346258..3f76cac 100644 --- a/src/Text/Parsing/Parser/Combinators.purs +++ b/src/Text/Parsing/Parser/Combinators.purs @@ -36,13 +36,13 @@ import Text.Parsing.Parser (ParseState(..), ParserT(..), ParseError(..), fail) withErrorMessage :: forall m s a. Monad m => ParserT s m a -> String -> ParserT s m a withErrorMessage p msg = p <|> fail ("Expected " <> msg) -infix 3 withErrorMessage as +infixl 3 withErrorMessage as -- | Flipped `()`. asErrorMessage :: forall m s a. Monad m => String -> ParserT s m a -> ParserT s m a asErrorMessage = flip () -infix 3 asErrorMessage as +infixl 3 asErrorMessage as -- | Wrap a parser with opening and closing markers. -- | diff --git a/src/Text/Parsing/Parser/Expr.purs b/src/Text/Parsing/Parser/Expr.purs index adfa62e..e9ad0b6 100644 --- a/src/Text/Parsing/Parser/Expr.purs +++ b/src/Text/Parsing/Parser/Expr.purs @@ -63,8 +63,8 @@ makeParser term ops = do prefixOp = choice accum.prefix "" postfixOp = choice accum.postfix "" - postfixP = postfixOp <|> pure id - prefixP = prefixOp <|> pure id + postfixP = postfixOp <|> pure identity + prefixP = prefixOp <|> pure identity splitOp :: forall m s a. Operator m s a -> SplitAccum m s a -> SplitAccum m s a splitOp (Infix op AssocNone) accum = accum { nassoc = op : accum.nassoc } diff --git a/src/Text/Parsing/Parser/Indent.purs b/src/Text/Parsing/Parser/Indent.purs index e0b9619..219d927 100644 --- a/src/Text/Parsing/Parser/Indent.purs +++ b/src/Text/Parsing/Parser/Indent.purs @@ -204,16 +204,16 @@ infixl 12 indentOp as -- | Parses with surrounding brackets indentBrackets :: forall a. IndentParser String a -> IndentParser String a -indentBrackets p = withPos $ pure id <-/> symbol "[" <+/> p <-/> symbol "]" +indentBrackets p = withPos $ pure identity <-/> symbol "[" <+/> p <-/> symbol "]" -- | Parses with surrounding angle brackets indentAngles :: forall a. IndentParser String a -> IndentParser String a -indentAngles p = withPos $ pure id <-/> symbol "<" <+/> p <-/> symbol ">" +indentAngles p = withPos $ pure identity <-/> symbol "<" <+/> p <-/> symbol ">" -- | Parses with surrounding braces indentBraces :: forall a. IndentParser String a -> IndentParser String a -indentBraces p = withPos $ pure id <-/> symbol "{" <+/> p <-/> symbol "}" +indentBraces p = withPos $ pure identity <-/> symbol "{" <+/> p <-/> symbol "}" -- | Parses with surrounding parentheses indentParens :: forall a. IndentParser String a -> IndentParser String a -indentParens p = withPos $ pure id <-/> symbol "(" <+/> p <-/> symbol ")" +indentParens p = withPos $ pure identity <-/> symbol "(" <+/> p <-/> symbol ")" diff --git a/src/Text/Parsing/Parser/String.purs b/src/Text/Parsing/Parser/String.purs index 335bab2..e5b9b25 100644 --- a/src/Text/Parsing/Parser/String.purs +++ b/src/Text/Parsing/Parser/String.purs @@ -2,17 +2,19 @@ module Text.Parsing.Parser.String where -import Data.String as S -import Control.Monad.State (modify, gets) +import Prelude hiding (between) + +import Control.Monad.State (gets, modify_) import Data.Array (many) import Data.Foldable (elem, notElem) import Data.Maybe (Maybe(..)) import Data.Newtype (wrap) -import Data.String (Pattern, fromCharArray, length, singleton) +import Data.String (Pattern, length) +import Data.String as S +import Data.String.CodeUnits as SCU import Text.Parsing.Parser (ParseState(..), ParserT, fail) import Text.Parsing.Parser.Combinators (tryRethrow, ()) import Text.Parsing.Parser.Pos (updatePosString) -import Prelude hiding (between) -- | This class exists to abstract over streams which support the string-like -- | operations which this modules needs. @@ -23,7 +25,7 @@ class StringLike s where uncons :: s -> Maybe { head :: Char, tail :: s } instance stringLikeString :: StringLike String where - uncons = S.uncons + uncons = SCU.uncons drop = S.drop indexOf = S.indexOf null = S.null @@ -40,7 +42,7 @@ string str = do input <- gets \(ParseState input _ _) -> input case indexOf (wrap str) input of Just 0 -> do - modify \(ParseState _ position _) -> + modify_ \(ParseState _ position _) -> ParseState (drop (length str) input) (updatePosString position str) true @@ -54,9 +56,9 @@ anyChar = do case uncons input of Nothing -> fail "Unexpected EOF" Just { head, tail } -> do - modify \(ParseState _ position _) -> + modify_ \(ParseState _ position _) -> ParseState tail - (updatePosString position (singleton head)) + (updatePosString position (SCU.singleton head)) true pure head @@ -65,7 +67,7 @@ satisfy :: forall s m. StringLike s => Monad m => (Char -> Boolean) -> ParserT s satisfy f = tryRethrow do c <- anyChar if f c then pure c - else fail $ "Character '" <> singleton c <> "' did not satisfy predicate" + else fail $ "Character '" <> SCU.singleton c <> "' did not satisfy predicate" -- | Match the specified character char :: forall s m. StringLike s => Monad m => Char -> ParserT s m Char @@ -75,7 +77,7 @@ char c = satisfy (_ == c) show c whiteSpace :: forall s m. StringLike s => Monad m => ParserT s m String whiteSpace = do cs <- many $ satisfy \c -> c == '\n' || c == '\r' || c == ' ' || c == '\t' - pure $ fromCharArray cs + pure $ SCU.fromCharArray cs -- | Skip whitespace characters. skipSpaces :: forall s m. StringLike s => Monad m => ParserT s m Unit diff --git a/src/Text/Parsing/Parser/Token.purs b/src/Text/Parsing/Parser/Token.purs index 0761e5f..023a864 100644 --- a/src/Text/Parsing/Parser/Token.purs +++ b/src/Text/Parsing/Parser/Token.purs @@ -21,28 +21,30 @@ module Text.Parsing.Parser.Token ) where -import Data.Array as Array -import Data.Char.Unicode as Unicode -import Data.List as List +import Prelude hiding (when,between) + import Control.Lazy (fix) -import Control.Monad.State (modify, gets) +import Control.Monad.State (gets, modify_) import Control.MonadPlus (guard, (<|>)) +import Data.Array as Array import Data.Char (fromCharCode, toCharCode) import Data.Char.Unicode (digitToInt, isAlpha, isAlphaNum, isDigit, isHexDigit, isOctDigit, isSpace, isUpper) +import Data.Char.Unicode as Unicode import Data.Either (Either(..)) import Data.Foldable (foldl, foldr) import Data.Identity (Identity) import Data.Int (toNumber) import Data.List (List(..)) +import Data.List as List import Data.Maybe (Maybe(..), maybe) -import Data.String (toCharArray, null, toLower, fromCharArray, singleton, uncons) +import Data.String (null, toLower) +import Data.String.CodeUnits as SCU import Data.Tuple (Tuple(..)) import Math (pow) import Text.Parsing.Parser (ParseState(..), ParserT, fail) import Text.Parsing.Parser.Combinators (skipMany1, try, tryRethrow, skipMany, notFollowedBy, option, choice, between, sepBy1, sepBy, (), ()) import Text.Parsing.Parser.Pos (Position) import Text.Parsing.Parser.String (satisfy, oneOf, noneOf, string, char) -import Prelude hiding (when,between) -- | Create a parser which Returns the first token in the stream. token :: forall m a. Monad m => (a -> Position) -> ParserT (List a) m a @@ -51,7 +53,7 @@ token tokpos = do case List.uncons input of Nothing -> fail "Unexpected EOF" Just { head, tail } -> do - modify \(ParseState _ position _) -> + modify_ \(ParseState _ position _) -> ParseState tail (tokpos head) true pure head @@ -397,7 +399,7 @@ makeTokenParser (LanguageDef languageDef) go :: ParserT String m String go = do maybeChars <- between (char '"') (char '"' "end of string") (List.many stringChar) - pure $ fromCharArray $ List.toUnfoldable $ foldr folder Nil maybeChars + pure $ SCU.fromCharArray $ List.toUnfoldable $ foldr folder Nil maybeChars folder :: Maybe Char -> List Char -> List Char folder Nothing chars = chars @@ -432,7 +434,9 @@ makeTokenParser (LanguageDef languageDef) charControl = do _ <- char '^' code <- upper - pure <<< fromCharCode $ toCharCode code - toCharCode 'A' + 1 + case fromCharCode (toCharCode code - toCharCode 'A' + 1) of + Just c -> pure c + Nothing -> fail "invalid character code (should not happen)" charNum :: ParserT String m Char charNum = do @@ -441,7 +445,9 @@ makeTokenParser (LanguageDef languageDef) <|> ( char 'x' *> number 16 hexDigit ) if code > 0x10FFFF then fail "invalid escape sequence" - else pure $ fromCharCode code + else case fromCharCode code of + Just c -> pure c + Nothing -> fail "invalid character code (should not happen)" charEsc :: ParserT String m Char charEsc = choice (map parseEsc escMap) @@ -567,8 +573,8 @@ makeTokenParser (LanguageDef languageDef) sign :: forall a . (Ring a) => ParserT String m (a -> a) sign = (char '-' $> negate) - <|> (char '+' $> id) - <|> pure id + <|> (char '+' $> identity) + <|> pure identity nat :: ParserT String m Int nat = zeroNumber <|> decimal @@ -624,7 +630,7 @@ makeTokenParser (LanguageDef languageDef) go = do c <- languageDef.opStart cs <- Array.many languageDef.opLetter - pure $ singleton c <> fromCharArray cs + pure $ SCU.singleton c <> SCU.fromCharArray cs isReservedOp :: String -> Boolean isReservedOp name = isReserved (Array.sort languageDef.reservedOpNames) name @@ -645,7 +651,7 @@ makeTokenParser (LanguageDef languageDef) | otherwise = walk name $> name where walk :: String -> ParserT String m Unit - walk name' = case uncons name' of + walk name' = case SCU.uncons name' of Nothing -> pure unit Just { head: c, tail: cs } -> (caseChar c msg) *> walk cs @@ -675,7 +681,7 @@ makeTokenParser (LanguageDef languageDef) go = do c <- languageDef.identStart cs <- Array.many languageDef.identLetter - pure $ singleton c <> fromCharArray cs + pure $ SCU.singleton c <> SCU.fromCharArray cs ----------------------------------------------------------- @@ -757,7 +763,7 @@ inCommentMulti langDef@(LanguageDef languageDef) = "end of comment" where startEnd :: Array Char - startEnd = toCharArray languageDef.commentEnd <> toCharArray languageDef.commentStart + startEnd = SCU.toCharArray languageDef.commentEnd <> SCU.toCharArray languageDef.commentStart inCommentSingle :: forall m . Monad m => GenLanguageDef String m -> ParserT String m Unit inCommentSingle (LanguageDef languageDef) = @@ -767,7 +773,7 @@ inCommentSingle (LanguageDef languageDef) = "end of comment" where startEnd :: Array Char - startEnd = toCharArray languageDef.commentEnd <> toCharArray languageDef.commentStart + startEnd = SCU.toCharArray languageDef.commentEnd <> SCU.toCharArray languageDef.commentStart ------------------------------------------------------------------------- -- Helper functions that should maybe go in Text.Parsing.Parser.String -- diff --git a/test/Main.purs b/test/Main.purs index a401378..8bd3742 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -1,16 +1,18 @@ module Test.Main where +import Prelude hiding (between,when) + import Control.Alt ((<|>)) import Control.Lazy (fix) -import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (logShow, CONSOLE) import Data.Array (some) import Data.Either (Either(..)) import Data.List (List(..), fromFoldable, many) import Data.Maybe (Maybe(..)) -import Data.String (fromCharArray, singleton) +import Data.String.CodeUnits (fromCharArray, singleton) import Data.Tuple (Tuple(..)) -import Test.Assert (ASSERT, assert') +import Effect (Effect) +import Effect.Console (logShow) +import Test.Assert (assert') import Text.Parsing.Parser (Parser, ParserT, runParser, parseErrorPosition) import Text.Parsing.Parser.Combinators (endBy1, sepBy1, optionMaybe, try, chainl, between) import Text.Parsing.Parser.Expr (Assoc(..), Operator(..), buildExprParser) @@ -18,7 +20,6 @@ import Text.Parsing.Parser.Language (javaStyle, haskellStyle, haskellDef) import Text.Parsing.Parser.Pos (Position(..), initialPos) import Text.Parsing.Parser.String (eof, string, char, satisfy, anyChar) import Text.Parsing.Parser.Token (TokenParser, match, when, token, makeTokenParser) -import Prelude hiding (between,when) parens :: forall m a. Monad m => ParserT String m a -> ParserT String m a parens = between (string "(") (string ")") @@ -28,14 +29,14 @@ nested = fix \p -> (do _ <- string "a" pure 0) <|> ((+) 1) <$> parens p -parseTest :: forall s a eff. Show a => Eq a => s -> a -> Parser s a -> Eff (console :: CONSOLE, assert :: ASSERT | eff) Unit +parseTest :: forall s a. Show a => Eq a => s -> a -> Parser s a -> Effect Unit parseTest input expected p = case runParser input p of Right actual -> do assert' ("expected: " <> show expected <> ", actual: " <> show actual) (expected == actual) logShow actual Left err -> assert' ("error: " <> show err) false -parseErrorTestPosition :: forall s a eff. Show a => Parser s a -> s -> Position -> Eff (console :: CONSOLE, assert :: ASSERT | eff) Unit +parseErrorTestPosition :: forall s a. Show a => Parser s a -> s -> Position -> Effect Unit parseErrorTestPosition p input expected = case runParser input p of Right _ -> assert' "error: ParseError expected!" false Left err -> do @@ -96,7 +97,7 @@ mkPos n = mkPos' n 1 mkPos' :: Int -> Int -> Position mkPos' column line = Position { column: column, line: line } -type TestM = forall eff . Eff (console :: CONSOLE, assert :: ASSERT | eff) Unit +type TestM = Effect Unit tokenParserIdentifierTest :: TestM tokenParserIdentifierTest = do @@ -411,7 +412,7 @@ javaStyleTest = do "hello {- comment\n -} foo" (mkPos 7) -main :: forall eff . Eff (console :: CONSOLE, assert :: ASSERT |eff) Unit +main :: Effect Unit main = do parseErrorTestPosition