Skip to content

Commit

Permalink
Update PrettyPrinter code for using smart-ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
hangingman committed Nov 14, 2021
1 parent 6058374 commit d63861f
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 101 deletions.
15 changes: 14 additions & 1 deletion source/src/BNFC/Backend/CPP/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Data.List ( intercalate )

import BNFC.CF
import BNFC.TypeChecker

import BNFC.Options ( Ansi )
import BNFC.Backend.C ( comment )
import BNFC.Backend.CPP.Naming

Expand Down Expand Up @@ -72,3 +72,16 @@ definedRules mlc cf banner
LitString s -> show s

call x es = x ++ "(" ++ intercalate ", " (map loop es) ++ ")"

data CppStdMode
= CppStdAnsi Ansi -- ^ @Ansi@ mode.
| CppStdBeyondAnsi Ansi -- ^ @BeyondAnsi@ mode.

wrapPointerIf :: Bool -> String -> String
wrapPointerIf b v = if b then "*" ++ v else v

wrapUniquePtrIf :: Bool -> String -> String
wrapUniquePtrIf b v = if b then "std::unique_ptr<" ++v++">" else v

wrapMoveIf :: Bool -> String -> String
wrapMoveIf b v = if b then "std::move(" ++v++")" else v
4 changes: 2 additions & 2 deletions source/src/BNFC/Backend/CPP/NoSTL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import BNFC.Backend.Base
import BNFC.Backend.C ( bufferH, bufferC, comment, testfileHeader )
import BNFC.Backend.C.CFtoBisonC ( cf2Bison )
import BNFC.Backend.C.CFtoFlexC ( cf2flex, ParserMode(..) )
import BNFC.Backend.CPP.Common ( commentWithEmacsModeHint )
import BNFC.Backend.CPP.Common ( commentWithEmacsModeHint, CppStdMode(..) )
import BNFC.Backend.CPP.Makefile
import BNFC.Backend.CPP.NoSTL.CFtoCPPAbs
import BNFC.Backend.CPP.STL.CFtoCVisitSkelSTL
Expand All @@ -37,7 +37,7 @@ makeCppNoStl opts cf = do
let (skelH, skelC) = cf2CVisitSkel False Nothing cf
mkCppFile "Skeleton.H" skelH
mkCppFile "Skeleton.C" skelC
let (prinH, prinC) = cf2CPPPrinter False Nothing cf ".H"
let (prinH, prinC) = cf2CPPPrinter (CppStdAnsi Ansi) False Nothing cf ".H"
mkCppFile "Printer.H" prinH
mkCppFile "Printer.C" prinC
mkCppFile "Test.C" (cpptest cf)
Expand Down
165 changes: 98 additions & 67 deletions source/src/BNFC/Backend/CPP/PrettyPrinter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ import BNFC.Utils
import BNFC.Backend.Common
import BNFC.Backend.Common.NamedVariables
import BNFC.Backend.Common.StrUtils (renderCharOrString)
import BNFC.Backend.CPP.Common ( CppStdMode(..), wrapUniquePtrIf, wrapPointerIf )
import BNFC.Backend.CPP.STL.STLUtils
import BNFC.PrettyPrint

--Produces (.H file, .C file)
cf2CPPPrinter :: Bool -> Maybe String -> CF -> String -> (String, String)
cf2CPPPrinter useStl inPackage cf hExt =
(mkHFile useStl inPackage cf groups hExt, mkCFile useStl inPackage cf groups hExt)
cf2CPPPrinter :: CppStdMode -> Bool -> Maybe String -> CF -> String -> (String, String)
cf2CPPPrinter mode useStl inPackage cf hExt =
(mkHFile mode useStl inPackage cf groups hExt, mkCFile mode useStl inPackage cf groups hExt)
where
groups = when useStl (positionRules cf) -- CPP/NoSTL treats position tokens as just tokens
++ fixCoercions (ruleGroupsInternals cf)
Expand All @@ -51,8 +52,8 @@ positionRules cf =
{- **** Header (.H) File Methods **** -}

--An extremely large function to make the Header File
mkHFile :: Bool -> Maybe String -> CF -> [(Cat,[Rule])] -> String -> String
mkHFile useStl inPackage cf groups hExt = unlines
mkHFile :: CppStdMode -> Bool -> Maybe String -> CF -> [(Cat,[Rule])] -> String -> String
mkHFile mode useStl inPackage cf groups hExt = unlines
[ printHeader
, content
, classFooter
Expand Down Expand Up @@ -100,7 +101,7 @@ mkHFile useStl inPackage cf groups hExt = unlines
" char *print(Visitable *v);"
]
hdef = nsDefine inPackage "PRINTER_HEADER"
content = concatMap (prDataH useStl) groups
content = concatMap (prDataH mode useStl) groups
classFooter = unlines $
[
" void visitInteger(Integer i);",
Expand Down Expand Up @@ -185,38 +186,48 @@ mkHFile useStl inPackage cf groups hExt = unlines
]

