From 7b7622628374ff48b263f9939f7bf21d8844d353 Mon Sep 17 00:00:00 2001 From: "hiroyuki.nagata" Date: Tue, 26 Oct 2021 23:38:56 +0900 Subject: [PATCH] [WIP] Generate C++ parser with driver setting --- source/src/BNFC/Backend/C/CFtoBisonC.hs | 189 +++++++++++------- source/src/BNFC/Backend/C/CFtoFlexC.hs | 12 +- source/src/BNFC/Backend/CPP/STL/CFtoSTLAbs.hs | 2 + 3 files changed, 122 insertions(+), 81 deletions(-) diff --git a/source/src/BNFC/Backend/C/CFtoBisonC.hs b/source/src/BNFC/Backend/C/CFtoBisonC.hs index 06d306ae..aff9a7b6 100644 --- a/source/src/BNFC/Backend/C/CFtoBisonC.hs +++ b/source/src/BNFC/Backend/C/CFtoBisonC.hs @@ -30,17 +30,18 @@ import Prelude hiding ((<>)) import Data.Char ( toLower, isUpper ) import Data.Foldable ( toList ) import Data.List ( intercalate, nub ) +import Data.Maybe ( fromMaybe ) import qualified Data.Map as Map import System.FilePath ( (<.>) ) import BNFC.CF import BNFC.Backend.Common.NamedVariables hiding (varName) -import BNFC.Backend.C.CFtoFlexC (ParserMode(..), cParser, reentrant, stlParser, parserHExt, parserName, parserPackage, variant, isBisonUseUnion, isBisonUseVariant) +import BNFC.Backend.C.CFtoFlexC (ParserMode(..), cParser, reentrant, stlParser, parserHExt, parserName, parserPackage, variant, isBisonUseUnion, isBisonUseVariant, beyondAnsi) import BNFC.Backend.CPP.Naming import BNFC.Backend.CPP.STL.STLUtils import BNFC.Options (RecordPositions(..), InPackage, Ansi(..)) import BNFC.PrettyPrint -import BNFC.Utils ((+++), table, applyWhen, for, unless, when, whenJust) +import BNFC.Utils ((+++), table, applyWhen, for, unless, when, whenJust, camelCase_) --This follows the basic structure of CFtoHappy. @@ -127,81 +128,121 @@ positionCats :: CF -> [String] positionCats cf = [ wpThing name | TokenReg name True _ <- cfgPragmas cf ] header :: ParserMode -> CF -> String -header mode cf = unlines $ concat - [ [ "/* Parser definition to be used with Bison. */" - , "" - , "/* Generate header file for lexer. */" - , "%defines \"" ++ ("Bison" <.> h) ++ "\"" - ] +header mode cf = unlines $ concat [ + -- + -- Common header + -- + [ "/* Parser definition to be used with Bison. */" + , "" + , "/* Generate header file for lexer. */" + , "%defines \"" ++ ("Bison" <.> h) ++ "\"" + ] , whenJust (parserPackage mode) $ \ ns -> - [ "%name-prefix = \"" ++ ns ++ "\"" - , " /* From Bison 2.6: %define api.prefix {" ++ ns ++ "} */" - ] - , [ "" - , "/* Reentrant parser */" - , reentrant mode - , "/* From Bison 2.3b (2008): %define api.pure full */" - -- The flag %pure_parser is deprecated with a warning since Bison 3.4, - -- but older Bisons like 2.3 (2006, shipped with macOS) don't recognize - -- %define api.pure full - , "%lex-param { yyscan_t scanner }" - , "%parse-param { yyscan_t scanner }" - , "" - , concat [ "/* Turn on line/column tracking in the ", name, "lloc structure: */" ] - , "%locations" - , "" - , "/* Argument to the parser to be filled with the parsed tree. */" - , "%parse-param { YYSTYPE *result }" - , "" - -- Use variant type if c++14 - , unlines $ (variant mode) - -- Use std::move if c++14 - --, unlines $ (automove mode) - , "" - , "%{" - , "/* Begin C preamble code */" - , "" - ] - -- Andreas, 2021-08-26, issue #377: Some C++ compilers want "algorithm". - -- Fixing regression introduced in 2.9.2. - , when (stlParser mode) - [ "#include /* for std::reverse */" -- mandatory e.g. with GNU C++ 11 - ] - , [ "#include " - , "#include " - , "#include " - , "#include \"" ++ ("Absyn" <.> h) ++ "\"" - , "" - , "#define YYMAXDEPTH 10000000" -- default maximum stack size is 10000, but right-recursion needs O(n) stack - , "" - , "/* The type yyscan_t is defined by flex, but we need it in the parser already. */" - , "#ifndef YY_TYPEDEF_YY_SCANNER_T" - , "#define YY_TYPEDEF_YY_SCANNER_T" - , "typedef void* yyscan_t;" - , "#endif" - , "" - -- , "typedef struct " ++ name ++ "_buffer_state *YY_BUFFER_STATE;" - , "typedef struct yy_buffer_state *YY_BUFFER_STATE;" - , "extern YY_BUFFER_STATE " ++ name ++ "_scan_string(const char *str, yyscan_t scanner);" - , "extern void " ++ name ++ "_delete_buffer(YY_BUFFER_STATE buf, yyscan_t scanner);" - , "" - , "extern void " ++ name ++ "lex_destroy(yyscan_t scanner);" - , "extern char* " ++ name ++ "get_text(yyscan_t scanner);" - , "" - , "extern yyscan_t " ++ name ++ "_initialize_lexer(FILE * inp);" - , "" - ] - , unless (stlParser mode) - [ "/* List reversal functions. */" - , concatMap (reverseList mode) $ filter isList $ allParserCatsNorm cf - ] - , [ "/* End C preamble code */" - , "%}" - ] + if beyondAnsi mode then + [ "%api.namespace = \"" ++ ns ++ "\"" + , "/* Specify the namespace for the C++ parser class. */"] + else + [ "%name-prefix = \"" ++ ns ++ "\"" + , "/* From Bison 2.6: %define api.prefix {" ++ ns ++ "} */"] + , if beyondAnsi mode then + -- Bison c++ beyond ansi mode + ["" + , "/* Reentrant parser */" + , "/* lalr1.cc always pure parser. needless to define %define api.pure full */" + , "" + , "%define api.parser.class {" ++ camelCaseName ++ "Parser}" + , "%code requires{" + , " namespace " ++ driverNs ++ " {" + , " class " ++ camelCaseName ++ "Scanner;" + , " class " ++ camelCaseName ++ "Driver;" + , " }" + , "}" + , "%parse-param { " ++ camelCaseName ++ "Scanner &scanner }" + , "%parse-param { " ++ camelCaseName ++ "Driver &driver }" + , "" + , "/* Turn on line/column tracking in the " ++name++ "lloc structure: */" + , "%locations" + , "/* variant based implementation of semantic values for C++ */" + , "%require \"3.2\"" + , "%define api.value.type variant" + , "/* 'yacc.c' does not support variant, so use skeleton 'lalr1.cc' */" + , "%skeleton \"lalr1.cc\"" + , "" + , "%code{" + , "/* Begin C++ preamble code */" + , "#include /* for std::reverse */" + , "#include " + , "#include " + , "#include " + , "" + , "/* include for all driver functions */" + , "#include \"Driver.H\"" + , "" + , "#undef yylex" + , "#define yylex scanner.yylex" + , "}" + , "" + ] + else + -- Bison c/c++ ansi mode + ["" + , "/* Reentrant parser */" + , "%pure_parser" + , "/* From Bison 2.3b (2008): %define api.pure full */" + , "/* The flag %pure_parser is deprecated with a warning since Bison 3.4, */" + , "/* but older Bisons like 2.3 (2006, shipped with macOS) don't recognize %define api.pure full */" + , "" + , "%lex-param { yyscan_t scanner }" + , "%parse-param { yyscan_t scanner }" + , "" + , "/* Turn on line/column tracking in the " ++name++ "lloc structure: */" + , "%locations" + , "/* Argument to the parser to be filled with the parsed tree. */" + , "%parse-param { YYSTYPE *result }" + , "" + , "%{" + , "/* Begin C preamble code */" + , "" + -- Andreas, 2021-08-26, issue #377: Some C++ compilers want "algorithm". + -- Fixing regression introduced in 2.9.2. + , when (stlParser mode) + "#include /* for std::reverse */" -- mandatory e.g. with GNU C++ 11 + , "#include " + , "#include " + , "#include " + , "#include \"" ++ ("Absyn" <.> h) ++ "\"" + , "" + , "#define YYMAXDEPTH 10000000" -- default maximum stack size is 10000, but right-recursion needs O(n) stack + , "" + , "/* The type yyscan_t is defined by flex, but we need it in the parser already. */" + , "#ifndef YY_TYPEDEF_YY_SCANNER_T" + , "#define YY_TYPEDEF_YY_SCANNER_T" + , "typedef void* yyscan_t;" + , "#endif" + , "" + , "typedef struct " ++ name ++ "_buffer_state *YY_BUFFER_STATE;" + , "typedef struct yy_buffer_state *YY_BUFFER_STATE;" + , "extern YY_BUFFER_STATE " ++ name ++ "_scan_string(const char *str, yyscan_t scanner);" + , "extern void " ++ name ++ "_delete_buffer(YY_BUFFER_STATE buf, yyscan_t scanner);" + , "" + , "extern void " ++ name ++ "lex_destroy(yyscan_t scanner);" + , "extern char* " ++ name ++ "get_text(yyscan_t scanner);" + , "" + , "extern yyscan_t " ++ name ++ "_initialize_lexer(FILE * inp);" + , "" + , unless (stlParser mode) + unlines [ "/* List reversal functions. */" + , concatMap (reverseList mode) $ filter isList $ allParserCatsNorm cf] + , "/* End C preamble code */" + , "%}" + ] ] where - h = parserHExt mode - name = parserName mode + h = parserHExt mode + name = parserName mode + camelCaseName = camelCase_ name + -- namespace for C++ driver + driverNs = fromMaybe camelCaseName (parserPackage mode) -- | Code that needs the @YYSTYPE@ defined by the @%union@ pragma. -- diff --git a/source/src/BNFC/Backend/C/CFtoFlexC.hs b/source/src/BNFC/Backend/C/CFtoFlexC.hs index 532d76b5..689adaf2 100644 --- a/source/src/BNFC/Backend/C/CFtoFlexC.hs +++ b/source/src/BNFC/Backend/C/CFtoFlexC.hs @@ -17,7 +17,7 @@ module BNFC.Backend.C.CFtoFlexC ( cf2flex - , ParserMode(..), parserName, parserPackage, reentrant, cParser, stlParser, parserHExt, variant, automove, isBisonUseUnion, isBisonUseVariant + , ParserMode(..), parserName, parserPackage, reentrant, cParser, stlParser, parserHExt, variant, beyondAnsi, isBisonUseUnion, isBisonUseVariant , preludeForBuffer -- C code defining a buffer for lexing string literals. , cMacros -- Lexer definitions. , commentStates -- Stream of names for lexer states for comments. @@ -72,12 +72,10 @@ variant = \case ,"%skeleton \"lalr1.cc\""] _ -> [] -automove :: ParserMode -> [String] -automove = \case - CppParser _ _ ansi | ansi == BeyondAnsi -> [ - "/* every occurrence '$n' is replaced by 'std::move ($n)' */" - , "%define api.value.automove"] - _ -> [] +beyondAnsi :: ParserMode -> Bool +beyondAnsi = \case + CppParser _ _ ansi | ansi == BeyondAnsi -> True + _ -> False isBisonUseUnion :: ParserMode -> Bool isBisonUseUnion = \case diff --git a/source/src/BNFC/Backend/CPP/STL/CFtoSTLAbs.hs b/source/src/BNFC/Backend/CPP/STL/CFtoSTLAbs.hs index 9c2b35db..e0f1a936 100644 --- a/source/src/BNFC/Backend/CPP/STL/CFtoSTLAbs.hs +++ b/source/src/BNFC/Backend/CPP/STL/CFtoSTLAbs.hs @@ -285,6 +285,8 @@ prListC :: CppStdMode -> (String,Bool) -> String prListC mode (c,b) = unlines [ "/******************** " ++ c ++ " ********************/" , case mode of { + CppStdAnsi _ -> [] + ; CppStdBeyondAnsi _ -> unlines [ c ++ "::" ++ c ++ "(" ++ c ++ "&& rhs) = default;", "",