{-
    BNF Converter: C++ Main file
    Copyright (C) 2004  Author:  Markus Forsberg, Michael Pellauer
-}

module BNFC.Backend.CPP.NoSTL (makeCppNoStl) where

import Data.Char
import Data.Foldable (toList)
import Data.List (nub)
import qualified Data.Map as Map

import BNFC.Utils
import BNFC.CF
import BNFC.Options
import BNFC.Backend.Base
import BNFC.Backend.C            (bufferH, bufferC)
import BNFC.Backend.C.CFtoBisonC (unionBuiltinTokens)
import BNFC.Backend.CPP.Makefile
import BNFC.Backend.CPP.NoSTL.CFtoCPPAbs
import BNFC.Backend.CPP.NoSTL.CFtoFlex
import BNFC.Backend.CPP.NoSTL.CFtoBison
import BNFC.Backend.CPP.STL.CFtoCVisitSkelSTL
import BNFC.Backend.CPP.PrettyPrinter
import qualified BNFC.Backend.Common.Makefile as Makefile

makeCppNoStl :: SharedOptions -> CF -> MkFiles ()
makeCppNoStl :: SharedOptions -> CF -> MkFiles ()
makeCppNoStl SharedOptions
opts CF
cf = do
    let ([Char]
hfile, [Char]
cfile) = [Char] -> CF -> ([Char], [Char])
cf2CPPAbs [Char]
name CF
cf
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Absyn.H" [Char]
hfile
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Absyn.C" [Char]
cfile
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Buffer.H" [Char]
bufferH
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Buffer.C" ([Char] -> MkFiles ()) -> [Char] -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
bufferC [Char]
"Buffer.H"
    let ([Char]
flex, SymMap
env) = Maybe [Char] -> [Char] -> CF -> ([Char], SymMap)
cf2flex Maybe [Char]
forall a. Maybe a
Nothing [Char]
name CF
cf
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".l") [Char]
flex
    let bison :: [Char]
bison = [Char] -> CF -> SymMap -> [Char]
cf2Bison [Char]
name CF
cf SymMap
env
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".y") [Char]
bison
    let header :: [Char]
header = CF -> [Cat] -> [Cat] -> [[Char]] -> [Char]
forall {f}. CFG f -> [Cat] -> [Cat] -> [[Char]] -> [Char]
mkHeaderFile CF
cf (CF -> [Cat]
forall f. CFG f -> [Cat]
allParserCats CF
cf) (NonEmpty Cat -> [Cat]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall a b. (a -> b) -> a -> b
$ CF -> NonEmpty Cat
forall f. CFG f -> NonEmpty Cat
allEntryPoints CF
cf) (SymMap -> [[Char]]
forall k a. Map k a -> [a]
Map.elems SymMap
env)
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Parser.H" [Char]
header
    let ([Char]
skelH, [Char]
skelC) = Bool -> Maybe [Char] -> CF -> ([Char], [Char])
cf2CVisitSkel Bool
False Maybe [Char]
forall a. Maybe a
Nothing CF
cf
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Skeleton.H" [Char]
skelH
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Skeleton.C" [Char]
skelC
    let ([Char]
prinH, [Char]
prinC) = Bool -> Maybe [Char] -> CF -> ([Char], [Char])
cf2CPPPrinter Bool
False Maybe [Char]
forall a. Maybe a
Nothing CF
cf
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Printer.H" [Char]
prinH
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Printer.C" [Char]
prinC
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile [Char]
"Test.C" (CF -> [Char]
cpptest CF
cf)
    SharedOptions -> ([Char] -> Doc) -> MkFiles ()
Makefile.mkMakefile SharedOptions
opts (([Char] -> Doc) -> MkFiles ()) -> ([Char] -> Doc) -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> Doc
makefile [Char]
name
  where name :: [Char]
name = SharedOptions -> [Char]
lang SharedOptions
opts


cpptest :: CF -> String
cpptest :: CF -> [Char]
cpptest CF
cf =
  [[Char]] -> [Char]
