From 44787b1a2c2a3a0873cb8afac5760ee877191883 Mon Sep 17 00:00:00 2001 From: Dmitriy Okoneshnikov Date: Sat, 1 Feb 2025 16:20:26 +0300 Subject: [PATCH] [ #493 ] C++: fixed broken `parse_error` exception --- source/CHANGELOG.md | 1 + source/src/BNFC/Backend/C/CFtoBisonC.hs | 42 ++++++++++++++++++------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/source/CHANGELOG.md b/source/CHANGELOG.md index 7fa13f6d..d4d65cca 100644 --- a/source/CHANGELOG.md +++ b/source/CHANGELOG.md @@ -2,6 +2,7 @@ * C: preserve case in constructors (union): e.g. label `EInt` now is union member `eInt_` rather than `eint_` [[#479](https://github.com/BNFC/bnfc/issues/479)] +* C++: repair broken `parse_error` exception throw [[#493](https://github.com/BNFC/bnfc/issues/493)] # 2.9.5 diff --git a/source/src/BNFC/Backend/C/CFtoBisonC.hs b/source/src/BNFC/Backend/C/CFtoBisonC.hs index 3e6d0fb8..158b15ea 100644 --- a/source/src/BNFC/Backend/C/CFtoBisonC.hs +++ b/source/src/BNFC/Backend/C/CFtoBisonC.hs @@ -118,6 +118,7 @@ header mode cf = unlines $ concat -- Fixing regression introduced in 2.9.2. , when (stlParser mode) [ "#include /* for std::reverse */" -- mandatory e.g. with GNU C++ 11 + , "#include \"" ++ ("ParserError" <.> h) ++ "\"" -- for throwing parser_error in C++ ] , [ "#include " , "#include " @@ -160,23 +161,42 @@ header mode cf = unlines $ concat unionDependentCode :: ParserMode -> String unionDependentCode mode = unlines [ "%{" - , errorHandler name + , errorHandler mode , "int yyparse(yyscan_t scanner, YYSTYPE *result);" , "" , "extern int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, yyscan_t scanner);" , "%}" ] - where - name = parserName mode -errorHandler :: String -> String -errorHandler name = unlines - [ "void yyerror(YYLTYPE *loc, yyscan_t scanner, YYSTYPE *result, const char *msg)" - , "{" - , " fprintf(stderr, \"error: %d,%d: %s at %s\\n\"," - , " loc->first_line, loc->first_column, msg, " ++ name ++ "get_text(scanner));" - , "}" - ] +errorHandler :: ParserMode -> String +errorHandler mode = case mode of + CParser _ _ -> + -- This generates error handler for C with fprintf + unlines + [ "void yyerror(YYLTYPE *loc, yyscan_t scanner, YYSTYPE *result, const char *msg)" + , "{" + , " fprintf(stderr, \"error: %d,%d: %s at %s\\n\"," + , " loc->first_line, loc->first_column, msg, " ++ name ++ "get_text(scanner));" + , "}" + ] + CppParser _ _ -> + -- This generates error handler for C++ with throw parse_error + unlines + [ "void yyerror(YYLTYPE *loc, yyscan_t scanner, YYSTYPE *result, const char *msg)" + , "{" + , " std::string error_msg = msg;" + , " if (loc) {" + , " error_msg += \" at line \" + std::to_string(loc->first_line) +" + , " \", column \" + std::to_string(loc->first_column);" + , " }" + , " if (scanner) {" + , " error_msg += \": '\" + std::string(" ++ name ++ "get_text(scanner)) + \"'\";" + , " }" + , " throw " ++ name ++ "::parse_error(loc ? loc->first_line : -1, error_msg);" + , "}" + ] + where + name = parserName mode -- | Parser entry point code. --