{- BNF Converter: C# Visit Skeleton Generator Copyright (C) 2006 Author: Johan Broberg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- ************************************************************** BNF Converter Module Description : This module generates the C# Visit Skeleton. The generated file uses the Visitor design pattern. Author : Johan Broberg (johan@pontemonti.com) License : GPL (GNU General Public License) Created : 30 November, 2006 Modified : 21 January, 2007 by Johan Broberg ************************************************************** -} module CAbstoCSharpVisitSkeleton (cabs2csharpvisitskeleton) where import CF import Utils ((+++), (++++)) import NamedVariables import List import OOAbstract hiding (basetypes) import CSharpUtils import CAbstoCSharpAbs --Produces .cs file cabs2csharpvisitskeleton :: Namespace -> CAbs -> String cabs2csharpvisitskeleton namespace cabs = unlines [ "/*** BNFC-Generated Visitor Design Pattern Skeleton. ***/", "/* This implements the common visitor design pattern. To make sure that", " compile errors occur when code in the Visitor don't match the abstract", " syntaxt, the \"abstract visit skeleton\" is used.", " ", " Replace the R and A parameters with the desired return", " and context types.*/", "", "namespace " ++ namespace ++ ".VisitSkeleton", "{", " #region Classes", unlinesInlineMap (prCon namespace) (signatures cabs), " #endregion", " ", " #region Token types", unlinesInlineMap (prBasic namespace) (tokentypes cabs), " #endregion", "}" ] prBasic namespace c = unlinesInline [ " public class " ++ c ++ "Visitor : Abstract" ++ c ++ "Visitor", " {", " public override R Visit(" ++ identifier namespace (typename c) +++ varname c ++ ", A arg)", " {", " /* Code for " ++ c ++ " Goes Here */", " return default(R);", " }", " }" ] prCon :: Namespace -> (Cat, [CAbsRule]) -> String prCon namespace (c,fs) = unlinesInline [ " public class " ++ c ++ "Visitor : Abstract" ++ c ++ "Visitor", " {", unlinesInlineMap (prVisit namespace) (map cabsrule2csharpabsrule fs), " }" ] prVisit :: Namespace -> CSharpAbsRule -> String prVisit namespace (f,cs) = unlinesInline [ " public override R Visit(" ++ identifier namespace f +++ varname f ++ ", A arg)", " {", " /* Code For " ++ f ++ " Goes Here */", unlinesInline $ map (prVisitArg namespace (varname f)) cs, " return default(R);", " }" ] prVisitArg :: Namespace -> String -> (Cat, Bool, VariableName, PropertyName) -> String prVisitArg namespace vname (cat, isPt, var, prop) | cat `elem` (map fst basetypes) = " // " ++ vname ++ "." ++ prop -- var /= "list_" is a dummy fix to make sure that a category named "List" doesn't get interpreted as a List. -- this isn't very good though, and should be fixed somehow. | "list" `isPrefixOf` var && var /= "list_" = listAccept | otherwise = " " ++ vname ++ "." ++ prop ++ ".Accept(new " ++ cat ++ "Visitor(), arg);" where listtype = typename (drop 4 cat) listAccept = unlinesInline [ " foreach(" ++ identifier namespace listtype ++ " x in " ++ vname ++ "." ++ prop ++ ")", " {", if listtype `notElem` (map snd basetypes) then " x.Accept(new " ++ listtype ++ "Visitor(), arg);" else " // x", " }" ]