--Prints all the required method names and their parameters.
prDataH :: Bool -> (Cat, [Rule]) -> String
prDataH useSTL (cat, rules)
| isList cat = unlines $ concat
[ [ concat [ " void visit", cl, "(", cl, " *p);" ] ]
, when useSTL
[ concat [ " void iter", cl, "(", itty, " i, ", itty, " j);" ] ]
]
| otherwise = abstract ++ concatMap prRuleH rules
where
cl = identCat (normCat cat)
itty = concat [ cl, "::", "const_iterator" ]
abstract = case lookupRule (noPosition $ catToStr cat) rules of
Just _ -> ""
Nothing -> " void visit" ++ cl ++ "(" ++ cl ++ " *p); /* abstract class */\n"
prDataH :: CppStdMode -> Bool -> (Cat, [Rule]) -> String
prDataH mode useSTL (cat, rules)
| isList cat = unlines $ concat
[ [ concat [ " void visit", cl, "(", wrapUniquePtrIf beyondAnsi cl, " ", vararg, ");" ] ]
, when useSTL
[ concat [ " void iter", cl, "(", itty, " i, ", itty, " j);" ] ]
]
| otherwise = abstract ++ concatMap prRuleH rules
where
beyondAnsi = case mode of
CppStdBeyondAnsi _ -> True
CppStdAnsi _ -> False
cl = identCat (normCat cat)
vararg = if beyondAnsi then "p" else "*p"
prRuleH = if beyondAnsi then prRuleHBeyondAnsi else prRuleHAnsi
itty = concat [ cl, "::", "const_iterator" ]
abstract = case lookupRule (noPosition $ catToStr cat) rules of
Just _ -> ""
Nothing -> " void visit" ++ cl ++ "(" ++ wrapUniquePtrIf beyondAnsi cl +++ vararg ++ "); /* abstract class */\n"

--Prints all the methods to visit a rule.
prRuleH :: IsFun f => Rul f -> String
prRuleH (Rule fun _ _ _) | isProperLabel fun = concat
prRuleHAnsi :: IsFun f => Rul f -> String
prRuleHAnsi (Rule fun _ _ _) | isProperLabel fun = concat
[" void visit", funName fun, "(", funName fun, " *p);\n"]
prRuleH _ = ""
prRuleHAnsi _ = ""

prRuleHBeyondAnsi :: IsFun f => Rul f -> String
prRuleHBeyondAnsi (Rule fun _ _ _) | isProperLabel fun = concat
[" void visit", funName fun, "(", wrapUniquePtrIf True (funName fun), " p);\n"]
prRuleHBeyondAnsi _ = ""

{- **** Implementation (.C) File Methods **** -}

--This makes the .C file by a similar method.
mkCFile :: Bool -> Maybe String -> CF -> [(Cat,[Rule])] -> String -> String
mkCFile useStl inPackage cf groups hExt = concat
mkCFile :: CppStdMode -> Bool -> Maybe String -> CF -> [(Cat,[Rule])] -> String -> String
mkCFile mode useStl inPackage cf groups hExt = concat
[
header,
nsStart inPackage ++ "\n",
prRender useStl,
printEntries,
concatMap (prPrintData useStl inPackage cf) groups,
concatMap (prPrintData useStl mode inPackage cf) groups,
printBasics,
printTokens,
showEntries,
Expand All @@ -226,6 +237,7 @@ mkCFile useStl inPackage cf groups hExt = concat
nsEnd inPackage ++ "\n"
]
where