unlines
   [
    [Char]
"/*** Compiler Front-End Test automatically generated by the BNF Converter ***/",
    [Char]
"/*                                                                          */",
    [Char]
"/* This test will parse a file, print the abstract syntax tree, and then    */",
    [Char]
"/* pretty-print the result.                                                 */",
    [Char]
"/*                                                                          */",
    [Char]
"/****************************************************************************/",
    [Char]
"#include <stdio.h>",
    [Char]
"#include <string.h>",
    [Char]
"#include \"Parser.H\"",
    [Char]
"#include \"Printer.H\"",
    [Char]
"#include \"Absyn.H\"",
    [Char]
"",
    [Char]
"void usage() {",
    [Char]
"  printf(\"usage: Call with one of the following argument " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
      [Char]
"combinations:\\n\");",
    [Char]
"  printf(\"\\t--help\\t\\tDisplay this help message.\\n\");",
    [Char]
"  printf(\"\\t(no arguments)\\tParse stdin verbosely.\\n\");",
    [Char]
"  printf(\"\\t(files)\\t\\tParse content of files verbosely.\\n\");",
    [Char]
"  printf(\"\\t-s (files)\\tSilent mode. Parse content of files " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
      [Char]
"silently.\\n\");",
    [Char]
"}",
    [Char]
"",
    [Char]
"int main(int argc, char ** argv)",
    [Char]
"{",
    [Char]
"  FILE *input;",
    [Char]
"  int quiet = 0;",
    [Char]
"  char *filename = NULL;",
    [Char]
"",
    [Char]
"  if (argc > 1) {",
    [Char]
"    if (strcmp(argv[1], \"-s\") == 0) {",
    [Char]
"      quiet = 1;",
    [Char]
"      if (argc > 2) {",
    [Char]
"        filename = argv[2];",
    [Char]
"      } else {",
    [Char]
"        input = stdin;",
    [Char]
"      }",
    [Char]
"    } else {",
    [Char]
"      filename = argv[1];",
    [Char]
"    }",
    [Char]
"  }",
    [Char]
"",
    [Char]
"  if (filename) {",
    [Char]
"    input = fopen(filename, \"r\");",
    [Char]
"    if (!input) {",
    [Char]
"      usage();",
    [Char]
"      exit(1);",
    [Char]
"    }",
    [Char]
"  } else input = stdin;",
    [Char]
"  /* The default entry point is used. For other options see Parser.H */",
    [Char]
"  " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dat [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" *parse_tree = p" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
def [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"(input);",
    [Char]
"  if (parse_tree)",
    [Char]
"  {",
    [Char]
"    printf(\"\\nParse Successful!\\n\");",
    [Char]
"    if (!quiet) {",
    [Char]
"      printf(\"\\n[Abstract Syntax]\\n\");",
    [Char]
"      ShowAbsyn *s = new ShowAbsyn();",
    [Char]
"      printf(\"%s\\n\\n\", s->show(parse_tree));",
    [Char]
"      printf(\"[Linearized Tree]\\n\");",
    [Char]
"      PrintAbsyn *p = new PrintAbsyn();",
    [Char]
"      printf(\"%s\\n\\n\", p->print(parse_tree));",
    [Char]
"    }",
    [Char]
"    return 0;",
    [Char]
"  }",
    [Char]
"  return 1;",
    [Char]
"}",
    [Char]
""
   ]
  where
   cat :: Cat
cat = CF -> Cat
firstEntry CF
cf
   dat :: [Char]
dat = Cat -> [Char]
identCat (Cat -> [Char]) -> Cat -> [Char]
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
cat
   def :: [Char]
def = Cat -> [Char]
identCat Cat
cat

mkHeaderFile :: CFG f -> [Cat] -> [Cat] -> [[Char]] -> [Char]
mkHeaderFile CFG f
cf [Cat]
cats [Cat]
eps [[Char]]
env = [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ [[[Char]]] -> [[Char]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [ [ [Char]
"#ifndef PARSER_HEADER_FILE"
    , [Char]
"#define PARSER_HEADER_FILE"
    , [Char]
""
    ]
  , (Cat -> [Char]) -> [Cat] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> [Char]
mkForwardDec ([Cat] -> [[Char]]) -> [Cat] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ [Cat] -> [Cat]
forall a. Eq a => [a] -> [a]
nub ([Cat] -> [Cat]) -> [Cat] -> [Cat]
forall a b. (a -> b) -> a -> b
$ (Cat -> Cat) -> [Cat] -> [Cat]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> Cat
normCat [Cat]
cats
  , [ [Char]
"typedef union"
    , [Char]
"{"
    ]
  , ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
"  " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) [[Char]]
unionBuiltinTokens
  , (Cat -> [[Char]]) -> [Cat] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Cat -> [[Char]]
mkVar [Cat]
cats
  , [ [Char]
"} YYSTYPE;"
    , [Char]
""
    , [Char]
"#define _ERROR_ 258"
    , Int -> [[Char]] -> [Char]
forall {t}. (Show t, Num t) => t -> [[Char]] -> [Char]
mkDefines (Int
259 :: Int) [[Char]]
env
    , [Char]
"extern YYSTYPE yylval;"
    , [Char]
""
    ]
  , (Cat -> [Char]) -> [Cat] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> [Char]
mkFunc [Cat]
eps
  , [ [Char]
""
    , [Char]
"#endif"
    ]
  ]
  where
  mkForwardDec :: Cat -> [Char]
mkForwardDec Cat
s = [Char]
"class " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat Cat
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
";"
  mkVar :: Cat -> [[Char]]
mkVar Cat
s | Cat -> Cat
normCat Cat
s Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
== Cat
s = [ [Char]
"  " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat Cat
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char]
"*" [Char] -> [Char] -> [Char]
+++ (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (Cat -> [Char]
identCat Cat
s) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"_;" ]
  mkVar Cat
_ = []
  mkDefines :: t -> [[Char]] -> [Char]
mkDefines t
n [] = t -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkString t
n
  mkDefines t
n ([Char]
s:[[Char]]
ss) = [Char]
"#define " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
+++ t -> [Char]
forall a. Show a => a -> [Char]
show t
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ t -> [[Char]] -> [Char]
mkDefines (t
nt -> t -> t
forall a. Num a => a -> a -> a
+t
1) [[Char]]
ss
  mkString :: a -> [Char]
mkString a
n =  if CFG f -> Cat -> Bool
forall f. CFG f -> Cat -> Bool
isUsedCat CFG f
cf ([Char] -> Cat
TokenCat [Char]
catString)
   then ([Char]
"#define _STRING_ " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n") [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkChar (a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
   else a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkChar a
n
  mkChar :: a -> [Char]
mkChar a
n =  if CFG f -> Cat -> Bool
forall f. CFG f -> Cat -> Bool
isUsedCat CFG f
cf ([Char] -> Cat
TokenCat [Char]
catChar)
   then ([Char]
"#define _CHAR_ " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n") [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkInteger (a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
   else a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkInteger a
n
  mkInteger :: a -> [Char]
mkInteger a
n =  if CFG f -> Cat -> Bool
forall f. CFG f -> Cat -> Bool
isUsedCat CFG f
cf ([Char] -> Cat
TokenCat [Char]
catInteger)
   then ([Char]
"#define _INTEGER_ " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n") [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkDouble (a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
   else a -> [Char]
forall {a}. (Show a, Num a) => a -> [Char]
mkDouble a
n
  mkDouble :: a -> [Char]
mkDouble a
n =  if CFG f -> Cat -> Bool
forall f. CFG f -> Cat -> Bool
isUsedCat CFG f
cf ([Char] -> Cat
TokenCat [Char]
catDouble)
   then ([Char]
"#define _DOUBLE_ " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n") [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
mkIdent(a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
   else a -> [Char]
forall a. Show a => a -> [Char]
mkIdent a
n
  mkIdent :: a -> [Char]
mkIdent a
n =  if CFG f -> Cat -> Bool
forall f. CFG f -> Cat -> Bool
isUsedCat CFG f
cf ([Char] -> Cat
TokenCat [Char]
catIdent)
   then [Char]
"#define _IDENT_ " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\n"
   else [Char]
""
  mkFunc :: Cat -> [Char]
mkFunc Cat
s = Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
s) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"*" [Char] -> [Char] -> [Char]
+++ [Char]
"p" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat Cat
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"(FILE *inp);"