# HG changeset patch # User John W. Eaton # Date 1452798032 18000 # Node ID f25c14056b7c30dba66300cbce47f471252a59da # Parent fd97ed44f2da32f5c89d0888e759088239393cbe overhaul parser error handling for end token mismatch * parse.h, oct-parse.in.yy (end_token_as_string): New static function. (octave_base_parser::end_error): Delete. (octave_base_parser::end_token_error): New function. (octave_base_parser::end_token_ok): Simply check for match. Change all uses to call end_token_error separately if end_token_ok returns false. diff -r fd97ed44f2da -r f25c14056b7c libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Thu Jan 14 09:59:07 2016 -0800 +++ b/libinterp/parse-tree/oct-parse.in.yy Thu Jan 14 14:00:32 2016 -0500 @@ -1541,11 +1541,16 @@ function_end : END { parser.endfunction_found = true; + if (parser.end_token_ok ($1, token::function_end)) $$ = parser.make_end ("endfunction", false, $1->line (), $1->column ()); else - ABORT_PARSE; + { + parser.end_token_error ($1, token::function_end); + + ABORT_PARSE; + } } | END_OF_INPUT { @@ -2084,156 +2089,96 @@ // Error mesages for mismatched end tokens. -void -octave_base_parser::end_error (const char *type, token::end_tok_type ettype, - int l, int c) +static std::string +end_token_as_string (token::end_tok_type ettype) { - static const char *fmt - = "'%s' command matched by '%s' near line %d column %d"; + std::string retval = ""; switch (ettype) { case token::simple_end: - error (fmt, type, "end", l, c); + retval = "end"; break; case token::classdef_end: - error (fmt, type, "endclassdef", l, c); + retval = "endclassdef"; break; case token::enumeration_end: - error (fmt, type, "endenumeration", l, c); + retval = "endenumeration"; break; case token::events_end: - error (fmt, type, "endevents", l, c); + retval = "endevents"; break; case token::for_end: - error (fmt, type, "endfor", l, c); + retval = "endfor"; break; case token::function_end: - error (fmt, type, "endfunction", l, c); + retval = "endfunction"; break; case token::if_end: - error (fmt, type, "endif", l, c); + retval = "endif"; break; case token::methods_end: - error (fmt, type, "endmethods", l, c); + retval = "endmethods"; break; case token::parfor_end: - error (fmt, type, "endparfor", l, c); + retval = "endparfor"; break; case token::properties_end: - error (fmt, type, "endproperties", l, c); + retval = "endproperties"; break; case token::switch_end: - error (fmt, type, "endswitch", l, c); + retval = "endswitch"; break; case token::try_catch_end: - error (fmt, type, "end_try_catch", l, c); + retval = "end_try_catch"; break; case token::unwind_protect_end: - error (fmt, type, "end_unwind_protect", l, c); + retval = "end_unwind_protect"; break; case token::while_end: - error (fmt, type, "endwhile", l, c); + retval = "endwhile"; break; default: panic_impossible (); break; } + + return retval; } +void +octave_base_parser::end_token_error (token *tok, token::end_tok_type expected) +{ + std::string msg = ("'" + end_token_as_string (expected) + + "' command matched by '" + + end_token_as_string (tok->ettype ()) + "'"); + + bison_error (msg, tok->line (), tok->column ()); +} + + // Check to see that end tokens are properly matched. bool octave_base_parser::end_token_ok (token *tok, token::end_tok_type expected) { - bool retval = true; - token::end_tok_type ettype = tok->ettype (); - if (ettype != expected && ettype != token::simple_end) - { - retval = false; - - bison_error ("parse error"); - - int l = tok->line (); - int c = tok->column (); - - switch (expected) - { - case token::classdef_end: - end_error ("classdef", ettype, l, c); - break; - - case token::enumeration_end: - end_error ("enumeration", ettype, l, c); - break; - - case token::events_end: - end_error ("events", ettype, l, c); - break; - - case token::for_end: - end_error ("for", ettype, l, c); - break; - - case token::function_end: - end_error ("function", ettype, l, c); - break; - - case token::if_end: - end_error ("if", ettype, l, c); - break; - - case token::methods_end: - end_error ("methods", ettype, l, c); - break; - - case token::parfor_end: - end_error ("parfor", ettype, l, c); - break; - - case token::properties_end: - end_error ("properties", ettype, l, c); - break; - - case token::switch_end: - end_error ("switch", ettype, l, c); - break; - - case token::try_catch_end: - end_error ("try", ettype, l, c); - break; - - case token::unwind_protect_end: - end_error ("unwind_protect", ettype, l, c); - break; - - case token::while_end: - end_error ("while", ettype, l, c); - break; - - default: - panic_impossible (); - break; - } - } - - return retval; + return ettype == expected || ettype == token::simple_end; } // Maybe print a warning if an assignment expression is used as the @@ -2679,6 +2624,8 @@ { delete body; delete cleanup_stmts; + + end_token_error (end_tok, token::unwind_protect_end); } return retval; @@ -2733,6 +2680,8 @@ { delete body; delete cleanup_stmts; + + end_token_error (end_tok, token::try_catch_end); } return retval; @@ -2766,6 +2715,8 @@ { delete expr; delete body; + + end_token_error (end_tok, token::while_end); } return retval; @@ -2841,6 +2792,8 @@ delete expr; delete maxproc; delete body; + + end_token_error (end_tok, parfor ? token::parfor_end : token::for_end); } return retval; @@ -2923,7 +2876,11 @@ retval = new tree_if_command (list, lc, tc, l, c); } else - delete list; + { + delete list; + + end_token_error (end_tok, token::if_end); + } return retval; } @@ -2979,6 +2936,8 @@ { delete expr; delete list; + + end_token_error (end_tok, token::switch_end); } return retval; @@ -3400,27 +3359,39 @@ nm = lexer.fcn_file_name.substr (pos+1); if (nm != cls_name) - bison_error ("invalid classdef definition, the class name must match the filename"); - else if (end_token_ok (end_tok, token::classdef_end)) - { - octave_comment_list *tc = lexer.comment_buf.get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - if (! body) - body = new tree_classdef_body (); - - retval = new tree_classdef (a, id, sc, body, lc, tc, - curr_package_name, l, c); - } - - if (! retval) { delete a; delete id; delete sc; delete body; + + bison_error ("invalid classdef definition, the class name must match the filename"); + + } + else + { + if (end_token_ok (end_tok, token::classdef_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! body) + body = new tree_classdef_body (); + + retval = new tree_classdef (a, id, sc, body, lc, tc, + curr_package_name, l, c); + } + else + { + delete a; + delete id; + delete sc; + delete body; + + end_token_error (end_tok, token::switch_end); + } } return retval; @@ -3451,6 +3422,8 @@ { delete a; delete plist; + + end_token_error (end_tok, token::properties_end); } return retval; @@ -3481,6 +3454,8 @@ { delete a; delete mlist; + + end_token_error (end_tok, token::methods_end); } return retval; @@ -3511,6 +3486,8 @@ { delete a; delete elist; + + end_token_error (end_tok, token::events_end); } return retval; @@ -3541,6 +3518,8 @@ { delete a; delete elist; + + end_token_error (end_tok, token::enumeration_end); } return retval; diff -r fd97ed44f2da -r f25c14056b7c libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Thu Jan 14 09:59:07 2016 -0800 +++ b/libinterp/parse-tree/parse.h Thu Jan 14 14:00:32 2016 -0500 @@ -152,7 +152,7 @@ void reset (void); // Error mesages for mismatched end tokens. - void end_error (const char *type, token::end_tok_type expected, int l, int c); + void end_token_error (token *tok, token::end_tok_type expected); // Check to see that end tokens are properly matched. bool end_token_ok (token *tok, token::end_tok_type expected);