header = unlines
[
"/*** Pretty Printer and Abstract Syntax Viewer ***/",
Expand Down Expand Up @@ -376,33 +388,30 @@ mkCFile useStl inPackage cf groups hExt = concat
{- **** Pretty Printer Methods **** -}

-- | Generates methods for the Pretty Printer.
prPrintData :: Bool -> Maybe String -> CF -> (Cat, [Rule]) -> String
prPrintData True {- use STL -} _ _ (cat@(ListCat _), rules) =
render $ genPrintVisitorList (cat, rules)
prPrintData False {- use STL -} _ _ (cat@(ListCat _), rules) =
genPrintVisitorListNoStl (cat, rules)
-- Not a list :
prPrintData _ _inPackage cf (TokenCat cat, _rules) | isPositionCat cf cat = unlines $
-- a position token
[ "void PrintAbsyn::visit" ++ cat ++ "(" ++ cat ++ " *p)"
, "{"
, " visitIdent(p->string_);"
, "}"
, ""
]
prPrintData _ inPackage _cf (cat, rules) = -- Not a list
abstract ++ concatMap (prPrintRule inPackage) rules
prPrintData :: Bool -> CppStdMode -> Maybe String -> CF -> (Cat, [Rule]) -> String
prPrintData True mode _ _ (cat@(ListCat _), rules) =
render $ genPrintVisitorList (mode, cat, rules)
prPrintData False mode _ _ (cat@(ListCat _), rules) =
genPrintVisitorListNoStl (mode, cat, rules)
prPrintData _ mode _inPackage cf (TokenCat cat, _rules) |
isPositionCat cf cat = genPositionToken cat
prPrintData _ mode inPackage _cf (cat, rules) =
abstract ++ concatMap (prPrintRule beyondAnsi inPackage) rules
where
cl = identCat (normCat cat)
abstract = case lookupRule (noPosition $ catToStr cat) rules of
Just _ -> ""
Nothing -> "void PrintAbsyn::visit" ++ cl ++ "(" ++ cl +++ "*p) {} //abstract class\n\n"
beyondAnsi = case mode of
CppStdBeyondAnsi _ -> True
CppStdAnsi _ -> False
cl = identCat (normCat cat)
vararg = if beyondAnsi then "p" else "*p"
abstract = case lookupRule (noPosition $ catToStr cat) rules of
Just _ -> ""
Nothing -> "void PrintAbsyn::visit" ++ cl ++ "(" ++ wrapUniquePtrIf beyondAnsi cl +++ vararg ++") {} //abstract class\n\n"

-- | Generate pretty printer visitor for a list category (STL version).
--
genPrintVisitorList :: (Cat, [Rule]) -> Doc
genPrintVisitorList (cat@(ListCat _), rules) = vcat
[ "void PrintAbsyn::visit" <> lty <> parens (lty <+> "*" <> vname)
genPrintVisitorList :: (CppStdMode, Cat, [Rule]) -> Doc
genPrintVisitorList (mode, cat@(ListCat _), rules) = vcat
[ "void PrintAbsyn::visit" <> lty <> parens (ltyarg <+> varg)
, codeblock 2
[ "iter" <> lty <> parens (vname <> "->begin()" <> comma <+> vname <> "->end()") <> semi ]
, ""
Expand Down Expand Up @@ -433,10 +442,15 @@ genPrintVisitorList (cat@(ListCat _), rules) = vcat
, ""
]
where
beyondAnsi = case mode of
CppStdBeyondAnsi _ -> True
CppStdAnsi _ -> False
cl = identCat (normCat cat)
lty = text cl -- List type
lty = text cl -- List type
ltyarg = text $ wrapUniquePtrIf beyondAnsi cl -- List type arg
itty = lty <> "::const_iterator" -- Iterator type
vname = text $ map toLower cl
varg = text $ wrapPointerIf (not beyondAnsi) (map toLower cl)
prules = sortRulesByPrecedence rules
swRules f = switchByPrecedence "_i_" $
map (second $ sep . prListRule_) $
Expand All @@ -448,6 +462,16 @@ genPrintVisitorList (cat@(ListCat _), rules) = vcat

genPrintVisitorList _ = error "genPrintVisitorList expects a ListCat"

genPositionToken :: String -> String
genPositionToken cat = unlines $
-- a position token
[ "void PrintAbsyn::visit" ++ cat ++ "(" ++ cat ++ " *p)"
, "{"
, " visitIdent(p->string_);"
, "}"
, ""
]

-- | Only render the rhs (items) of a list rule.

prListRule_ :: IsFun a => Rul a -> [Doc]
Expand All @@ -464,9 +488,9 @@ prListRule_ (Rule _ _ items _) = for items $ \case
-- This is the only part of the pretty printer that differs significantly
-- between the versions with and without STL.
-- The present version has been adapted from CFtoCPrinter.
genPrintVisitorListNoStl :: (Cat, [Rule]) -> String
genPrintVisitorListNoStl (cat@(ListCat _), rules) = unlines $ concat
[ [ "void PrintAbsyn::visit" ++ cl ++ "("++ cl ++ " *" ++ vname ++ ")"
genPrintVisitorListNoStl :: (CppStdMode, Cat, [Rule]) -> String
genPrintVisitorListNoStl (mode, cat@(ListCat _), rules) = unlines $ concat
[ [ "void PrintAbsyn::visit" ++ cl ++ "("++ wrapUniquePtrIf beyondAnsi cl +++ varg ++ ")"
, "{"
, " if (" ++ vname +++ "== 0)"
, " { /* nil */"
Expand All @@ -491,20 +515,24 @@ genPrintVisitorListNoStl (cat@(ListCat _), rules) = unlines $ concat
]
]
where
cl = identCat (normCat cat)
vname = map toLower cl
pre = vname ++ "->"
prules = sortRulesByPrecedence rules
swRules f = switchByPrecedence "_i_" $
beyondAnsi = case mode of
CppStdBeyondAnsi _ -> True
CppStdAnsi _ -> False
cl = identCat (normCat cat)
vname = map toLower cl
varg = wrapPointerIf (not beyondAnsi) (map toLower cl)
pre = vname ++ "->"
prules = sortRulesByPrecedence rules
swRules f = switchByPrecedence "_i_" $
map (second $ sep . map text . prPrintRule_ pre) $
uniqOn fst $ filter f prules
-- Discard duplicates, can only handle one rule per precedence.
uniqOn fst $ filter f prules
-- Discard duplicates, can only handle one rule per precedence.
genPrintVisitorListNoStl _ = error "genPrintVisitorListNoStl expects a ListCat"

--Pretty Printer methods for a rule.
prPrintRule :: Maybe String -> Rule -> String
prPrintRule inPackage r@(Rule fun _ _ _) | isProperLabel fun = unlines $ concat
[ [ "void PrintAbsyn::visit" ++ funName fun ++ "(" ++ funName fun +++ "*" ++ fnm ++ ")"
prPrintRule :: Bool -> Maybe String -> Rule -> String
prPrintRule beyondAnsi inPackage r@(Rule fun _ _ _) | isProperLabel fun = unlines $ concat
[ [ "void PrintAbsyn::visit" ++ visitFunName ++ "(" ++ vararg +++ fnm ++ ")"
, "{"
, " int oldi = _i_;"
, parenCode "_L_PAREN"
Expand All @@ -519,10 +547,13 @@ prPrintRule inPackage r@(Rule fun _ _ _) | isProperLabel fun = unlines $ concat
]
]
where
p = precRule r
parenCode x = " if (oldi > " ++ show p ++ ") render(" ++ nsDefine inPackage x ++ ");"
fnm = "p" --old names could cause conflicts
prPrintRule _ _ = ""
visitFunName = funName fun
vararg = wrapUniquePtrIf beyondAnsi (funName fun)
p = precRule r
parenCode x = " if (oldi > " ++ show p ++ ") render(" ++ nsDefine inPackage x ++ ");"
fnm = if beyondAnsi then "p" else "*p" --old names could cause conflicts

prPrintRule _ _ _ = ""

prPrintRule_ :: IsFun a => String -> Rul a -> [String]
prPrintRule_ pre (Rule _ _ items _) = map (prPrintItem pre) $ numVars items
Expand Down
4 changes: 2 additions & 2 deletions source/src/BNFC/Backend/CPP/STL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import BNFC.Backend.Base
import BNFC.Backend.C ( bufferH, bufferC, comment, testfileHeader )
import BNFC.Backend.C.CFtoBisonC ( cf2Bison, unionBuiltinTokens, positionCats, varName )
import BNFC.Backend.C.CFtoFlexC ( cf2flex, ParserMode(..), beyondAnsi, parserPackage, parserName, stlParser )
import BNFC.Backend.CPP.Common ( commentWithEmacsModeHint )
import BNFC.Backend.CPP.Common ( commentWithEmacsModeHint, CppStdMode(..) )
import BNFC.Backend.CPP.Makefile
import BNFC.Backend.CPP.STL.CFtoSTLAbs
import BNFC.Backend.CPP.STL.CFtoCVisitSkelSTL
Expand All @@ -48,7 +48,7 @@ makeCppStl opts cf = do
let (skelH, skelC) = cf2CVisitSkel True (inPackage opts) cf
mkCppFile ("Skeleton" ++ hExt) skelH
mkCppFile ("Skeleton" ++ cppExt) skelC
let (prinH, prinC) = cf2CPPPrinter True (inPackage opts) cf hExt
let (prinH, prinC) = cf2CPPPrinter cppStdMode True (inPackage opts) cf hExt
mkCppFile ("Printer" ++ hExt) prinH
mkCppFile ("Printer" ++ cppExt) prinC
mkCppFile ("Test" ++ cppExt) (cpptest (inPackage opts) cf hExt)
Expand Down
Loading

0 comments on commit d63861f

Please sign in to comment.