packages feed

HaTeX 3.12.0.0 → 3.13.0.0

raw patch · 5 files changed

+131/−70 lines, 5 filesdep +parsecdep −attoparsecPVP ok

version bump matches the API change (PVP)

Dependencies added: parsec

Dependencies removed: attoparsec

API changes (from Hackage documentation)

- Text.LaTeX.Base.Parser: latexAtOnce :: Text -> Either String LaTeX
+ Text.LaTeX.Base.Parser: Expect :: !String -> Message
+ Text.LaTeX.Base.Parser: Message :: !String -> Message
+ Text.LaTeX.Base.Parser: SysUnExpect :: !String -> Message
+ Text.LaTeX.Base.Parser: UnExpect :: !String -> Message
+ Text.LaTeX.Base.Parser: data Message :: *
+ Text.LaTeX.Base.Parser: data ParseError :: *
+ Text.LaTeX.Base.Parser: data SourcePos :: *
+ Text.LaTeX.Base.Parser: errorMessages :: ParseError -> [Message]
+ Text.LaTeX.Base.Parser: errorPos :: ParseError -> SourcePos
+ Text.LaTeX.Base.Parser: messageString :: Message -> String
+ Text.LaTeX.Base.Parser: parseLaTeXFile :: FilePath -> IO (Either ParseError LaTeX)
+ Text.LaTeX.Base.Parser: sourceColumn :: SourcePos -> Column
+ Text.LaTeX.Base.Parser: sourceLine :: SourcePos -> Line
+ Text.LaTeX.Base.Parser: sourceName :: SourcePos -> SourceName
- Text.LaTeX.Base.Parser: parseLaTeX :: Text -> Either String LaTeX
+ Text.LaTeX.Base.Parser: parseLaTeX :: Text -> Either ParseError LaTeX

Files

HaTeX.cabal view
@@ -1,5 +1,5 @@ Name: HaTeX
-Version: 3.12.0.0
+Version: 3.13.0.0
 Author: Daniel Díaz
 Category: Text, LaTeX
 Build-type: Simple
@@ -45,13 +45,15 @@   Default-language: Haskell2010
   Build-depends: base == 4.*
                , bytestring >= 0.9.2.1 && < 0.11
-               , transformers >= 0.2.2 && < 0.5
                , text >= 0.11.2.3 && < 2
-               , attoparsec >= 0.10.2 && < 0.12
-               , matrix
+               , transformers >= 0.2.2 && < 0.5
                , containers >= 0.4.2.1 && < 0.6
+               , matrix
+                 -- Testing
                , QuickCheck
-                 -- For pretty-printing
+                 -- Parsing
+               , parsec >= 3.1
+                 -- Pretty-printing
                , wl-pprint-extras >= 3.5
   Exposed-modules:
     Text.LaTeX
