BNFC-2.5.0: src/formats/c-sharp/CAbstoCSharpVisitSkeleton.hs
{-
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 Data.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<R,A> : Abstract" ++ c ++ "Visitor<R,A>",
" {",
" 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<R,A> : Abstract" ++ c ++ "Visitor<R,A>",
" {",
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<R,A>(), 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<R,A>(), arg);"
else " // x",
" }"
]