Accept a leading single quote for data constructor promotion (#13)
authorAndrew Martin <andrew.thaddeus@gmail.com>
Fri, 28 Dec 2018 16:08:16 +0000 (11:08 -0500)
committerRyan Scott <ryan.gl.scott@gmail.com>
Fri, 28 Dec 2018 16:08:16 +0000 (10:08 -0600)
* Accept a leading single quote for data constructor promotion. This syntax was not previously understood by hsc2hs.

* Document the weirdness of single quotes. Correctly handle promoted data constructors that end with single quote.

* improve handling of leading whitespace in promoted data constructors, improve comments on this subject

* update changelog to reflect improved support for promoted data constructors

HSCParser.hs
changelog.md

index d855cf1..478faf0 100644 (file)
@@ -100,6 +100,9 @@ anyChar_ = do
 any2Chars_ :: Parser ()
 any2Chars_ = anyChar_ >> anyChar_
 
+any3Chars_ :: Parser ()
+any3Chars_ = anyChar_ >> anyChar_ >> anyChar_
+
 many :: Parser a -> Parser [a]
 many p = many1 p `mplus` return []
 
@@ -161,12 +164,57 @@ text = do
                 _ -> do
                     return () `fakeOutput` unescapeHashes symb
                     text
-        '\"':_    -> do anyChar_; hsString '\"'; text
-        '\'':_    -> do anyChar_; hsString '\''; text
-        '{':'-':_ -> do any2Chars_; linePragma `mplus`
-                                    columnPragma `mplus`
-                                    hsComment; text
-        _:_       -> do anyChar_; text
+        '\"':_        -> do anyChar_; hsString '\"'; text
+        -- See Note [Single Quotes]
+        '\'':'\\':_ -> do any2Chars_; hsString '\''; text -- Case 1
+        '\'':d:'\'':_ -> do any3Chars_; text -- Case 2
+        '\'':d:_ | isSpace d -> do -- Case 3
+          any2Chars_
+          manySatisfy_ (\c' -> isSpace c')
+          manySatisfy_ (\c' -> isAlphaNum c' || c' == '_' || c' == '\'')
+          text
+        '\'':_ -> do -- Case 4
+          anyChar_
+          manySatisfy_ (\c' -> isAlphaNum c' || c' == '_' || c' == '\'')
+          text
+        '{':'-':_ -> do
+          any2Chars_
+          linePragma `mplus` columnPragma `mplus` hsComment
+          text
+        _:_           -> do anyChar_; text
+
+-- Note [Single Quotes]
+--
+-- hsc2hs performs some tricks to figure out if we are looking at character
+-- literal or a promoted data constructor. In order, the cases considered are:
+--
+-- 1. quote-backslash: An escape sequence character literal. Since these
+--    escape sequences have several different possible lengths, hsc2hs will
+--    consume everything after this until another single quote is encountered.
+-- 2. quote-any-quote: A character literal. Consumes the triplet.
+-- 3. quote-space: Here, the order of the patterns becomes important. This
+--    case and the case below handle promoted data constructors. This one
+--    is to handle data constructor that end in a quote. They have special
+--    syntax for promotion that requires adding a leading space. After an
+--    arbitrary number of initial space characters, consume
+--    all alphanumeric characters and quotes, considering them part of the
+--    identifier.
+-- 4. quote: If nothing else matched, we assume we are dealing with a normal
+--    promoted data constructor. Consume all alphanumeric characters and
+--    quotes, considering them part of the identifier.
+--
+-- Here are some lines of code for which at one of the described cases
+-- would be matched at some point:
+--
+--     data Foo = Foo' | Bar
+--
+--     main :: IO ()
+--     main = do
+-- 1>    putChar 'x'
+-- 2>    putChar '\NUL'
+-- 3>    let y = Proxy :: Proxy ' Foo'
+-- 4>    let x = Proxy :: Proxy 'Bar
+--       pure ()
 
 hsString :: Char -> Parser ()
 hsString quote = do
index 07812af..33e8877 100644 (file)
@@ -6,6 +6,9 @@
  - Support for non-x86 platforms should be significantly more robust due to
    improvements in `hsc2hs`'s assembly parser
 
+ - Add support for haskell files that use a leading single quote for promoted
+   data constructors.
+
 ## 0.68.4
 
  - Add support to read command line arguments supplied via response files