{-# LANGUAGE LambdaCase #-} -- | Common to the C++ backends. module BNFC.Backend.CPP.Common where import Data.Char ( isUpper ) import Data.List ( intercalate ) import BNFC.CF import BNFC.TypeChecker import BNFC.Backend.C ( comment ) import BNFC.Backend.CPP.Naming -- | C++ line comment including mode hint for emacs. commentWithEmacsModeHint :: String -> String commentWithEmacsModeHint = comment . ("-*- c++ -*- " ++) -- | C++ code for the @define@d constructors. -- -- @definedRules Nothing@ only prints the header. definedRules :: Maybe ListConstructors -> CF -> String -> String definedRules mlc cf banner | null theLines = [] | otherwise = unlines $ banner : "" : theLines where theLines = map rule $ definitions cf ctx = buildContext cf rule (Define f args e t) = case mlc of Nothing -> header ++ ";" Just lc -> unlines [ header ++ " {" , " return " ++ cppExp lc (map fst args) e ++ ";" , "}" ] where header = cppType t ++ " " ++ sanitizeCpp (funName f) ++ "(" ++ intercalate ", " (map cppArg args) ++ ")" cppType :: Base -> String cppType (ListT (BaseT x)) = "List" ++ x ++ "*" cppType (ListT t) = cppType t ++ "*" cppType (BaseT x) | x `elem` baseTokenCatNames = x | isToken x ctx = "String" | otherwise = x ++ "*" cppArg :: (String, Base) -> String cppArg (x,t) = cppType t ++ " " ++ x ++ "_" cppExp :: ListConstructors -> [String] -> Exp -> String cppExp (LC nil cons) args = loop where loop = \case App "[]" (FunT [] (ListT t)) [] -> fst $ nil t App "(:)" (FunT _ (ListT t)) es -> call (fst $ cons t) es Var x -> x ++ "_" -- argument App t _ [e] | isToken t ctx -> loop e App x _ es | isUpper (head x) -> call ("new " ++ x) es | x `elem` args -> call (x ++ "_") es | otherwise -> call (sanitizeCpp x) es LitInt n -> show n LitDouble x -> show x LitChar c -> show c LitString s -> show s call x es = x ++ "(" ++ intercalate ", " (map loop es) ++ ")"