Mercurial > octave
changeset 21073:f7cc48f601d2
additional reworking of error handling in the parser (bug #46877)
* oct-parse.in.yy (ABORT_PARSE): Delete. Replace all uses with
YYABORT. Ensure that all uses of octave_base_parser::bison_error are
followed by YYABORT.
(octave_base_parser::make_for_command): Always delete unused parse
tree elements if an error is detected.
octave_base_parser::make_index_expression): Likewise.
(octave_base_parser::parse_error_msg): New data member.
(octave_base_parser::bison_error): Store error message for later use
instead of calling parse_error.
(octave_parser::run, octave_push_parser::run): Check return status of
Bison-generated parser and call parse_error here with stored message.
Handle exceptions generated while parsing.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 14 Jan 2016 16:40:12 -0500 |
parents | a9ed4104ecfd |
children | 9ff2ae6cd5b0 |
files | libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h |
diffstat | 2 files changed, 151 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.in.yy Thu Jan 14 13:30:22 2016 -0800 +++ b/libinterp/parse-tree/oct-parse.in.yy Thu Jan 14 16:40:12 2016 -0500 @@ -108,17 +108,6 @@ static void yyerror (octave_base_parser& parser, const char *s); -#define ABORT_PARSE \ - do \ - { \ - yyerrok; \ - if (interactive && ! lexer.input_from_eval_string ()) \ - YYACCEPT; \ - else \ - YYABORT; \ - } \ - while (0) - #define lexer parser.lexer #define scanner lexer.scanner @@ -422,7 +411,7 @@ | parse_error { $$ = 0; - ABORT_PARSE; + YYABORT; } ; @@ -480,7 +469,7 @@ if (! $$) { // make_index_expression deleted $1 and $2. - ABORT_PARSE; + YYABORT; } } ; @@ -689,7 +678,7 @@ if (! $$) { // make_index_expression deleted $1. - ABORT_PARSE; + YYABORT; } } | oper_expr '(' arg_list ')' @@ -698,7 +687,7 @@ if (! $$) { // make_index_expression deleted $1 and $3. - ABORT_PARSE; + YYABORT; } } | oper_expr '{' '}' @@ -707,7 +696,7 @@ if (! $$) { // make_index_expression deleted $1. - ABORT_PARSE; + YYABORT; } } | oper_expr '{' arg_list '}' @@ -716,7 +705,7 @@ if (! $$) { // make_index_expression deleted $1 and $3. - ABORT_PARSE; + YYABORT; } } | oper_expr HERMITIAN @@ -775,7 +764,7 @@ if (! $$) { // make_index_expression deleted $1. - ABORT_PARSE; + YYABORT; } } | power_expr '(' arg_list ')' @@ -784,7 +773,7 @@ if (! $$) { // make_index_expression deleted $1 and $3. - ABORT_PARSE; + YYABORT; } } | power_expr '{' '}' @@ -793,7 +782,7 @@ if (! $$) { // make_index_expression deleted $1. - ABORT_PARSE; + YYABORT; } } | power_expr '{' arg_list '}' @@ -802,7 +791,7 @@ if (! $$) { // make_index_expression deleted $1 and $3. - ABORT_PARSE; + YYABORT; } } | power_expr indirect_ref_op STRUCT_ELT @@ -835,7 +824,7 @@ { delete $1; delete $3; - ABORT_PARSE; + YYABORT; } } ; @@ -877,7 +866,7 @@ else { // validate_matrix_for_assignment deleted $1. - ABORT_PARSE; + YYABORT; } } ; @@ -923,14 +912,19 @@ else { delete $1; - ABORT_PARSE; + YYABORT; } } else $$ = $1; } | assign_expr - { $$ = $1; } + { + if (! $1) + YYABORT; + + $$ = $1; + } | anon_fcn_handle { $$ = $1; } ; @@ -1016,7 +1010,7 @@ if (! ($$ = parser.finish_if_command ($1, $3, $4, $2))) { // finish_if_command deleted $3. - ABORT_PARSE; + YYABORT; } } ; @@ -1076,7 +1070,7 @@ if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2))) { // finish_switch_command deleted $3 adn $5. - ABORT_PARSE; + YYABORT; } } ; @@ -1134,7 +1128,7 @@ if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2))) { // make_while_command deleted $3 and $6. - ABORT_PARSE; + YYABORT; } } | DO stash_comment opt_sep opt_list UNTIL expression @@ -1153,7 +1147,7 @@ $8, $9, $2))) { // make_for_command deleted $3, $5, and $8. - ABORT_PARSE; + YYABORT; } } | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END @@ -1165,7 +1159,7 @@ $9, $10, $2))) { // make_for_command deleted $4, $6, and $9. - ABORT_PARSE; + YYABORT; } } | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END @@ -1177,7 +1171,7 @@ 0, $8, $9, $2))) { // make_for_command deleted $3, $5, and $8. - ABORT_PARSE; + YYABORT; } } | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END @@ -1189,7 +1183,7 @@ $8, $11, $12, $2))) { // make_for_command deleted $4, $6, $8, and $11. - ABORT_PARSE; + YYABORT; } } ; @@ -1220,7 +1214,7 @@ if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6))) { // make_unwind_command deleted $4 and $8. - ABORT_PARSE; + YYABORT; } } | TRY stash_comment opt_sep opt_list CATCH stash_comment @@ -1233,7 +1227,7 @@ if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6))) { // make_try_command deleted $4 and $8. - ABORT_PARSE; + YYABORT; } } | TRY stash_comment opt_sep opt_list END @@ -1243,7 +1237,7 @@ if (! ($$ = parser.make_try_command ($1, $4, 0, 0, $5, $2, 0))) { // make_try_command deleted $4. - ABORT_PARSE; + YYABORT; } } ; @@ -1274,7 +1268,10 @@ if (lexer.reading_script_file && parser.curr_fcn_depth > 1) - parser.bison_error ("nested functions not implemented in this context"); + { + parser.bison_error ("nested functions not implemented in this context"); + YYABORT; + } } ; @@ -1313,9 +1310,9 @@ } | param_list_beg error { + $$ = 0; parser.bison_error ("invalid parameter list"); - $$ = 0; - ABORT_PARSE; + YYABORT; } ; @@ -1332,7 +1329,7 @@ else { delete $1; - ABORT_PARSE; + YYABORT; } } ; @@ -1377,7 +1374,7 @@ else { delete tmp; - ABORT_PARSE; + YYABORT; } } | '[' return_list1 ']' @@ -1392,7 +1389,7 @@ else { delete $2; - ABORT_PARSE; + YYABORT; } } ; @@ -1548,8 +1545,7 @@ else { parser.end_token_error ($1, token::function_end); - - ABORT_PARSE; + YYABORT; } } | END_OF_INPUT @@ -1615,7 +1611,7 @@ if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2))) { // make_classdef deleted $3, $4, $5, and $7. - ABORT_PARSE; + YYABORT; } } | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END @@ -1627,7 +1623,7 @@ if (! ($$ = parser.make_classdef ($1, $3, $4, $5, 0, $7, $2))) { // make_classdef deleted $3, $4, and $5. - ABORT_PARSE; + YYABORT; } } ; @@ -1744,7 +1740,7 @@ ($1, $3, $5, $7, $2))) { // make_classdef_properties_block delete $3 and $5. - ABORT_PARSE; + YYABORT; } } | PROPERTIES stash_comment opt_attr_list opt_sep END @@ -1755,7 +1751,7 @@ ($1, $3, 0, $5, $2))) { // make_classdef_properties_block delete $3. - ABORT_PARSE; + YYABORT; } } ; @@ -1792,7 +1788,7 @@ ($1, $3, $5, $7, $2))) { // make_classdef_methods_block deleted $3 and $5. - ABORT_PARSE; + YYABORT; } } | METHODS stash_comment opt_attr_list opt_sep END @@ -1803,7 +1799,7 @@ ($1, $3, 0, $5, $2))) { // make_classdef_methods_block deleted $3. - ABORT_PARSE; + YYABORT; } } ; @@ -1812,12 +1808,12 @@ method_decl1 : identifier { if (! ($$ = parser.start_classdef_external_method ($1, 0))) - ABORT_PARSE; + YYABORT; } | identifier param_list { if (! ($$ = parser.start_classdef_external_method ($1, $2))) - ABORT_PARSE; + YYABORT; } ; @@ -1875,7 +1871,7 @@ ($1, $3, $5, $7, $2))) { // make_classdef_events_block deleted $3 and $5. - ABORT_PARSE; + YYABORT; } } | EVENTS stash_comment opt_attr_list opt_sep END @@ -1886,7 +1882,7 @@ ($1, $3, 0, $5, $2))) { // make_classdef_events_block deleted $3. - ABORT_PARSE; + YYABORT; } } ; @@ -1915,7 +1911,7 @@ ($1, $3, $5, $7, $2))) { // make_classdef_enum_block deleted $3 and $5. - ABORT_PARSE; + YYABORT; } } | ENUMERATION stash_comment opt_attr_list opt_sep END @@ -1926,7 +1922,7 @@ ($1, $3, 0, $5, $2))) { // make_classdef_enum_block deleted $3. - ABORT_PARSE; + YYABORT; } } ; @@ -2780,7 +2776,14 @@ else { if (parfor) - bison_error ("invalid syntax for parfor statement"); + { + delete lhs; + delete expr; + delete maxproc; + delete body; + + bison_error ("invalid syntax for parfor statement"); + } else retval = new tree_complex_for_command (lhs, expr, body, lc, tc, l, c); @@ -3050,7 +3053,12 @@ else if (t == octave_value::op_asn_eq) return new tree_multi_assignment (lhs, rhs, false, l, c); else - bison_error ("computed multiple assignment not allowed"); + { + delete lhs; + delete rhs; + + bison_error ("computed multiple assignment not allowed"); + } return retval; } @@ -3602,30 +3610,30 @@ if (args && args->has_magic_tilde ()) { - bison_error ("invalid use of empty argument (~) in index expression"); - delete expr; delete args; - return retval; - } - - int l = expr->line (); - int c = expr->column (); - - if (! expr->is_postfix_indexed ()) - expr->set_postfix_index (type); - - if (expr->is_index_expression ()) - { - tree_index_expression *tmp = static_cast<tree_index_expression *> (expr); - - tmp->append (args, type); - - retval = tmp; + bison_error ("invalid use of empty argument (~) in index expression"); } else - retval = new tree_index_expression (expr, args, l, c, type); + { + int l = expr->line (); + int c = expr->column (); + + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index (type); + + if (expr->is_index_expression ()) + { + tree_index_expression *tmp = static_cast<tree_index_expression *> (expr); + + tmp->append (args, type); + + retval = tmp; + } + else + retval = new tree_index_expression (expr, args, l, c, type); + } return retval; } @@ -3742,10 +3750,12 @@ if (row && row->has_magic_tilde ()) { retval = false; + if (e->is_matrix ()) bison_error ("invalid use of tilde (~) in matrix expression"); else bison_error ("invalid use of tilde (~) in cell expression"); + break; } } @@ -3762,12 +3772,12 @@ { octave_value ov = e->rvalue1 (); + delete e; + if (ov.is_empty ()) bison_error ("invalid empty left hand side of assignment"); else bison_error ("invalid constant left hand side of assignment"); - - delete e; } else { @@ -3797,8 +3807,9 @@ } else { + delete tmp; + bison_error ("invalid left hand side of assignment"); - delete tmp; } if (retval && is_simple_assign) @@ -3997,15 +4008,43 @@ output_buf << "\n"; - std::string msg = output_buf.str (); - - parse_error ("%s", msg.c_str ()); + parse_error_msg = output_buf.str (); } int octave_parser::run (void) { - return octave_parse (*this); + int status = -1; + + yypstate *pstate = static_cast<yypstate *> (parser_state); + + try + { + status = octave_pull_parse (pstate, *this); + } + catch (octave_execution_exception& e) + { + std::string file = lexer.fcn_file_full_name; + + if (file.empty ()) + error (e, "parse error"); + else + error (e, "parse error in %s", file.c_str ()); + } + catch (...) + { + std::string file = lexer.fcn_file_full_name; + + if (file.empty ()) + error ("unexpected exception while parsing input"); + else + error ("unexpected exception while parsing %s", file.c_str ()); + } + + if (status != 0) + parse_error ("%s", parse_error_msg.c_str ()); + + return status; } // Parse input from INPUT. Pass TRUE for EOF if the end of INPUT should @@ -4035,10 +4074,34 @@ yypstate *pstate = static_cast<yypstate *> (parser_state); - status = octave_push_parse (pstate, token, &lval, *this); + try + { + status = octave_push_parse (pstate, token, &lval, *this); + } + catch (octave_execution_exception& e) + { + std::string file = lexer.fcn_file_full_name; + + if (file.empty ()) + error (e, "parse error"); + else + error (e, "parse error in %s", file.c_str ()); + } + catch (...) + { + std::string file = lexer.fcn_file_full_name; + + if (file.empty ()) + error ("unexpected exception while parsing input"); + else + error ("unexpected exception while parsing %s", file.c_str ()); + } } while (status == YYPUSH_MORE); + if (status != 0) + parse_error ("%s", parse_error_msg.c_str ()); + return status; }
--- a/libinterp/parse-tree/parse.h Thu Jan 14 13:30:22 2016 -0800 +++ b/libinterp/parse-tree/parse.h Thu Jan 14 16:40:12 2016 -0500 @@ -391,6 +391,10 @@ // Generic error messages. void bison_error (const std::string& s, int l = -1, int c = -1); + // Contains error message if Bison-generated parser returns non-zero + // status. + std::string parse_error_msg; + // Have we found an explicit end to a function? bool endfunction_found;