Phase 3: End-of-line and inline block comment parsing
- Add pEndComment parser for -- end-of-line comments - Add pInlineComment parser for [- ... -] block comments - Update pText to stop before -- and [- sequences using notFollowedBy - Add tests for both comment types (2 new tests, 19 total)
This commit is contained in:
+18
-2
@@ -111,6 +111,8 @@ pStepBlock = do
|
|||||||
pStepItem :: Parser StepItem
|
pStepItem :: Parser StepItem
|
||||||
pStepItem =
|
pStepItem =
|
||||||
pLineBreak
|
pLineBreak
|
||||||
|
P.<|> P.try pInlineComment
|
||||||
|
P.<|> P.try pEndComment
|
||||||
P.<|> P.try pRecipeRef
|
P.<|> P.try pRecipeRef
|
||||||
P.<|> P.try pIngredient
|
P.<|> P.try pIngredient
|
||||||
P.<|> P.try pCookware
|
P.<|> P.try pCookware
|
||||||
@@ -250,6 +252,20 @@ readMaybeDouble t = case reads (T.unpack t) of
|
|||||||
[(n, "")] -> Just n
|
[(n, "")] -> Just n
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
|
-- | Inline block comment: [- comment text -]
|
||||||
|
pInlineComment :: Parser StepItem
|
||||||
|
pInlineComment = do
|
||||||
|
_ <- P.string "[-"
|
||||||
|
content <- P.manyTill P.anyChar (P.try (P.string "-]"))
|
||||||
|
return (StepComment (T.pack content))
|
||||||
|
|
||||||
|
-- | End-of-line comment: -- rest of line
|
||||||
|
pEndComment :: Parser StepItem
|
||||||
|
pEndComment = do
|
||||||
|
_ <- P.string "--"
|
||||||
|
content <- P.many (P.noneOf "\n")
|
||||||
|
return (StepEndComment (T.strip (T.pack content)))
|
||||||
|
|
||||||
-- | Cookware: #name or #multi word name{}
|
-- | Cookware: #name or #multi word name{}
|
||||||
pCookware :: Parser StepItem
|
pCookware :: Parser StepItem
|
||||||
pCookware = P.char '#' *> (StepCookware . Cookware . T.pack <$> pNameWithBraces)
|
pCookware = P.char '#' *> (StepCookware . Cookware . T.pack <$> pNameWithBraces)
|
||||||
@@ -279,10 +295,10 @@ pTimer = do
|
|||||||
Just q -> return (Duration (quantityAmount q) (quantityUnit q))
|
Just q -> return (Duration (quantityAmount q) (quantityUnit q))
|
||||||
Nothing -> P.parserFail ("invalid duration: " <> content)
|
Nothing -> P.parserFail ("invalid duration: " <> content)
|
||||||
|
|
||||||
-- | Plain text (everything up to a special character or newline).
|
-- | Plain text (everything up to a special character, newline, or comment start).
|
||||||
pText :: Parser StepItem
|
pText :: Parser StepItem
|
||||||
pText = do
|
pText = do
|
||||||
chars <- P.many1 (P.noneOf ['\\', '\n', '@', '#', '~'])
|
chars <- P.many1 (P.notFollowedBy (P.string "--") *> P.notFollowedBy (P.string "[-") *> P.noneOf ['\\', '\n', '@', '#', '~'])
|
||||||
return (StepText (T.pack chars))
|
return (StepText (T.pack chars))
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -259,6 +259,40 @@ spec = do
|
|||||||
}
|
}
|
||||||
parseCookFile input `shouldBe` expected
|
parseCookFile input `shouldBe` expected
|
||||||
|
|
||||||
|
describe "Comments" $ do
|
||||||
|
it "parses an end-of-line comment within a step" $ do
|
||||||
|
let input = "Mash until smooth -- alternatively, boil 'em first"
|
||||||
|
case parseCookFile input of
|
||||||
|
Left err -> expectationFailure ("parse failed: " <> err)
|
||||||
|
Right recipe -> do
|
||||||
|
let body = NE.toList (sectionBody (NE.head (recipeSections recipe)))
|
||||||
|
case body of
|
||||||
|
[SecStep (Step items)] -> do
|
||||||
|
let expected =
|
||||||
|
[ StepText "Mash until smooth "
|
||||||
|
, StepEndComment "alternatively, boil 'em first"
|
||||||
|
]
|
||||||
|
items `shouldBe` expected
|
||||||
|
other -> expectationFailure ("expected single SecStep, got " <> show other)
|
||||||
|
|
||||||
|
it "parses an inline block comment" $ do
|
||||||
|
let input = "Slowly add @milk{4%cup} [- TODO change units to litres -], keep mixing"
|
||||||
|
case parseCookFile input of
|
||||||
|
Left err -> expectationFailure ("parse failed: " <> err)
|
||||||
|
Right recipe -> do
|
||||||
|
let body = NE.toList (sectionBody (NE.head (recipeSections recipe)))
|
||||||
|
case body of
|
||||||
|
[SecStep (Step items)] -> do
|
||||||
|
let expected =
|
||||||
|
[ StepText "Slowly add "
|
||||||
|
, StepIngredient (Ingredient "milk" (Just (Quantity 4 (Just "cup") False)) Nothing)
|
||||||
|
, StepText " "
|
||||||
|
, StepComment " TODO change units to litres "
|
||||||
|
, StepText ", keep mixing"
|
||||||
|
]
|
||||||
|
items `shouldBe` expected
|
||||||
|
other -> expectationFailure ("expected single SecStep, got " <> show other)
|
||||||
|
|
||||||
describe "EasyPancakes example" $ do
|
describe "EasyPancakes example" $ do
|
||||||
let pancakeInput =
|
let pancakeInput =
|
||||||
"-- TODO add source\n"
|
"-- TODO add source\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user