Skip to content

Commit

Permalink
Fix #384: Haskell/OCaml printer: nil case also for nonempty lists
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasabel committed Sep 22, 2021
1 parent bab5bc3 commit 100552e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
13 changes: 12 additions & 1 deletion source/src/BNFC/Backend/Haskell/CFtoPrinter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ prologue tokenText useGadt name absMod cf = map text $ concat
, "#endif"
]
, [ ""
-- Needed for precedence category lists, e.g. @[Exp2]@:
, "{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}"
, ""
, "-- | Pretty-printer for " ++ takeWhile ('.' /=) name ++ "."
Expand Down Expand Up @@ -292,7 +293,7 @@ case_fun absMod functor cf cat rules =

-- Special printing of lists (precedence changes concrete syntax!)
if isList cat then
map mkPrtListCase $ List.sortBy compareRules $ rulesForNormalizedCat cf cat
listCases $ List.sortBy compareRules $ rulesForNormalizedCat cf cat

-- Ordinary category
else
Expand All @@ -310,6 +311,16 @@ case_fun absMod functor cf cat rules =
ListCat c -> "[" <> type' c <> "]"
c@TokenCat{} -> text (qualifiedCat absMod c)
c -> text (qualifiedCat absMod c) <> "' a"
listCases [] = []
listCases rules = concat
[ [ "prt _ [] = concatD []" | not $ any isNilFun rules ]
-- Andreas, 2021-09-22, issue #386
-- If the list is @nonempty@ according to the grammar, still add a nil case.
-- In the AST it is simply a list, and the AST could be created
-- by other means than by parsing.
, map mkPrtListCase rules
]


-- | When writing the Print instance for a category (in case_fun), we have
-- a different case for each constructor for this category.
Expand Down
17 changes: 12 additions & 5 deletions source/src/BNFC/Backend/OCaml/CFtoOCamlPrinter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -174,18 +174,25 @@ case_fun absMod cat xs = unlines [
-- mkListRule rs = unlines $ ("and prt" ++ fixTypeUpper cat ++ "ListBNFC" +++ "_ es : doc = match es with"):rs

ifList :: CF -> Cat -> String
ifList cf cat = render $
case cases of
[] -> empty
ifList cf cat
| null rules = ""
| otherwise = render $ case cases of
[] -> empty -- IMPOSSIBLE CASE when (rules /= [])
first:rest -> vcat
[ "and prt" <> text (fixTypeUpper cat) <> "ListBNFC i es : doc = match (i, es) with"
, nest 4 first
, nest 2 $ vcat (map ("|" <+>) rest)
]
where
rules = sortBy compareRules $ rulesForNormalizedCat cf (ListCat cat)
cases = [ d | r <- rules, let d = mkPrtListCase r, not (isEmpty d) ]

cases = concat
[ [ "(_,[]) -> (concatD [])" | not $ any isNilFun rules ]
-- Andreas, 2021-09-22, issue #386
-- If the list is @nonempty@ according to the grammar, still add a nil case.
-- In the AST it is simply a list, and the AST could be created
-- by other means than by parsing.
, [ d | r <- rules, let d = mkPrtListCase r, not (isEmpty d) ]
]

-- | Pattern match on the list constructor and the coercion level
--
Expand Down

0 comments on commit 100552e

Please sign in to comment.