/src/Lang/Php/Ast/Common.hs

https://github.com/sarang25491/lex-pass · Haskell · 123 lines · 95 code · 22 blank · 6 comment · 19 complexity · 0d1d80905b4ddf8fab793f37a196b59c MD5 · raw file

  1. {-# LANGUAGE DeriveDataTypeable, TemplateHaskell, TypeSynonymInstances,
  2. FlexibleInstances, FlexibleContexts, OverlappingInstances,
  3. UndecidableInstances #-}
  4. module Lang.Php.Ast.Common (
  5. module Common,
  6. module Control.Applicative,
  7. module Control.Arrow,
  8. module Control.Monad,
  9. module Data.Binary,
  10. module Data.Char,
  11. module Data.Data,
  12. module Data.DeriveTH,
  13. module Data.List,
  14. module Data.Maybe,
  15. module FUtil,
  16. WS, WS2, WSElem(..), WSCap(..), WSCap2, capify, wsNoNLParser, w2With,
  17. upToCharsOrEndParser) where
  18. import Common
  19. import Control.Applicative hiding ((<|>), many, optional, Const)
  20. import Control.Arrow
  21. import Control.Monad
  22. import Data.Binary
  23. import Data.Char
  24. import Data.Data hiding (Prefix, Infix)
  25. import Data.DeriveTH
  26. import Data.List
  27. import Data.Maybe
  28. import FUtil
  29. import qualified Data.Intercal as IC
  30. type WS = [WSElem]
  31. data WSElem = WS String | LineComment Bool String | Comment String
  32. deriving (Show, Eq, Typeable, Data)
  33. type WS2 = (WS, WS)
  34. w2With :: (Unparse t, Unparse t1) => String -> (t, t1) -> String
  35. w2With s (w1, w2) = unparse w1 ++ s ++ unparse w2
  36. instance Parse WSElem where
  37. parse = WS <$> many1 space <|>
  38. Comment <$> (tokStartCommentP >> upToCharsParser '*' '/') <|> do
  39. isSlash <- (tokLineCommentP >> return True) <|>
  40. (tokPoundP >> return False)
  41. (gotChars, c) <- upToCharsOrEndParser (/= '\n') '?' '>'
  42. -- hackily put the "?>" back; this should be rare and frowned upon
  43. -- and i can't believe php works this way with // vs ?>
  44. when gotChars $ do
  45. setInput =<< ("?>" ++) <$> getInput
  46. pos <- getPosition
  47. setPosition . setSourceColumn pos $ sourceColumn pos - 2
  48. return $ LineComment isSlash c
  49. -- yikes, these can't be in Lex.hs currently, reorg needed?
  50. tokStartComment = "/*"
  51. tokStartCommentP = try $ string tokStartComment
  52. tokLineComment = "//";
  53. tokLineCommentP = try $ string tokLineComment
  54. tokEndComment = "*/"
  55. tokEndCommentP = try $ string tokEndComment
  56. tokPound = "#"
  57. tokPoundP = string tokPound
  58. upToCharsParser c1 c2 = do
  59. (gotChars, r) <- upToCharsOrEndParser (const True) c1 c2
  60. if gotChars then return r
  61. else fail $ "Unexpected <eof>, expecting " ++ [c1, c2] ++ "."
  62. upToCharsOrEndParser f c1 c2 = do
  63. s <- many (satisfy (\ x -> x /= c1 && f x))
  64. r1Mb <- optionMaybe (char c1)
  65. second (s ++) <$> case r1Mb of
  66. Nothing -> return (False, "")
  67. Just _ -> upToCharsOrEndParserC2 f c1 c2
  68. upToCharsOrEndParserC2 f c1 c2 = do
  69. r2Mb <- optionMaybe $ satisfy f
  70. case r2Mb of
  71. Nothing -> return (False, [c1])
  72. Just r2 -> if r2 == c2
  73. then return (True, "")
  74. else second (c1:) <$> if r2 == c1
  75. then upToCharsOrEndParserC2 f c1 c2
  76. else second (r2:) <$> upToCharsOrEndParser f c1 c2
  77. instance Unparse WSElem where
  78. unparse (WS a) = a
  79. unparse (Comment a) = tokStartComment ++ a ++ tokEndComment
  80. unparse (LineComment isSlash a) =
  81. (if isSlash then tokLineComment else tokPound) ++ a
  82. wsNoNLParser :: Parser String
  83. wsNoNLParser = many (satisfy (\ x -> isSpace x && x /= '\n'))
  84. data WSCap a = WSCap {
  85. wsCapPre :: WS,
  86. wsCapMain :: a,
  87. wsCapPost :: WS}
  88. deriving (Show, Eq, Typeable, Data)
  89. instance (Unparse a) => Unparse (WSCap a) where
  90. unparse (WSCap a b c) = concat [unparse a, unparse b, unparse c]
  91. instance Functor WSCap where
  92. fmap f w = w {wsCapMain = f $ wsCapMain w}
  93. capify :: WS -> (a, WS) -> WSCap a
  94. capify a (b, c) = WSCap a b c
  95. instance (Parse (a, WS)) => Parse (WSCap a) where
  96. parse = liftM2 capify parse parse
  97. instance Parse a => Parse (a, WS) where
  98. parse = liftM2 (,) parse parse
  99. type WSCap2 a = WSCap (WSCap a)
  100. $(derive makeBinary ''WSElem)
  101. $(derive makeBinary ''WSCap)