Hi Denis! > Le 25 mars 2016 à 19:37, Denis T <[email protected]> a écrit : > > Hi, > > I've found out that Bison 3.0.4 parser crashes when you attempt to throw > syntax_error from any mid-rule action of C++ parser, which uses location > tracking. Here's a simple example: > > %code provides { > int yylex(yy::parser::semantic_type* type, const yy::parser::location_type* > loc); > } > > %require "3.0.4" > %language "C++" > %skeleton "lalr1.cc" > %locations > %define api.value.type {int} > > %% > > start: > '1' '2' '3' { throw syntax_error(@1, "Test"); } '4' '5' '6' { $$ = 0; } > ; > > %% > > void yy::parser::error(const yy::parser::location_type& loc, const > std::string& message) > { > std::cout << message << std::endl; > } > > int yylex(yy::parser::semantic_type* type, const yy::parser::location_type* > loc) > { > static int start = '0'; > return ++start; > } > > int main() > { > yy::parser().parse(); > } > > > The crash occurs in yyerrorlab, when trying to do something with locations, > in the following autogenerated line: > yyerror_range[1].location = yystack_[yylen - 1].location; // <- crash, as > yylen = 0 here
Good catch. For the record, Bison 3.0.5 has a fix for this. I’m ashamed to report that 3.0.5 was released recently (May 27th 2018), but the fix was sitting in git long before. commit 476c1cca5945eeef3493cfc6ef06ed6d0972d787 Author: Akim Demaille <[email protected]> Date: Tue Aug 11 13:48:57 2015 +0200 lalr1, yacc: use the default location as initial error location Currently lalr1.cc makes an out-of-bound access when trying to read @1 in rules with an empty rhs (i.e., when there is no @1) that raises an error (YYERROR). glr.c already gracefully handles this by using @$ as initial location for the errors. Let's do that in yacc.c and lalr1.cc. * data/lalr1.cc, data/yacc.c: Use @$ to initialize the error location. * tests/actions.at: Check that case. > Fortunately, there's an easy workaround for this bug: it's possible to move > mid-rule action to another rule, and the issue doesn't reproduce anymore: > start: > one_two_three '4' '5' '6' { $$ = 0; } > ; > > one_two_three: > '1' '2' '3' { throw syntax_error(@1, "Test"); } > ; > > > And a small another bug: it's currently not possible to use syntax_error > class from outside grammar file, as it has inline constructor defined > (c++.m4), which makes this class non-constructible from other cpp files, at > least in Visual Studio 2015. Removing « inline" keyword solves this issue. That was also addressed in 3.0.5. Thanks a lot!
