# HG changeset patch # User jwe # Date 949015848 0 # Node ID 8b1f46ac2b6498999a41384367fc211e3f41cc32 # Parent 1bb6e519a4a2bc9f5e9c6bf90aad234e829b0464 [project @ 2000-01-27 23:30:45 by jwe] diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,23 @@ +2000-01-27 John W. Eaton + + * pt-walk.h (tree_walker::visit_do_while_command): New pure virtual. + (tree_walker::visit_do_until_command): Ditto. + * pt-pr-code.cc (tree_print_code::visit_do_while_command): + New function. + (tree_print_code::visit_do_until_command): Ditto. + * pt-loop.h (tree_do_while_command): New class. + (tree_do_until_command): Ditto. + (tree_while_command::expr, tree_while_command::list): + Now protected instead of private. + * parse.y (make_do_while_command): New function. + (make_do_until_command): Ditto. + (loop_command): Recognize do-while and do-until statements. + (DO, UNTIL): New tokens. + * Makefile.in (parse.cc): Expect 13 shift/reduce conflicts. + + * input.cc (match_sans_spaces): Require non-blank part of test + string to match standard string exactly. + 2000-01-26 John W. Eaton * oct-stream.h (scanf_format_elt::char_class): New struct elt. diff --git a/src/Makefile.in b/src/Makefile.in --- a/src/Makefile.in +++ b/src/Makefile.in @@ -437,7 +437,7 @@ # Special rules -- these files need special things to be defined. parse.cc : parse.y - @echo "expect 11 shift/reduce conflicts" + @echo "expect 13 shift/reduce conflicts" $(YACC) $(YFLAGS) $< @$(top_srcdir)/move-if-change y.tab.c $(@F) diff --git a/src/input.cc b/src/input.cc --- a/src/input.cc +++ b/src/input.cc @@ -483,7 +483,7 @@ size_t len = end == NPOS ? NPOS : end - beg + 1; - return test.compare (standard, beg, len) == 0; + return (test.substr (beg, len) == standard); } return false; diff --git a/src/lex.l b/src/lex.l --- a/src/lex.l +++ b/src/lex.l @@ -1020,6 +1020,7 @@ case otherwise_kw: case return_kw: case static_kw: + case until_kw: case unwind_protect_cleanup_kw: break; @@ -1055,6 +1056,7 @@ yylval.tok_val = new token (token::while_end, l, c); break; + case do_kw: case for_kw: case while_kw: promptflag--; diff --git a/src/octave.gperf b/src/octave.gperf --- a/src/octave.gperf +++ b/src/octave.gperf @@ -7,6 +7,7 @@ case_kw, catch_kw, continue_kw, + do_kw, else_kw, elseif_kw, end_kw, @@ -31,6 +32,7 @@ static_kw, switch_kw, try_kw, + until_kw, unwind_protect_kw, unwind_protect_cleanup_kw, while_kw @@ -44,6 +46,7 @@ case, CASE, case_kw catch, CATCH, catch_kw continue, CONTINUE, continue_kw +do, DO, do_kw else, ELSE, else_kw elseif, ELSEIF, elseif_kw end, END, end_kw @@ -66,6 +69,7 @@ static, STATIC, static_kw switch, SWITCH, switch_kw try, TRY, try_kw +until, UNTIL, until_kw unwind_protect, UNWIND, unwind_protect_kw unwind_protect_cleanup, CLEANUP, unwind_protect_cleanup_kw while, WHILE, while_kw diff --git a/src/parse.y b/src/parse.y --- a/src/parse.y +++ b/src/parse.y @@ -186,6 +186,16 @@ make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok); +// Build a do-while command. +static tree_command * +make_do_while_command (token *do_tok, tree_statement_list *body, + tree_expression *expr); + +// Build a do-until command. +static tree_command * +make_do_until_command (token *do_tok, tree_statement_list *body, + tree_expression *expr); + // Build a for command. static tree_command * make_for_command (token *for_tok, tree_argument_list *lhs, @@ -351,7 +361,7 @@ %token END %token PLOT %token TEXT STYLE AXES_TAG -%token FOR WHILE +%token FOR WHILE DO UNTIL %token IF ELSEIF ELSE %token SWITCH CASE OTHERWISE %token BREAK CONTINUE FUNC_RET @@ -949,6 +959,16 @@ if (! ($$ = make_while_command ($1, $2, $4, $5))) ABORT_PARSE; } + | DO opt_sep opt_list WHILE expression + { + if (! ($$ = make_do_while_command ($1, $3, $5))) + ABORT_PARSE; + } + | DO opt_sep opt_list UNTIL expression + { + if (! ($$ = make_do_until_command ($1, $3, $5))) + ABORT_PARSE; + } | FOR assign_lhs '=' expression opt_sep opt_list END { if (! ($$ = make_for_command ($1, $2, $4, $6, $7))) @@ -2072,6 +2092,48 @@ return retval; } +// Build a do-while command. + +static tree_command * +make_do_while_command (token *do_tok, tree_statement_list *body, + tree_expression *expr) +{ + tree_command *retval = 0; + + maybe_warn_assign_as_truth_value (expr); + + // We have to do this because while can also be used to begin a loop. + lexer_flags.looping -= 2; + promptflag++; + + int l = do_tok->line (); + int c = do_tok->column (); + + retval = new tree_do_while_command (expr, body, l, c); + + return retval; +} + +// Build a do-until command. + +static tree_command * +make_do_until_command (token *do_tok, tree_statement_list *body, + tree_expression *expr) +{ + tree_command *retval = 0; + + maybe_warn_assign_as_truth_value (expr); + + lexer_flags.looping--; + + int l = do_tok->line (); + int c = do_tok->column (); + + retval = new tree_do_until_command (expr, body, l, c); + + return retval; +} + // Build a for command. static tree_command * diff --git a/src/pt-loop.cc b/src/pt-loop.cc --- a/src/pt-loop.cc +++ b/src/pt-loop.cc @@ -115,6 +115,92 @@ tw.visit_while_command (*this); } +// Do-While + +void +tree_do_while_command::eval (void) +{ + if (error_state) + return; + + if (! expr) + panic_impossible (); + + for (;;) + { + if (list) + { + list->eval (); + + if (error_state) + { + eval_error (); + return; + } + } + + if (quit_loop_now () || ! expr->is_logically_true ("do-while")) + break; + } +} + +void +tree_do_while_command::eval_error (void) +{ + if (error_state > 0) + ::error ("evaluating do-while command near line %d, column %d", + line (), column ()); +} + +void +tree_do_while_command::accept (tree_walker& tw) +{ + tw.visit_do_while_command (*this); +} + +// Do-Until + +void +tree_do_until_command::eval (void) +{ + if (error_state) + return; + + if (! expr) + panic_impossible (); + + for (;;) + { + if (list) + { + list->eval (); + + if (error_state) + { + eval_error (); + return; + } + } + + if (quit_loop_now () || expr->is_logically_true ("do-until")) + break; + } +} + +void +tree_do_until_command::eval_error (void) +{ + if (error_state > 0) + ::error ("evaluating do-until command near line %d, column %d", + line (), column ()); +} + +void +tree_do_until_command::accept (tree_walker& tw) +{ + tw.visit_do_until_command (*this); +} + // For. tree_simple_for_command::~tree_simple_for_command (void) diff --git a/src/pt-loop.h b/src/pt-loop.h --- a/src/pt-loop.h +++ b/src/pt-loop.h @@ -67,7 +67,7 @@ void accept (tree_walker& tw); -private: +protected: // Expression to test. tree_expression *expr; @@ -75,6 +75,8 @@ // List of commands to execute. tree_statement_list *list; +private: + // No copying! tree_while_command (const tree_while_command&); @@ -82,6 +84,74 @@ tree_while_command& operator = (const tree_while_command&); }; +// Do-While. + +class +tree_do_while_command : public tree_while_command +{ +public: + + tree_do_while_command (int l = -1, int c = -1) + : tree_while_command (l, c) { } + + tree_do_while_command (tree_expression *e, int l = -1, int c = -1) + : tree_while_command (e, l, c) { } + + tree_do_while_command (tree_expression *e, tree_statement_list *lst, + int l = -1, int c = -1) + : tree_while_command (e, lst, l, c) { } + + ~tree_do_while_command (void) { } + + void eval (void); + + void eval_error (void); + + void accept (tree_walker& tw); + +private: + + // No copying! + + tree_do_while_command (const tree_do_while_command&); + + tree_do_while_command& operator = (const tree_do_while_command&); +}; + +// Do-Until. + +class +tree_do_until_command : public tree_while_command +{ +public: + + tree_do_until_command (int l = -1, int c = -1) + : tree_while_command (l, c) { } + + tree_do_until_command (tree_expression *e, int l = -1, int c = -1) + : tree_while_command (e, l, c) { } + + tree_do_until_command (tree_expression *e, tree_statement_list *lst, + int l = -1, int c = -1) + : tree_while_command (e, lst, l, c) { } + + ~tree_do_until_command (void) { } + + void eval (void); + + void eval_error (void); + + void accept (tree_walker& tw); + +private: + + // No copying! + + tree_do_until_command (const tree_do_until_command&); + + tree_do_until_command& operator = (const tree_do_until_command&); +}; + // For. class diff --git a/src/pt-pr-code.cc b/src/pt-pr-code.cc --- a/src/pt-pr-code.cc +++ b/src/pt-pr-code.cc @@ -1101,6 +1101,66 @@ os << "endwhile"; } +void +tree_print_code::visit_do_while_command (tree_do_while_command& cmd) +{ + indent (); + + os << "do"; + + newline (); + + tree_statement_list *list = cmd.body (); + + if (list) + { + increment_indent_level (); + list->accept (*this); + decrement_indent_level (); + } + + indent (); + + os << "while"; + + tree_expression *expr = cmd.condition (); + + if (expr) + expr->accept (*this); + + newline (); +} + +void +tree_print_code::visit_do_until_command (tree_do_until_command& cmd) +{ + indent (); + + os << "do"; + + newline (); + + tree_statement_list *list = cmd.body (); + + if (list) + { + increment_indent_level (); + list->accept (*this); + decrement_indent_level (); + } + + indent (); + + os << "until"; + + tree_expression *expr = cmd.condition (); + + if (expr) + expr->accept (*this); + + newline (); +} + // Current indentation. int tree_print_code::curr_print_indent_level = 0; diff --git a/src/pt-pr-code.h b/src/pt-pr-code.h --- a/src/pt-pr-code.h +++ b/src/pt-pr-code.h @@ -138,6 +138,10 @@ void visit_while_command (tree_while_command&); + void visit_do_while_command (tree_do_while_command&); + + void visit_do_until_command (tree_do_until_command&); + private: ostream& os; diff --git a/src/pt-walk.h b/src/pt-walk.h --- a/src/pt-walk.h +++ b/src/pt-walk.h @@ -67,6 +67,8 @@ class tree_try_catch_command; class tree_unwind_protect_command; class tree_while_command; +class tree_do_until_command; +class tree_do_while_command; class tree_walker @@ -205,6 +207,12 @@ virtual void visit_while_command (tree_while_command&) = 0; + virtual void + visit_do_while_command (tree_do_while_command&) = 0; + + virtual void + visit_do_until_command (tree_do_until_command&) = 0; + protected: tree_walker (void) { }