Text/LaTeX/Base/Parser.hs view
@@ -1,67 +1,84 @@-{-# LANGUAGE CPP #-}+ {-# LANGUAGE OverloadedStrings #-}----------------------------------------------------------------------------------- |--- Module     : Text/LaTeX/Base/Parser.hs--- Copyright  : (c) Tobias Schoofs--- License    : LGPL --- Stability  : experimental--- Portability: portable++-- | The /LaTeX/ parser.+-- +--   Use 'parseLaTeX' to parse a 'Text' containing /LaTeX/ code.+--   If the 'Text' is in a file, you may want to use 'parseLaTeXFile'.+--   Use this module together with "Text.LaTeX.Base.Syntax" to perform+--   analysis and transformations of /LaTeX/ code. The parser ('parseLaTeX')+--   is related with the renderer ('render') by the following property: ----- LaTeX Parser based on Attoparsec--------------------------------------------------------------------------------+--   /If @t :: Text@ is a syntactically valid LaTeX block, then:/+--+-- > fmap render (parseLaTeX t) == Right t+-- +--   This property says two things:+--+-- * Given a valid LaTeX input, 'parseLaTeX' returns a 'LaTeX' value.+-- * If the parsed value is again rendered, you get the initial input.+--+--   In other words, 'parseLaTeX' is a partial function defined over the+--   set of valid LaTeX files, and 'render' is its inverse.+-- module Text.LaTeX.Base.Parser (+    -- * The parser     parseLaTeX+  , parseLaTeXFile   , latexParser   , latexBlockParser-  , latexAtOnce-#ifdef _TEST-  , specials-#endif+    -- * Parsing errors+  , ParseError+  , errorPos+  , errorMessages+    -- ** Error messages+  , Message (..)+  , messageString+    -- ** Source positions+  , SourcePos+  , sourceLine+  , sourceColumn+  , sourceName     ) where -import           Data.Attoparsec.Text hiding (take, takeTill)-import qualified Data.Attoparsec.Text as A   (takeTill)-import           Data.Char (toLower)+import           Text.Parsec hiding ((<|>),many)+import           Text.Parsec.Text+import           Text.Parsec.Error+import           Data.Char (toLower,digitToInt) import           Data.Monoid import           Data.Maybe (fromMaybe)-import           Data.Text (Text) import qualified Data.Text as T  -import           Control.Applicative ((<|>), (<$>),many)+import           Control.Applicative import           Control.Monad (unless)  import           Text.LaTeX.Base.Syntax+import           Text.LaTeX.Base.Render  -- | Parse a 'Text' sequence as a 'LaTeX' block. If it fails, it returns --   an error string.-parseLaTeX :: Text -> Either String LaTeX+parseLaTeX :: Text -> Either ParseError LaTeX parseLaTeX t | T.null t  = return TeXEmpty-             | otherwise = -  case parse latexParser t of-    Fail _ _ e     -> Left e-    Done _ r       -> Right r-    rx@(Partial _) -> -- Left "incomplete input"-                      case feed rx T.empty of-                        Fail _ _ e -> Left e-                        Partial _  -> Left "incomplete input"-                        Done _ r   -> Right r--{-# DEPRECATED latexAtOnce "Use parseLaTeX instead." #-}+             | otherwise = parse latexParser "parseLaTeX input" t --- | Same as 'parseLaTeX'.-latexAtOnce :: Text -> Either String LaTeX-latexAtOnce = parseLaTeX+-- | Read a file and parse it as 'LaTeX'.+parseLaTeXFile :: FilePath -> IO (Either ParseError LaTeX)+parseLaTeXFile fp = parse latexParser fp <$> readFileTex fp ---------------------------------------------------------------------------- | Incremental 'LaTeX' parser.-------------------------------------------------------------------------+-- | The 'LaTeX' parser. latexParser :: Parser LaTeX-latexParser = mconcat <$> latexBlockParser `manyTill` endOfInput +latexParser = mconcat <$> latexBlockParser `manyTill` eof  -- | Parser of a single 'LaTeX' constructor, no appending blocks. latexBlockParser :: Parser LaTeX-latexBlockParser = foldr1 (<|>) [text, dolMath, comment, text2, environment, command]+latexBlockParser = foldr1 (<|>)+  [ text            <?> "text"+  , dolMath         <?> "inline math ($)"+  , comment         <?> "comment"+  , text2           <?> "text2"+  , try environment <?> "environment"+  , command         <?> "command"+    ] -- Note: text stops on ']'; if the other parsers fail on the rest --       text2 handles it, starting with ']'    @@ -74,7 +91,7 @@   case mbC of     Nothing -> fail "text: Empty input."     Just c | c `elem` "$%\\{]}" -> fail "not text"-           | otherwise          -> TeXRaw <$> A.takeTill (`elem` "$%\\{]}")+           | otherwise          -> TeXRaw <$> takeTill (`elem` "$%\\{]}")  ------------------------------------------------------------------------ -- Text without stopping on ']'@@ -92,41 +109,43 @@ environment = anonym <|> env  anonym :: Parser LaTeX-anonym = char '{' >> -    TeXBraces . mconcat <$> latexBlockParser `manyTill` char '}'+anonym = do+  _ <- char '{'+  l <- TeXBraces . mconcat <$> many latexBlockParser+  _ <- char '}'+  return l  env :: Parser LaTeX env = do-  _  <- char '\\'-  n  <- envName "begin"+  n  <- char '\\' *> envName "begin"   sps <- many $ char ' '   let lsps = if null sps then mempty else TeXRaw $ T.pack sps   as <- cmdArgs   b  <- envBody n -  return $ TeXEnv (T.unpack n) (fromMaybe [] as) $+  return $ TeXEnv n (fromMaybe [] as) $     case as of      Just [] -> lsps <> TeXBraces mempty <> b      Nothing -> lsps <> b      _ -> b -envName :: Text -> Parser Text+envName :: String -> Parser String envName k = do   _ <- string k   _ <- char '{'-  n <- A.takeTill (== '}')+  n <- takeTill (== '}')   _ <- char '}'-  return n+  return $ T.unpack n -envBody :: Text -> Parser LaTeX+envBody :: String -> Parser LaTeX envBody n = mconcat <$> (bodyBlock n) `manyTill` endenv-  where endenv = try $ string ("\\end") >> skipSpace >> string ("{" <> n <> "}")+  where endenv = try $ string ("\\end") >> spaces >> string ("{" <> n <> "}") -bodyBlock :: Text -> Parser LaTeX+bodyBlock :: String -> Parser LaTeX bodyBlock n = do   c <- peekChar   case c of       Just _ -> latexBlockParser-     _ -> fail $ "Environment '" <> T.unpack n <> "' not finalized."+     _ -> fail $ "Environment '" <> n <> "' not finalized."  ------------------------------------------------------------------------ -- Command@@ -140,7 +159,7 @@     Just x  -> if isSpecial x                   then special                   else do-                    c  <- A.takeTill endCmd+                    c  <- takeTill endCmd                     -- if c `elem` ["begin","end"]                     --    then fail $ "Command not allowed: " ++ T.unpack c                     --    else maybe (TeXCommS $ T.unpack c) (TeXComm $ T.unpack c) <$> cmdArgs@@ -161,7 +180,7 @@             '[' -> "]"             '{' -> "}"             _   -> error "this cannot happen!"-  b <- mconcat <$> latexBlockParser `manyTill` string e+  b <- mconcat <$> manyTill latexBlockParser (string e)   case c of       '[' -> return $ OptArg b     '{' -> return $ FixArg b@@ -185,6 +204,7 @@ ------------------------------------------------------------------------ -- Line break ------------------------------------------------------------------------+ lbreak :: Parser LaTeX lbreak = do   y <- try (char '[' <|> char '*' <|> return ' ')  @@ -197,13 +217,13 @@     _   -> return (TeXLineBreak Nothing False)  linebreak :: Bool -> Parser LaTeX-linebreak t = do m <- measure+linebreak t = do m <- measure <?> "measure"                  _ <- char ']'                  s <- try (char '*' <|> return ' ')                  return $ TeXLineBreak (Just m) (t || s == '*')  measure :: Parser Measure-measure = try (double >>= unit) <|> CustomMeasure <$> latexBlockParser+measure = try (floating >>= unit) <|> (CustomMeasure . mconcat) <$> manyTill latexBlockParser (lookAhead $ char ']')  unit :: Double -> Parser Measure unit f = do@@ -241,7 +261,7 @@   b <- mconcat <$> latexBlockParser `manyTill` char '$'   return $ TeXMath Dollar b -math :: MathType -> Text -> Parser LaTeX+math :: MathType -> String -> Parser LaTeX math t eMath = do    b <- mconcat <$> latexBlockParser `manyTill` try (string eMath)    return $ TeXMath t b@@ -252,7 +272,7 @@ comment :: Parser LaTeX comment = do   _  <- char '%'-  c  <- A.takeTill (== '\n')+  c  <- takeTill (== '\n')   e  <- atEnd   unless e (char '\n' >>= \_ -> return ())   return $ TeXComment c@@ -260,6 +280,7 @@ ------------------------------------------------------------------------ -- Helpers ------------------------------------------------------------------------+ isSpecial :: Char -> Bool isSpecial = (`elem` specials) @@ -272,3 +293,40 @@  specials :: String specials = "'(),.-\"!^$&#{}%~|/:;=[]\\` "++peekChar :: Parser (Maybe Char)+peekChar = Just <$> (try $ lookAhead anyChar) <|> pure Nothing++atEnd :: Parser Bool+atEnd = (eof *> pure True) <|> pure False++takeTill :: (Char -> Bool) -> Parser Text+takeTill p = T.pack <$> many (satisfy (not . p))++-- Parsing doubles+--+-- Code for 'floating', 'fractExponent', and 'sign' comes from parsers package:+--+-- http://hackage.haskell.org/package/parsers+--++floating :: Parser Double+floating = decimal <**> fractExponent++fractExponent :: Parser (Integer -> Double)+fractExponent = (\fract expo n -> (fromInteger n + fract) * expo) <$> fraction <*> option 1.0 exponent'+            <|> (\expo n -> fromInteger n * expo) <$> exponent' where+  fraction = foldr op 0.0 <$> (char '.' *> (some digit <?> "fraction"))+  op d f = (f + fromIntegral (digitToInt d))/10.0+  exponent' = ((\f e -> power (f e)) <$ oneOf "eE" <*> sign <*> (decimal <?> "exponent")) <?> "exponent"+  power e+    | e < 0     = 1.0/power(-e)+    | otherwise = fromInteger (10^e)++decimal :: Parser Integer+decimal = read <$> many1 digit++sign :: Parser (Integer -> Integer)+sign = negate <$ char '-'+   <|> id <$ char '+'+   <|> pure id
Text/LaTeX/Base/Syntax.hs view
@@ -256,7 +256,7 @@ arbitraryChar = elements $
      ['A'..'Z']
   ++ ['a'..'z']
-  ++ "\n-+*/!\"$%&()[]{}^_.,:;'#@<>?\\ "
+  ++ "\n-+*/!\"$%&(){}^_.,:;'#@<>?\\ "
 
 -- | Utility for the instance of 'LaTeX' to 'Arbitrary'.
 --   We generate a short sequence of characters and
parsertest/parsertest.hs view
@@ -12,7 +12,7 @@   t <- T.readFile $ "example" ++ show i ++ ".tex"   case parseLaTeX t of     Left err -> do putStrLn "Failed."-                   putStrLn $ "The error was: " ++ err+                   putStrLn $ "The error was: " ++ show err                    return False     Right _  -> putStrLn "Succeed." >> return True @@ -23,4 +23,4 @@   let b = and bs   putStrLn $ "Parser Test Passed: " ++ show b   if b then return ()-       else putStrLn $ "Number of errors: " ++ show (length $ filter (==False) bs)+       else putStrLn $ "Test result: " ++ show (length $ filter (==True) bs) ++ "/" ++ show (length bs)
test/Main.hs view
@@ -6,6 +6,9 @@ import qualified Test.Tasty.QuickCheck as QC import Test.QuickCheck +instance Eq ParseError where+  _ == _ = undefined+ main :: IO () main = defaultMain $ testGroup "HaTeX"   [ testGroup "LaTeX"@@ -17,9 +20,7 @@     ]   , testGroup "Parser"     [ QC.testProperty "render . parse = id" $-         \l0 -> let t = render (l0 :: LaTeX)-                in case parseLaTeX t of-                     Left _ -> False-                     Right l -> render l == t+         \l -> let t = render (l :: LaTeX)+               in  fmap render (parseLaTeX t) == Right t     ]   ]