1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2021 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING.  If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26// Parser for Octave.
27
28// C decarations.
29
30%{
31
32#define YYDEBUG 1
33
34#if defined (HAVE_CONFIG_H)
35#  include "config.h"
36#endif
37
38#include <cassert>
39#include <cstdio>
40#include <cstdlib>
41
42#include <iostream>
43#include <map>
44#include <sstream>
45
46#include "Matrix.h"
47#include "cmd-edit.h"
48#include "cmd-hist.h"
49#include "file-ops.h"
50#include "file-stat.h"
51#include "oct-env.h"
52#include "oct-time.h"
53#include "quit.h"
54
55#include "Cell.h"
56#include "anon-fcn-validator.h"
57#include "builtin-defun-decls.h"
58#include "defun.h"
59#include "dynamic-ld.h"
60#include "error.h"
61#include "input.h"
62#include "interpreter-private.h"
63#include "interpreter.h"
64#include "lex.h"
65#include "load-path.h"
66#include "lo-sysdep.h"
67#include "oct-hist.h"
68#include "oct-map.h"
69#include "ov-classdef.h"
70#include "ov-fcn-handle.h"
71#include "ov-usr-fcn.h"
72#include "ov-null-mat.h"
73#include "pager.h"
74#include "parse.h"
75#include "pt-all.h"
76#include "pt-eval.h"
77#include "symtab.h"
78#include "token.h"
79#include "unwind-prot.h"
80#include "utils.h"
81#include "variables.h"
82
83// oct-parse.h must be included after pt-all.h
84#include "oct-parse.h"
85
86extern int octave_lex (YYSTYPE *, void *);
87
88// Forward declarations for some functions defined at the bottom of
89// the file.
90
91static void yyerror (octave::base_parser& parser, const char *s);
92
93#define lexer (parser.get_lexer ())
94#define scanner lexer.m_scanner
95
96// Previous versions of Octave used Bison's YYUSE macro to avoid
97// warnings about unused values in rules.  But that Bison macro was
98// apparently never intended to be public.  So define our own.  All we
99// need to do is mention the symantic value somewhere in the rule.  It
100// doesn't actually need to be used to avoid the Bison warning, so just
101// define this macro to discard its parameter.
102#define OCTAVE_YYUSE(X)
103
104#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
105   // Disable this warning for code that is generated by Bison,
106   // including grammar rules.  Push the current state so we can
107   // restore the warning state prior to functions we define at
108   // the bottom of the file.
109#  pragma GCC diagnostic push
110#  pragma GCC diagnostic ignored "-Wold-style-cast"
111#endif
112
113%}
114
115// Bison declarations.
116
117// The grammar currently has 9 shift/reduce conflicts.  Ensure that
118// we notice if that number changes.
119
120%expect 9
121
122// We are using the pure parser interface and the reentrant lexer
123// interface but the Octave parser and lexer are NOT properly
124// reentrant because both still use many global variables.  It should be
125// safe to create a parser object and call it while another parser
126// object is active (to parse a callback function while the main
127// interactive parser is waiting for input, for example) if you take
128// care to properly save and restore (typically with an unwind_protect
129// object) relevant global values before and after the nested call.
130
131%define api.pure
132// No spaces inside the braces for the prefix and push-pull definitions!
133%define api.prefix {octave_}
134%define api.push-pull both
135%parse-param { octave::base_parser& parser }
136%lex-param { void *lexer.scanner }
137
138%union
139{
140  int dummy_type;
141
142  // The type of the basic tokens returned by the lexer.
143  octave::token *tok_val;
144
145  // Comment strings that we need to deal with mid-rule.
146  octave::comment_list *comment_type;
147
148  // Types for the nonterminals we generate.
149  char punct_type;
150  octave::tree *tree_type;
151  octave::tree_matrix *tree_matrix_type;
152  octave::tree_cell *tree_cell_type;
153  octave::tree_expression *tree_expression_type;
154  octave::tree_constant *tree_constant_type;
155  octave::tree_fcn_handle *tree_fcn_handle_type;
156  octave::tree_superclass_ref *tree_superclass_ref_type;
157  octave::tree_metaclass_query *tree_metaclass_query_type;
158  octave::tree_function_def *tree_function_def_type;
159  octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;
160  octave::tree_identifier *tree_identifier_type;
161  octave::tree_index_expression *tree_index_expression_type;
162  octave::tree_colon_expression *tree_colon_expression_type;
163  octave::tree_argument_list *tree_argument_list_type;
164  octave::tree_parameter_list *tree_parameter_list_type;
165  octave::tree_command *tree_command_type;
166  octave::tree_if_command *tree_if_command_type;
167  octave::tree_if_clause *tree_if_clause_type;
168  octave::tree_if_command_list *tree_if_command_list_type;
169  octave::tree_switch_command *tree_switch_command_type;
170  octave::tree_switch_case *tree_switch_case_type;
171  octave::tree_switch_case_list *tree_switch_case_list_type;
172  octave::tree_decl_elt *tree_decl_elt_type;
173  octave::tree_decl_init_list *tree_decl_init_list_type;
174  octave::tree_decl_command *tree_decl_command_type;
175  octave::tree_statement *tree_statement_type;
176  octave::tree_statement_list *tree_statement_list_type;
177  octave_user_function *octave_user_function_type;
178
179  octave::tree_classdef *tree_classdef_type;
180  octave::tree_classdef_attribute* tree_classdef_attribute_type;
181  octave::tree_classdef_attribute_list* tree_classdef_attribute_list_type;
182  octave::tree_classdef_superclass* tree_classdef_superclass_type;
183  octave::tree_classdef_superclass_list* tree_classdef_superclass_list_type;
184  octave::tree_classdef_body* tree_classdef_body_type;
185  octave::tree_classdef_property* tree_classdef_property_type;
186  octave::tree_classdef_property_list* tree_classdef_property_list_type;
187  octave::tree_classdef_properties_block* tree_classdef_properties_block_type;
188  octave::tree_classdef_methods_list* tree_classdef_methods_list_type;
189  octave::tree_classdef_methods_block* tree_classdef_methods_block_type;
190  octave::tree_classdef_event* tree_classdef_event_type;
191  octave::tree_classdef_events_list* tree_classdef_events_list_type;
192  octave::tree_classdef_events_block* tree_classdef_events_block_type;
193  octave::tree_classdef_enum* tree_classdef_enum_type;
194  octave::tree_classdef_enum_list* tree_classdef_enum_list_type;
195  octave::tree_classdef_enum_block* tree_classdef_enum_block_type;
196}
197
198// Tokens with line and column information.
199%token <tok_val> '=' ':' '-' '+' '*' '/'
200%token <tok_val> '(' ')' '[' ']' '{' '}' '.' '@'
201%token <tok_val> ',' ';' '\n'
202%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
203%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
204%token <tok_val> EXPR_AND_AND EXPR_OR_OR
205%token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
206%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
207%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
208%token <tok_val> HERMITIAN TRANSPOSE
209%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
210%token <tok_val> NUM IMAG_NUM
211%token <tok_val> STRUCT_ELT
212%token <tok_val> NAME
213%token <tok_val> END
214%token <tok_val> DQ_STRING SQ_STRING
215%token <tok_val> FOR PARFOR WHILE DO UNTIL
216%token <tok_val> IF ELSEIF ELSE
217%token <tok_val> SWITCH CASE OTHERWISE
218%token <tok_val> BREAK CONTINUE FUNC_RET
219%token <tok_val> UNWIND CLEANUP
220%token <tok_val> TRY CATCH
221%token <tok_val> GLOBAL PERSISTENT
222%token <tok_val> FCN_HANDLE
223%token <tok_val> CLASSDEF
224%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
225%token <tok_val> METAQUERY
226%token <tok_val> SUPERCLASSREF
227%token <tok_val> FQ_IDENT
228%token <tok_val> GET SET
229%token <tok_val> FCN
230%token <tok_val> LEXICAL_ERROR
231%token <tok_val> END_OF_INPUT
232
233// Other tokens.
234%token <dummy_type> INPUT_FILE
235// %token VARARGIN VARARGOUT
236
237// Nonterminals we construct.
238%type <dummy_type> indirect_ref_op decl_param_init
239%type <dummy_type> push_fcn_symtab push_script_symtab begin_file
240%type <dummy_type> param_list_beg param_list_end stmt_begin anon_fcn_begin
241%type <dummy_type> parsing_local_fcns parse_error
242%type <comment_type> stash_comment
243%type <tok_val> function_beg classdef_beg
244%type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
245%type <tree_type> input
246%type <tree_constant_type> string constant magic_colon
247%type <tree_anon_fcn_handle_type> anon_fcn_handle
248%type <tree_fcn_handle_type> fcn_handle
249%type <tree_matrix_type> matrix_rows
250%type <tree_cell_type> cell_rows
251%type <tree_expression_type> matrix cell
252%type <tree_expression_type> primary_expr oper_expr power_expr
253%type <tree_expression_type> simple_expr colon_expr assign_expr expression
254%type <tree_identifier_type> identifier fcn_name magic_tilde
255%type <tree_superclass_ref_type> superclass_identifier
256%type <tree_metaclass_query_type> meta_identifier
257%type <tree_index_expression_type> word_list_cmd
258%type <tree_argument_list_type> arg_list word_list assign_lhs
259%type <tree_argument_list_type> cell_or_matrix_row
260%type <tree_parameter_list_type> opt_param_list param_list
261%type <tree_parameter_list_type> param_list1 param_list2
262%type <tree_parameter_list_type> return_list return_list1
263%type <tree_command_type> command select_command loop_command
264%type <tree_command_type> jump_command except_command
265%type <tree_function_def_type> function
266%type <tree_classdef_type> classdef
267%type <tree_command_type> file
268%type <tree_if_command_type> if_command
269%type <tree_if_clause_type> elseif_clause else_clause
270%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
271%type <tree_switch_command_type> switch_command
272%type <tree_switch_case_type> switch_case default_case
273%type <tree_switch_case_list_type> case_list1 case_list
274%type <tree_decl_elt_type> decl2 param_list_elt
275%type <tree_decl_init_list_type> decl1
276%type <tree_decl_command_type> declaration
277%type <tree_statement_type> statement function_end
278%type <tree_statement_list_type> simple_list simple_list1 list list1
279%type <tree_statement_list_type> opt_list
280%type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1
281%type <tree_classdef_attribute_type> attr
282%type <tree_classdef_attribute_list_type> attr_list attr_list1
283%type <tree_classdef_superclass_type> superclass
284%type <tree_classdef_superclass_list_type> superclass_list superclass_list1
285%type <tree_classdef_body_type> class_body class_body1
286%type <tree_classdef_property_type> class_property
287%type <tree_classdef_property_list_type> property_list property_list1
288%type <tree_classdef_properties_block_type> properties_block
289%type <tree_classdef_methods_list_type> methods_list methods_list1
290%type <tree_classdef_methods_block_type> methods_block
291%type <tree_classdef_event_type> class_event
292%type <tree_classdef_events_list_type> events_list events_list1
293%type <tree_classdef_events_block_type> events_block
294%type <tree_classdef_enum_type> class_enum
295%type <tree_classdef_enum_list_type> enum_list enum_list1
296%type <tree_classdef_enum_block_type> enum_block
297%type <tree_function_def_type> method_decl method
298%type <octave_user_function_type> method_decl1
299
300// Precedence and associativity.
301%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ
302%left EXPR_OR_OR
303%left EXPR_AND_AND
304%left EXPR_OR
305%left EXPR_AND
306%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
307%left ':'
308%left '-' '+' EPLUS EMINUS
309%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
310%right UNARY EXPR_NOT
311%left POW EPOW HERMITIAN TRANSPOSE
312%right PLUS_PLUS MINUS_MINUS
313%left '(' '.' '{'
314
315// How to clean up if there is a parse error.  We handle deleting tokens
316// and comments separately and separators are just characters.  The
317// remaining items are dynamically allocated parse tree objects that
318// must be deleted.  Use the wildcard case (<*>) to detect unhandled
319// cases (for example, a new semantic type is added but not handled
320// here).
321
322%destructor { } <tok_val>
323%destructor { } <punct_type>
324%destructor { } <comment_type>
325%destructor { } <>
326
327%destructor { delete $$; } <tree_type>
328%destructor { delete $$; } <tree_matrix_type>
329%destructor { delete $$; } <tree_cell_type>
330%destructor { delete $$; } <tree_expression_type>
331%destructor { delete $$; } <tree_constant_type>
332%destructor { delete $$; } <tree_fcn_handle_type>
333%destructor { delete $$; } <tree_superclass_ref_type>
334%destructor { delete $$; } <tree_metaclass_query_type>
335%destructor { delete $$; } <tree_function_def_type>
336%destructor { delete $$; } <tree_anon_fcn_handle_type>
337%destructor { delete $$; } <tree_identifier_type>
338%destructor { delete $$; } <tree_index_expression_type>
339%destructor { delete $$; } <tree_argument_list_type>
340%destructor { delete $$; } <tree_parameter_list_type>
341%destructor { delete $$; } <tree_command_type>
342%destructor { delete $$; } <tree_if_command_type>
343%destructor { delete $$; } <tree_if_clause_type>
344%destructor { delete $$; } <tree_if_command_list_type>
345%destructor { delete $$; } <tree_switch_command_type>
346%destructor { delete $$; } <tree_switch_case_type>
347%destructor { delete $$; } <tree_switch_case_list_type>
348%destructor { delete $$; } <tree_decl_elt_type>
349%destructor { delete $$; } <tree_decl_init_list_type>
350%destructor { delete $$; } <tree_decl_command_type>
351%destructor { delete $$; } <tree_statement_type>
352%destructor { delete $$; } <tree_statement_list_type>
353%destructor { delete $$; } <octave_user_function_type>
354
355%destructor { delete $$; } <tree_classdef_type>
356%destructor { delete $$; } <tree_classdef_attribute_type>
357%destructor { delete $$; } <tree_classdef_attribute_list_type>
358%destructor { delete $$; } <tree_classdef_superclass_type>
359%destructor { delete $$; } <tree_classdef_superclass_list_type>
360%destructor { delete $$; } <tree_classdef_body_type>
361%destructor { delete $$; } <tree_classdef_property_type>
362%destructor { delete $$; } <tree_classdef_property_list_type>
363%destructor { delete $$; } <tree_classdef_properties_block_type>
364%destructor { delete $$; } <tree_classdef_methods_list_type>
365%destructor { delete $$; } <tree_classdef_methods_block_type>
366%destructor { delete $$; } <tree_classdef_event_type>
367%destructor { delete $$; } <tree_classdef_events_list_type>
368%destructor { delete $$; } <tree_classdef_events_block_type>
369%destructor { delete $$; } <tree_classdef_enum_type>
370%destructor { delete $$; } <tree_classdef_enum_list_type>
371%destructor { delete $$; } <tree_classdef_enum_block_type>
372
373// Defining a generic destructor generates a warning if destructors are
374// already explicitly declared for all types.
375//
376// %destructor {
377//    warning_with_id
378//      ("Octave:parser-destructor",
379//       "possible memory leak in cleanup following parse error");
380// } <*>
381
382// Where to start.
383%start input
384
385%%
386
387// ==============================
388// Statements and statement lists
389// ==============================
390
391input           : simple_list '\n'
392                  {
393                    OCTAVE_YYUSE ($2);
394
395                    $$ = nullptr;
396                    std::shared_ptr<octave::tree_statement_list> tmp_lst ($1);
397                    parser.statement_list (tmp_lst);
398                    YYACCEPT;
399                  }
400                | simple_list END_OF_INPUT
401                  {
402                    OCTAVE_YYUSE ($2);
403
404                    $$ = nullptr;
405                    lexer.m_end_of_input = true;
406                    std::shared_ptr<octave::tree_statement_list> tmp_lst ($1);
407                    parser.statement_list (tmp_lst);
408                    YYACCEPT;
409                  }
410                | parse_error
411                  {
412                    $$ = nullptr;
413                    YYABORT;
414                  }
415                ;
416
417simple_list     : opt_sep_no_nl
418                  {
419                    OCTAVE_YYUSE ($1);
420
421                    $$ = nullptr;
422                  }
423                | simple_list1 opt_sep_no_nl
424                  { $$ = parser.set_stmt_print_flag ($1, $2, false); }
425                ;
426
427simple_list1    : statement
428                  { $$ = parser.make_statement_list ($1); }
429                | simple_list1 sep_no_nl statement
430                  { $$ = parser.append_statement_list ($1, $2, $3, false); }
431                ;
432
433opt_list        : // empty
434                  { $$ = new octave::tree_statement_list (); }
435                | list
436                  { $$ = $1; }
437                ;
438
439list            : list1 opt_sep
440                  { $$ = parser.set_stmt_print_flag ($1, $2, true); }
441                ;
442
443list1           : statement
444                  { $$ = parser.make_statement_list ($1); }
445                | list1 sep statement
446                  { $$ = parser.append_statement_list ($1, $2, $3, true); }
447                ;
448
449opt_fcn_list    : // empty
450                  { $$ = new octave::tree_statement_list (); }
451                | fcn_list
452                  { $$ = $1; }
453                ;
454
455fcn_list        : fcn_list1 opt_sep
456                  {
457                    OCTAVE_YYUSE ($2);
458
459                    $$ = $1;
460                  }
461                ;
462
463fcn_list1       : function
464                  {
465                    octave::tree_statement *stmt = parser.make_statement ($1);
466                    $$ = new octave::tree_statement_list (stmt);
467                  }
468                | fcn_list1 opt_sep function
469                  {
470                    octave::tree_statement *stmt = parser.make_statement ($3);
471                    $$ = parser.append_statement_list ($1, $2, stmt, false);
472                  }
473                ;
474
475statement       : expression
476                  { $$ = parser.make_statement ($1); }
477                | command
478                  { $$ = parser.make_statement ($1); }
479                | word_list_cmd
480                  { $$ = parser.make_statement ($1); }
481                ;
482
483// =================
484// Word-list command
485// =================
486
487// These are not really like expressions since they can't appear on
488// the RHS of an assignment.  But they are also not like commands (IF,
489// WHILE, etc.
490
491word_list_cmd   : identifier word_list
492                  {
493                    $$ = parser.make_index_expression ($1, $2, '(');
494                    if (! $$)
495                      {
496                        // make_index_expression deleted $1 and $2.
497                        YYABORT;
498                      }
499                    $$->mark_word_list_cmd ();
500                  }
501                ;
502
503word_list       : string
504                  { $$ = new octave::tree_argument_list ($1); }
505                | word_list string
506                  {
507                    $1->append ($2);
508                    $$ = $1;
509                  }
510                ;
511
512// ===========
513// Expressions
514// ===========
515
516identifier      : NAME
517                  {
518                    $$ = new octave::tree_identifier ($1->sym_rec (),
519                                                      $1->line (),
520                                                      $1->column ());
521                  }
522                ;
523
524superclass_identifier
525                : SUPERCLASSREF
526                  {
527                    std::string meth = $1->superclass_method_name ();
528                    std::string cls = $1->superclass_class_name ();
529
530                    $$ = new octave::tree_superclass_ref (meth, cls,
531                                                          $1->line (),
532                                                          $1->column ());
533                  }
534                ;
535
536meta_identifier : METAQUERY
537                  {
538                    std::string cls = $1->text ();
539
540                    $$ = new octave::tree_metaclass_query (cls, $1->line (),
541                                                           $1->column ());
542                  }
543                ;
544
545string          : DQ_STRING
546                  { $$ = parser.make_constant (DQ_STRING, $1); }
547                | SQ_STRING
548                  { $$ = parser.make_constant (SQ_STRING, $1); }
549                ;
550
551constant        : NUM
552                  { $$ = parser.make_constant (NUM, $1); }
553                | IMAG_NUM
554                  { $$ = parser.make_constant (IMAG_NUM, $1); }
555                | string
556                  { $$ = $1; }
557                ;
558
559matrix          : '[' matrix_rows ']'
560                  { $$ = parser.finish_matrix ($2, $1, $3); }
561                ;
562
563matrix_rows     : cell_or_matrix_row
564                  { $$ = $1 ? new octave::tree_matrix ($1) : nullptr; }
565                | matrix_rows ';' cell_or_matrix_row
566                  {
567                    OCTAVE_YYUSE ($2);
568
569                    if ($1)
570                      {
571                        if ($3)
572                          $1->append ($3);
573
574                        $$ = $1;
575                      }
576                    else
577                      $$ = $3 ? new octave::tree_matrix ($3) : nullptr;
578                  }
579                ;
580
581cell            : '{' cell_rows '}'
582                  { $$ = parser.finish_cell ($2, $1, $3); }
583                ;
584
585cell_rows       : cell_or_matrix_row
586                  { $$ = $1 ? new octave::tree_cell ($1) : nullptr; }
587                | cell_rows ';' cell_or_matrix_row
588                  {
589                    OCTAVE_YYUSE ($2);
590
591                    if ($1)
592                      {
593                        if ($3)
594                          $1->append ($3);
595
596                        $$ = $1;
597                      }
598                    else
599                      $$ = $3 ? new octave::tree_cell ($3) : nullptr;
600                  }
601                ;
602
603// tree_argument_list objects can't be empty or have leading or trailing
604// commas, but those are all allowed in matrix and cell array rows.
605
606// FIXME: is tree_argument_list the best object for this purpose, or
607// should we have a separate one intended specifically to represent the
608// list of objects that make up elements in cell and matrix expressions?
609
610cell_or_matrix_row
611                : // empty
612                  { $$ = nullptr; }
613                | ','
614                  {
615                    OCTAVE_YYUSE ($1);
616
617                    $$ = nullptr;
618                  }
619                | arg_list
620                  { $$ = $1; }
621                | arg_list ','
622                  {
623                    OCTAVE_YYUSE ($2);
624
625                    $$ = $1;
626                  }
627                | ',' arg_list
628                  {
629                    OCTAVE_YYUSE ($1);
630
631                    $$ = $2;
632                  }
633                | ',' arg_list ','
634                  {
635                    OCTAVE_YYUSE ($1);
636                    OCTAVE_YYUSE ($3);
637
638                    $$ = $2;
639                  }
640                ;
641
642fcn_handle      : FCN_HANDLE
643                  { $$ = parser.make_fcn_handle ($1); }
644                ;
645
646// Note that we are deliberately not setting the beginning of statement
647// flag after recognizing the parameter list because we don't want to
648// accept word list commands in anonymous function bodies.
649
650anon_fcn_handle : '@' param_list anon_fcn_begin expression
651                  {
652                    $$ = parser.make_anon_fcn_handle ($2, $4, $1->beg_pos ());
653                    if (! $$)
654                      {
655                        // make_anon_fcn_handle deleted $2 and $4.
656                        YYABORT;
657                      }
658
659                    lexer.m_parsing_anon_fcn_body = false;
660                    lexer.m_nesting_level.remove ();
661                  }
662                | '@' param_list anon_fcn_begin error
663                  {
664                    OCTAVE_YYUSE ($1);
665                    OCTAVE_YYUSE ($2);
666
667                    lexer.m_parsing_anon_fcn_body = false;
668
669                    $$ = nullptr;
670                    parser.bison_error ("anonymous function bodies must be single expressions");
671                    YYABORT;
672                  }
673                ;
674
675primary_expr    : identifier
676                  { $$ = $1; }
677                | constant
678                  { $$ = $1; }
679                | fcn_handle
680                  { $$ = $1; }
681                | matrix
682                  {
683                    lexer.m_looking_at_matrix_or_assign_lhs = false;
684                    $$ = $1;
685                  }
686                | cell
687                  { $$ = $1; }
688                | meta_identifier
689                  { $$ = $1; }
690                | superclass_identifier
691                  { $$ = $1; }
692                | '(' expression ')'
693                  {
694                    OCTAVE_YYUSE ($1);
695                    OCTAVE_YYUSE ($3);
696
697                    $$ = $2->mark_in_parens ();
698                  }
699                ;
700
701magic_colon     : ':'
702                  {
703                    OCTAVE_YYUSE ($1);
704
705                    octave_value tmp (octave_value::magic_colon_t);
706                    $$ = new octave::tree_constant (tmp);
707                  }
708                ;
709
710magic_tilde     : EXPR_NOT
711                  {
712                    OCTAVE_YYUSE ($1);
713
714                    $$ = new octave::tree_black_hole ();
715                  }
716                ;
717
718arg_list        : expression
719                  { $$ = new octave::tree_argument_list ($1); }
720                | magic_colon
721                  { $$ = new octave::tree_argument_list ($1); }
722                | magic_tilde
723                  { $$ = new octave::tree_argument_list ($1); }
724                | arg_list ',' magic_colon
725                  {
726                    OCTAVE_YYUSE ($2);
727
728                    $1->append ($3);
729                    $$ = $1;
730                  }
731                | arg_list ',' magic_tilde
732                  {
733                    OCTAVE_YYUSE ($2);
734
735                    $1->append ($3);
736                    $$ = $1;
737                  }
738                | arg_list ',' expression
739                  {
740                    OCTAVE_YYUSE ($2);
741
742                    $1->append ($3);
743                    $$ = $1;
744                  }
745                ;
746
747indirect_ref_op : '.'
748                  {
749                    OCTAVE_YYUSE ($1);
750
751                    $$ = 0;
752                    lexer.m_looking_at_indirect_ref = true;
753                  }
754                ;
755
756oper_expr       : primary_expr
757                  { $$ = $1; }
758                | oper_expr PLUS_PLUS
759                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
760                | oper_expr MINUS_MINUS
761                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
762                | oper_expr '(' ')'
763                  {
764                    OCTAVE_YYUSE ($2);
765                    OCTAVE_YYUSE ($3);
766
767                    $$ = parser.make_index_expression ($1, nullptr, '(');
768                    if (! $$)
769                      {
770                        // make_index_expression deleted $1.
771                        YYABORT;
772                      }
773                  }
774                | oper_expr '(' arg_list ')'
775                  {
776                    OCTAVE_YYUSE ($2);
777                    OCTAVE_YYUSE ($4);
778
779                    $$ = parser.make_index_expression ($1, $3, '(');
780                    if (! $$)
781                      {
782                        // make_index_expression deleted $1 and $3.
783                        YYABORT;
784                      }
785                  }
786                | oper_expr '{' '}'
787                  {
788                    OCTAVE_YYUSE ($2);
789                    OCTAVE_YYUSE ($3);
790
791                    $$ = parser.make_index_expression ($1, nullptr, '{');
792                    if (! $$)
793                      {
794                        // make_index_expression deleted $1.
795                        YYABORT;
796                      }
797                  }
798                | oper_expr '{' arg_list '}'
799                  {
800                    OCTAVE_YYUSE ($2);
801                    OCTAVE_YYUSE ($4);
802
803                    $$ = parser.make_index_expression ($1, $3, '{');
804                    if (! $$)
805                      {
806                        // make_index_expression deleted $1 and $3.
807                        YYABORT;
808                      }
809                  }
810                | oper_expr HERMITIAN
811                  { $$ = parser.make_postfix_op (HERMITIAN, $1, $2); }
812                | oper_expr TRANSPOSE
813                  { $$ = parser.make_postfix_op (TRANSPOSE, $1, $2); }
814                | oper_expr indirect_ref_op STRUCT_ELT
815                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
816                | oper_expr indirect_ref_op '(' expression ')'
817                  {
818                    OCTAVE_YYUSE ($3);
819                    OCTAVE_YYUSE ($5);
820
821                    $$ = parser.make_indirect_ref ($1, $4);
822                  }
823                | PLUS_PLUS oper_expr %prec UNARY
824                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
825                | MINUS_MINUS oper_expr %prec UNARY
826                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
827                | EXPR_NOT oper_expr %prec UNARY
828                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
829                | '+' oper_expr %prec UNARY
830                  { $$ = parser.make_prefix_op ('+', $2, $1); }
831                | '-' oper_expr %prec UNARY
832                  { $$ = parser.make_prefix_op ('-', $2, $1); }
833                | oper_expr POW power_expr
834                  { $$ = parser.make_binary_op (POW, $1, $2, $3); }
835                | oper_expr EPOW power_expr
836                  { $$ = parser.make_binary_op (EPOW, $1, $2, $3); }
837                | oper_expr '+' oper_expr
838                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
839                | oper_expr '-' oper_expr
840                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
841                | oper_expr '*' oper_expr
842                  { $$ = parser.make_binary_op ('*', $1, $2, $3); }
843                | oper_expr '/' oper_expr
844                  { $$ = parser.make_binary_op ('/', $1, $2, $3); }
845                | oper_expr EPLUS oper_expr
846                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
847                | oper_expr EMINUS oper_expr
848                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
849                | oper_expr EMUL oper_expr
850                  { $$ = parser.make_binary_op (EMUL, $1, $2, $3); }
851                | oper_expr EDIV oper_expr
852                  { $$ = parser.make_binary_op (EDIV, $1, $2, $3); }
853                | oper_expr LEFTDIV oper_expr
854                  { $$ = parser.make_binary_op (LEFTDIV, $1, $2, $3); }
855                | oper_expr ELEFTDIV oper_expr
856                  { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
857                ;
858
859power_expr      : primary_expr
860                  { $$ = $1; }
861                | power_expr PLUS_PLUS
862                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
863                | power_expr MINUS_MINUS
864                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
865                | power_expr '(' ')'
866                  {
867                    OCTAVE_YYUSE ($2);
868                    OCTAVE_YYUSE ($3);
869
870                    $$ = parser.make_index_expression ($1, nullptr, '(');
871                    if (! $$)
872                      {
873                        // make_index_expression deleted $1.
874                        YYABORT;
875                      }
876                  }
877                | power_expr '(' arg_list ')'
878                  {
879                    OCTAVE_YYUSE ($2);
880                    OCTAVE_YYUSE ($4);
881
882                    $$ = parser.make_index_expression ($1, $3, '(');
883                    if (! $$)
884                      {
885                        // make_index_expression deleted $1 and $3.
886                        YYABORT;
887                      }
888                  }
889                | power_expr '{' '}'
890                  {
891                    OCTAVE_YYUSE ($2);
892                    OCTAVE_YYUSE ($3);
893
894                    $$ = parser.make_index_expression ($1, nullptr, '{');
895                    if (! $$)
896                      {
897                        // make_index_expression deleted $1.
898                        YYABORT;
899                      }
900                  }
901                | power_expr '{' arg_list '}'
902                  {
903                    OCTAVE_YYUSE ($2);
904                    OCTAVE_YYUSE ($4);
905
906                    $$ = parser.make_index_expression ($1, $3, '{');
907                    if (! $$)
908                      {
909                        // make_index_expression deleted $1 and $3.
910                        YYABORT;
911                      }
912                  }
913                | power_expr indirect_ref_op STRUCT_ELT
914                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
915                | power_expr indirect_ref_op '(' expression ')'
916                  {
917                    OCTAVE_YYUSE ($3);
918                    OCTAVE_YYUSE ($5);
919
920                    $$ = parser.make_indirect_ref ($1, $4);
921                  }
922                | PLUS_PLUS power_expr %prec POW
923                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
924                | MINUS_MINUS power_expr %prec POW
925                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
926                | EXPR_NOT power_expr %prec POW
927                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
928                | '+' power_expr %prec POW
929                  { $$ = parser.make_prefix_op ('+', $2, $1); }
930                | '-' power_expr %prec POW
931                  { $$ = parser.make_prefix_op ('-', $2, $1); }
932                ;
933
934colon_expr      : oper_expr ':' oper_expr
935                  {
936                    OCTAVE_YYUSE ($2);
937
938                    $$ = parser.make_colon_expression ($1, $3);
939
940                    if (! $$)
941                      {
942                        // finish_colon_expression deleted $1 and $3.
943                        YYABORT;
944                      }
945                  }
946                | oper_expr ':' oper_expr ':' oper_expr
947                  {
948                    OCTAVE_YYUSE ($2);
949                    OCTAVE_YYUSE ($4);
950
951                    $$ = parser.make_colon_expression ($1, $5, $3);
952
953                    if (! $$)
954                      {
955                        // finish_colon_expression deleted $1, $3, and $5.
956                        YYABORT;
957                      }
958                  }
959                ;
960
961simple_expr     : oper_expr
962                  { $$ = $1; }
963                | colon_expr
964                  { $$ = $1; }
965                | simple_expr EXPR_LT simple_expr
966                  { $$ = parser.make_binary_op (EXPR_LT, $1, $2, $3); }
967                | simple_expr EXPR_LE simple_expr
968                  { $$ = parser.make_binary_op (EXPR_LE, $1, $2, $3); }
969                | simple_expr EXPR_EQ simple_expr
970                  { $$ = parser.make_binary_op (EXPR_EQ, $1, $2, $3); }
971                | simple_expr EXPR_GE simple_expr
972                  { $$ = parser.make_binary_op (EXPR_GE, $1, $2, $3); }
973                | simple_expr EXPR_GT simple_expr
974                  { $$ = parser.make_binary_op (EXPR_GT, $1, $2, $3); }
975                | simple_expr EXPR_NE simple_expr
976                  { $$ = parser.make_binary_op (EXPR_NE, $1, $2, $3); }
977                | simple_expr EXPR_AND simple_expr
978                  { $$ = parser.make_binary_op (EXPR_AND, $1, $2, $3); }
979                | simple_expr EXPR_OR simple_expr
980                  { $$ = parser.make_binary_op (EXPR_OR, $1, $2, $3); }
981                | simple_expr EXPR_AND_AND simple_expr
982                  { $$ = parser.make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
983                | simple_expr EXPR_OR_OR simple_expr
984                  { $$ = parser.make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
985                ;
986
987assign_lhs      : simple_expr
988                  {
989                    $$ = parser.validate_matrix_for_assignment ($1);
990
991                    if ($$)
992                      { lexer.m_looking_at_matrix_or_assign_lhs = false; }
993                    else
994                      {
995                        // validate_matrix_for_assignment deleted $1.
996                        YYABORT;
997                      }
998                  }
999                ;
1000
1001assign_expr     : assign_lhs '=' expression
1002                  { $$ = parser.make_assign_op ('=', $1, $2, $3); }
1003                | assign_lhs ADD_EQ expression
1004                  { $$ = parser.make_assign_op (ADD_EQ, $1, $2, $3); }
1005                | assign_lhs SUB_EQ expression
1006                  { $$ = parser.make_assign_op (SUB_EQ, $1, $2, $3); }
1007                | assign_lhs MUL_EQ expression
1008                  { $$ = parser.make_assign_op (MUL_EQ, $1, $2, $3); }
1009                | assign_lhs DIV_EQ expression
1010                  { $$ = parser.make_assign_op (DIV_EQ, $1, $2, $3); }
1011                | assign_lhs LEFTDIV_EQ expression
1012                  { $$ = parser.make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
1013                | assign_lhs POW_EQ expression
1014                  { $$ = parser.make_assign_op (POW_EQ, $1, $2, $3); }
1015                | assign_lhs EMUL_EQ expression
1016                  { $$ = parser.make_assign_op (EMUL_EQ, $1, $2, $3); }
1017                | assign_lhs EDIV_EQ expression
1018                  { $$ = parser.make_assign_op (EDIV_EQ, $1, $2, $3); }
1019                | assign_lhs ELEFTDIV_EQ expression
1020                  { $$ = parser.make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
1021                | assign_lhs EPOW_EQ expression
1022                  { $$ = parser.make_assign_op (EPOW_EQ, $1, $2, $3); }
1023                | assign_lhs AND_EQ expression
1024                  { $$ = parser.make_assign_op (AND_EQ, $1, $2, $3); }
1025                | assign_lhs OR_EQ expression
1026                  { $$ = parser.make_assign_op (OR_EQ, $1, $2, $3); }
1027                ;
1028
1029expression      : simple_expr
1030                  {
1031                    if ($1 && ($1->is_matrix () || $1->iscell ()))
1032                      {
1033                        if (parser.validate_array_list ($1))
1034                          $$ = $1;
1035                        else
1036                          {
1037                            delete $1;
1038                            YYABORT;
1039                          }
1040                      }
1041                    else
1042                      $$ = $1;
1043                  }
1044                | assign_expr
1045                  {
1046                    if (! $1)
1047                      YYABORT;
1048
1049                    $$ = $1;
1050                  }
1051                | anon_fcn_handle
1052                  { $$ = $1; }
1053                ;
1054
1055// ================================================
1056// Commands, declarations, and function definitions
1057// ================================================
1058
1059command         : declaration
1060                  { $$ = $1; }
1061                | select_command
1062                  { $$ = $1; }
1063                | loop_command
1064                  { $$ = $1; }
1065                | jump_command
1066                  { $$ = $1; }
1067                | except_command
1068                  { $$ = $1; }
1069                | function
1070                  { $$ = $1; }
1071                | file
1072                  { $$ = $1; }
1073                ;
1074
1075// ======================
1076// Declaration statements
1077// ======================
1078
1079declaration     : GLOBAL decl1
1080                  {
1081                    $$ = parser.make_decl_command (GLOBAL, $1, $2);
1082                    lexer.m_looking_at_decl_list = false;
1083                  }
1084                | PERSISTENT decl1
1085                  {
1086                    $$ = parser.make_decl_command (PERSISTENT, $1, $2);
1087                    lexer.m_looking_at_decl_list = false;
1088                  }
1089                ;
1090
1091decl1           : decl2
1092                  { $$ = new octave::tree_decl_init_list ($1); }
1093                | decl1 decl2
1094                  {
1095                    $1->append ($2);
1096                    $$ = $1;
1097                  }
1098                ;
1099
1100decl_param_init : // empty
1101                  {
1102                    $$ = 0;
1103                    lexer.m_looking_at_initializer_expression = true;
1104                  }
1105
1106decl2           : identifier
1107                  { $$ = new octave::tree_decl_elt ($1); }
1108                | identifier '=' decl_param_init expression
1109                  {
1110                    OCTAVE_YYUSE ($2);
1111
1112                    lexer.m_looking_at_initializer_expression = false;
1113                    $$ = new octave::tree_decl_elt ($1, $4);
1114                  }
1115                ;
1116
1117// ====================
1118// Selection statements
1119// ====================
1120
1121select_command  : if_command
1122                  { $$ = $1; }
1123                | switch_command
1124                  { $$ = $1; }
1125                ;
1126
1127// ============
1128// If statement
1129// ============
1130
1131if_command      : IF stash_comment if_cmd_list END
1132                  {
1133                    if (! ($$ = parser.finish_if_command ($1, $3, $4, $2)))
1134                      {
1135                        // finish_if_command deleted $3.
1136                        YYABORT;
1137                      }
1138                  }
1139                ;
1140
1141if_cmd_list     : if_cmd_list1
1142                  { $$ = $1; }
1143                | if_cmd_list1 else_clause
1144                  {
1145                    $1->append ($2);
1146                    $$ = $1;
1147                  }
1148                ;
1149
1150if_cmd_list1    : expression stmt_begin opt_sep opt_list
1151                  {
1152                    OCTAVE_YYUSE ($3);
1153
1154                    $1->mark_braindead_shortcircuit ();
1155
1156                    $$ = parser.start_if_command ($1, $4);
1157                  }
1158                | if_cmd_list1 elseif_clause
1159                  {
1160                    $1->append ($2);
1161                    $$ = $1;
1162                  }
1163                ;
1164
1165elseif_clause   : ELSEIF stash_comment opt_sep expression stmt_begin opt_sep opt_list
1166                  {
1167                    OCTAVE_YYUSE ($3);
1168                    OCTAVE_YYUSE ($6);
1169
1170                    $4->mark_braindead_shortcircuit ();
1171
1172                    $$ = parser.make_elseif_clause ($1, $4, $7, $2);
1173                  }
1174                ;
1175
1176else_clause     : ELSE stash_comment opt_sep opt_list
1177                  {
1178                    OCTAVE_YYUSE ($1);
1179                    OCTAVE_YYUSE ($3);
1180
1181                    $$ = new octave::tree_if_clause ($4, $2);
1182                  }
1183                ;
1184
1185// ================
1186// Switch statement
1187// ================
1188
1189switch_command  : SWITCH stash_comment expression opt_sep case_list END
1190                  {
1191                    OCTAVE_YYUSE ($4);
1192
1193                    if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2)))
1194                      {
1195                        // finish_switch_command deleted $3 adn $5.
1196                        YYABORT;
1197                      }
1198                  }
1199                ;
1200
1201case_list       : // empty
1202                  { $$ = new octave::tree_switch_case_list (); }
1203                | default_case
1204                  { $$ = new octave::tree_switch_case_list ($1); }
1205                | case_list1
1206                  { $$ = $1; }
1207                | case_list1 default_case
1208                  {
1209                    $1->append ($2);
1210                    $$ = $1;
1211                  }
1212                ;
1213
1214case_list1      : switch_case
1215                  { $$ = new octave::tree_switch_case_list ($1); }
1216                | case_list1 switch_case
1217                  {
1218                    $1->append ($2);
1219                    $$ = $1;
1220                  }
1221                ;
1222
1223switch_case     : CASE stash_comment opt_sep expression stmt_begin opt_sep opt_list
1224                  {
1225                    OCTAVE_YYUSE ($3);
1226                    OCTAVE_YYUSE ($6);
1227
1228                    $$ = parser.make_switch_case ($1, $4, $7, $2);
1229                  }
1230                ;
1231
1232default_case    : OTHERWISE stash_comment opt_sep opt_list
1233                  {
1234                    OCTAVE_YYUSE ($1);
1235                    OCTAVE_YYUSE ($3);
1236
1237                    $$ = new octave::tree_switch_case ($4, $2);
1238                  }
1239                ;
1240
1241// =======
1242// Looping
1243// =======
1244
1245loop_command    : WHILE stash_comment expression stmt_begin opt_sep opt_list END
1246                  {
1247                    OCTAVE_YYUSE ($5);
1248
1249                    $3->mark_braindead_shortcircuit ();
1250
1251                    if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2)))
1252                      {
1253                        // make_while_command deleted $3 and $6.
1254                        YYABORT;
1255                      }
1256                  }
1257                | DO stash_comment opt_sep opt_list UNTIL expression
1258                  {
1259                    OCTAVE_YYUSE ($1);
1260                    OCTAVE_YYUSE ($3);
1261
1262                    $$ = parser.make_do_until_command ($5, $4, $6, $2);
1263                  }
1264                | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
1265                  {
1266                    OCTAVE_YYUSE ($4);
1267                    OCTAVE_YYUSE ($7);
1268
1269                    if (! ($$ = parser.make_for_command (FOR, $1, $3, $5,
1270                                                         nullptr, $8, $9, $2)))
1271                      {
1272                        // make_for_command deleted $3, $5, and $8.
1273                        YYABORT;
1274                      }
1275                  }
1276                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
1277                  {
1278                    OCTAVE_YYUSE ($3);
1279                    OCTAVE_YYUSE ($5);
1280                    OCTAVE_YYUSE ($7);
1281                    OCTAVE_YYUSE ($8);
1282
1283                    if (! ($$ = parser.make_for_command (FOR, $1, $4, $6,
1284                                                         nullptr, $9, $10, $2)))
1285                      {
1286                        // make_for_command deleted $4, $6, and $9.
1287                        YYABORT;
1288                      }
1289                  }
1290                | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
1291                  {
1292                    OCTAVE_YYUSE ($4);
1293                    OCTAVE_YYUSE ($7);
1294
1295                    if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5,
1296                                                         nullptr, $8, $9, $2)))
1297                      {
1298                        // make_for_command deleted $3, $5, and $8.
1299                        YYABORT;
1300                      }
1301                  }
1302                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
1303                  {
1304                    OCTAVE_YYUSE ($3);
1305                    OCTAVE_YYUSE ($5);
1306                    OCTAVE_YYUSE ($7);
1307                    OCTAVE_YYUSE ($9);
1308                    OCTAVE_YYUSE ($10);
1309
1310                    if (! ($$ = parser.make_for_command (PARFOR, $1, $4, $6,
1311                                                         $8, $11, $12, $2)))
1312                      {
1313                        // make_for_command deleted $4, $6, $8, and $11.
1314                        YYABORT;
1315                      }
1316                  }
1317                ;
1318
1319// =======
1320// Jumping
1321// =======
1322
1323jump_command    : BREAK
1324                  {
1325                    if (! ($$ = parser.make_break_command ($1)))
1326                      YYABORT;
1327                  }
1328                | CONTINUE
1329                  {
1330                    if (! ($$ = parser.make_continue_command ($1)))
1331                      YYABORT;
1332                  }
1333                | FUNC_RET
1334                  { $$ = parser.make_return_command ($1); }
1335                ;
1336
1337// ==========
1338// Exceptions
1339// ==========
1340
1341except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
1342                  stash_comment opt_sep opt_list END
1343                  {
1344                    OCTAVE_YYUSE ($3);
1345                    OCTAVE_YYUSE ($5);
1346                    OCTAVE_YYUSE ($7);
1347
1348                    if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6)))
1349                      {
1350                        // make_unwind_command deleted $4 and $8.
1351                        YYABORT;
1352                      }
1353                  }
1354                | TRY stash_comment opt_sep opt_list CATCH stash_comment
1355                  opt_sep opt_list END
1356                  {
1357                    OCTAVE_YYUSE ($3);
1358                    OCTAVE_YYUSE ($5);
1359                    OCTAVE_YYUSE ($7);
1360
1361                    if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6)))
1362                      {
1363                        // make_try_command deleted $4 and $8.
1364                        YYABORT;
1365                      }
1366                  }
1367                | TRY stash_comment opt_sep opt_list END
1368                  {
1369                    OCTAVE_YYUSE ($3);
1370
1371                    if (! ($$ = parser.make_try_command ($1, $4, 0, nullptr,
1372                                                         $5, $2, nullptr)))
1373                      {
1374                        // make_try_command deleted $4.
1375                        YYABORT;
1376                      }
1377                  }
1378                ;
1379
1380// ===========================================
1381// Some 'subroutines' for function definitions
1382// ===========================================
1383
1384push_fcn_symtab : // empty
1385                  {
1386                    if (! parser.push_fcn_symtab ())
1387                      YYABORT;
1388
1389                    $$ = 0;
1390                  }
1391                ;
1392
1393// ===========================
1394// List of function parameters
1395// ===========================
1396
1397param_list_beg  : '('
1398                  {
1399                    OCTAVE_YYUSE ($1);
1400
1401                    $$ = 0;
1402                    lexer.m_looking_at_parameter_list = true;
1403
1404                    if (lexer.m_looking_at_function_handle)
1405                      {
1406                        // Will get a real name later.
1407                        lexer.m_symtab_context.push (octave::symbol_scope ("parser:param_lsit_beg"));
1408                        lexer.m_looking_at_function_handle--;
1409                        lexer.m_looking_at_anon_fcn_args = true;
1410                      }
1411                  }
1412                ;
1413
1414param_list_end  : ')'
1415                  {
1416                    OCTAVE_YYUSE ($1);
1417
1418                    $$ = 0;
1419                    lexer.m_looking_at_parameter_list = false;
1420                    lexer.m_looking_for_object_index = false;
1421                  }
1422                ;
1423
1424opt_param_list  : // empty
1425                  { $$ = nullptr; }
1426                | param_list
1427                  { $$ = $1; }
1428                ;
1429
1430param_list      : param_list_beg param_list1 param_list_end
1431                  {
1432                    if ($2)
1433                      lexer.mark_as_variables ($2->variable_names ());
1434
1435                    $$ = $2;
1436                  }
1437                | param_list_beg error
1438                  {
1439                    $$ = nullptr;
1440                    parser.bison_error ("invalid parameter list");
1441                    YYABORT;
1442                  }
1443                ;
1444
1445param_list1     : // empty
1446                  { $$ = new octave::tree_parameter_list (octave::tree_parameter_list::in); }
1447                | param_list2
1448                  {
1449                    $1->mark_as_formal_parameters ();
1450
1451                    if (parser.validate_param_list ($1, octave::tree_parameter_list::in))
1452                      {
1453                        lexer.mark_as_variables ($1->variable_names ());
1454                        $$ = $1;
1455                      }
1456                    else
1457                      {
1458                        delete $1;
1459                        YYABORT;
1460                      }
1461                  }
1462                ;
1463
1464param_list2     : param_list_elt
1465                  { $$ = new octave::tree_parameter_list (octave::tree_parameter_list::in, $1); }
1466                | param_list2 ',' param_list_elt
1467                  {
1468                    OCTAVE_YYUSE ($2);
1469
1470                    $1->append ($3);
1471                    $$ = $1;
1472                  }
1473                ;
1474
1475param_list_elt  : decl2
1476                  { $$ = $1; }
1477                | magic_tilde
1478                  { $$ = new octave::tree_decl_elt ($1); }
1479                ;
1480
1481// ===================================
1482// List of function return value names
1483// ===================================
1484
1485return_list     : '[' ']'
1486                  {
1487                    OCTAVE_YYUSE ($1);
1488                    OCTAVE_YYUSE ($2);
1489
1490                    lexer.m_looking_at_return_list = false;
1491
1492                    $$ = new octave::tree_parameter_list (octave::tree_parameter_list::out);
1493                  }
1494                | identifier
1495                  {
1496                    lexer.m_looking_at_return_list = false;
1497
1498                    octave::tree_parameter_list *tmp
1499                      = new octave::tree_parameter_list (octave::tree_parameter_list::out, $1);
1500
1501                    // Even though this parameter list can contain only
1502                    // a single identifier, we still need to validate it
1503                    // to check for varargin or varargout.
1504
1505                    if (parser.validate_param_list (tmp, octave::tree_parameter_list::out))
1506                      $$ = tmp;
1507                    else
1508                      {
1509                        delete tmp;
1510                        YYABORT;
1511                      }
1512                  }
1513                | '[' return_list1 ']'
1514                  {
1515                    OCTAVE_YYUSE ($1);
1516                    OCTAVE_YYUSE ($3);
1517
1518                    lexer.m_looking_at_return_list = false;
1519
1520                    // Check for duplicate parameter names, varargin,
1521                    // or varargout.
1522
1523                    if (parser.validate_param_list ($2, octave::tree_parameter_list::out))
1524                      $$ = $2;
1525                    else
1526                      {
1527                        delete $2;
1528                        YYABORT;
1529                      }
1530                  }
1531                ;
1532
1533return_list1    : identifier
1534                  {
1535                    $$ = new octave::tree_parameter_list (octave::tree_parameter_list::out, new octave::tree_decl_elt ($1));
1536                  }
1537                | return_list1 ',' identifier
1538                  {
1539                    OCTAVE_YYUSE ($2);
1540
1541                    $1->append (new octave::tree_decl_elt ($3));
1542                    $$ = $1;
1543                  }
1544                ;
1545
1546// =======================
1547// Script or function file
1548// =======================
1549
1550parsing_local_fcns
1551                : // empty
1552                  { parser.parsing_local_functions (true); }
1553                ;
1554
1555push_script_symtab : // empty
1556                  {
1557                    $$ = 0;
1558
1559                    // This scope may serve as the parent scope for local
1560                    // functions in classdef files..
1561                    lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_script_symtab"));
1562                  }
1563                ;
1564
1565begin_file      : push_script_symtab INPUT_FILE
1566                  { $$ = 0; }
1567                ;
1568
1569file            : begin_file opt_nl opt_list END_OF_INPUT
1570                  {
1571                    OCTAVE_YYUSE ($2);
1572
1573                    if (lexer.m_reading_fcn_file)
1574                      {
1575                        // Delete the dummy statement_list we created
1576                        // after parsing the function.  Any function
1577                        // definitions found in the file have already
1578                        // been stored in the symbol table or in
1579                        // base_parser::m_primary_fcn.
1580
1581                        // Unused symbol table context.
1582                        lexer.m_symtab_context.pop ();
1583
1584                        delete $3;
1585                      }
1586                    else
1587                      {
1588                        octave::tree_statement *end_of_script
1589                          = parser.make_end ("endscript", true,
1590                                             $4->beg_pos (), $4->end_pos ());
1591
1592                        parser.make_script ($3, end_of_script);
1593                      }
1594
1595                    $$ = nullptr;
1596                  }
1597                | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT
1598                  {
1599                    OCTAVE_YYUSE ($2);
1600                    OCTAVE_YYUSE ($5);
1601                    OCTAVE_YYUSE ($7);
1602
1603                    // Unused symbol table context.
1604                    lexer.m_symtab_context.pop ();
1605
1606                    parser.finish_classdef_file ($3, $6);
1607
1608                    $$ = nullptr;
1609                  }
1610                ;
1611
1612// ===================
1613// Function definition
1614// ===================
1615
1616function_beg    : push_fcn_symtab FCN
1617                  {
1618                    $$ = $2;
1619                    if (lexer.m_reading_classdef_file
1620                        || lexer.m_parsing_classdef)
1621                      lexer.m_maybe_classdef_get_set_method = true;
1622                  }
1623                ;
1624
1625fcn_name        : identifier
1626                  {
1627                    $$ = parser.make_fcn_name ($1);
1628                    if (! $$)
1629                      {
1630                        // make_fcn_name deleted $1.
1631                        YYABORT;
1632                      }
1633                  }
1634                | GET '.' identifier
1635                  {
1636                    OCTAVE_YYUSE ($1);
1637                    OCTAVE_YYUSE ($2);
1638
1639                    lexer.m_parsed_function_name.top () = true;
1640                    lexer.m_maybe_classdef_get_set_method = false;
1641                    lexer.m_parsing_classdef_get_method = true;
1642                    $$ = $3;
1643                  }
1644                | SET '.' identifier
1645                  {
1646                    OCTAVE_YYUSE ($1);
1647                    OCTAVE_YYUSE ($2);
1648
1649                    lexer.m_parsed_function_name.top () = true;
1650                    lexer.m_maybe_classdef_get_set_method = false;
1651                    lexer.m_parsing_classdef_set_method = true;
1652                    $$ = $3;
1653                  }
1654                ;
1655
1656function_end    : END
1657                  {
1658                    parser.endfunction_found (true);
1659
1660                    if (parser.end_token_ok ($1, octave::token::function_end))
1661                      $$ = parser.make_end ("endfunction", false,
1662                                            $1->beg_pos (), $1->end_pos ());
1663                    else
1664                      {
1665                        parser.end_token_error ($1, octave::token::function_end);
1666                        YYABORT;
1667                      }
1668                  }
1669                | END_OF_INPUT
1670                  {
1671// A lot of tests are based on the assumption that this is OK
1672//                  if (lexer.m_reading_script_file)
1673//                    {
1674//                      parser.bison_error ("function body open at end of script");
1675//                      YYABORT;
1676//                    }
1677
1678                    if (parser.endfunction_found ())
1679                      {
1680                        parser.bison_error ("inconsistent function endings -- "
1681                                 "if one function is explicitly ended, "
1682                                 "so must all the others");
1683                        YYABORT;
1684                      }
1685
1686                    if (! (lexer.m_reading_fcn_file || lexer.m_reading_script_file
1687                           || lexer.input_from_eval_string ()))
1688                      {
1689                        parser.bison_error ("function body open at end of input");
1690                        YYABORT;
1691                      }
1692
1693                    if (lexer.m_reading_classdef_file)
1694                      {
1695                        parser.bison_error ("classdef body open at end of input");
1696                        YYABORT;
1697                      }
1698
1699                    $$ = parser.make_end ("endfunction", true,
1700                                          $1->beg_pos (), $1->end_pos ());
1701                  }
1702                ;
1703
1704function        : function_beg stash_comment fcn_name
1705                  opt_param_list opt_sep opt_list function_end
1706                  {
1707                    OCTAVE_YYUSE ($5);
1708
1709                    $$ = parser.make_function ($1, nullptr, $3, $4, $6, $7, $2);
1710                  }
1711                | function_beg stash_comment return_list '=' fcn_name
1712                  opt_param_list opt_sep opt_list function_end
1713                  {
1714                    OCTAVE_YYUSE ($4);
1715                    OCTAVE_YYUSE ($7);
1716
1717                    $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2);
1718                  }
1719                ;
1720
1721// ========
1722// Classdef
1723// ========
1724
1725classdef_beg    : CLASSDEF
1726                  {
1727                    if (! lexer.m_reading_classdef_file)
1728                      {
1729                        parser.bison_error ("classdef must appear inside a file containing only a class definition");
1730                        YYABORT;
1731                      }
1732
1733                    // Create invalid parent scope.
1734                    lexer.m_symtab_context.push (octave::symbol_scope ());
1735                    lexer.m_parsing_classdef = true;
1736                    lexer.m_parsing_classdef_decl = true;
1737
1738                    $$ = $1;
1739                  }
1740                ;
1741
1742classdef        : classdef_beg stash_comment attr_list identifier opt_sep superclass_list class_body END
1743                  {
1744                    OCTAVE_YYUSE ($5);
1745
1746                    octave::comment_list *lc = $2;
1747                    octave::comment_list *tc = lexer.get_comment ();
1748
1749                    lexer.m_parsing_classdef = false;
1750
1751                    if (! ($$ = parser.make_classdef ($1, $3, $4, $6, $7, $8,
1752                                                      lc, tc)))
1753                      {
1754                        // make_classdef deleted $3, $4, $6, $7, LC, and
1755                        // TC.
1756                        YYABORT;
1757                      }
1758                  }
1759                ;
1760
1761attr_list       : // empty
1762                  { $$ = nullptr; }
1763                | '(' attr_list1 ')' opt_sep
1764                  {
1765                    OCTAVE_YYUSE ($1);
1766                    OCTAVE_YYUSE ($3);
1767                    OCTAVE_YYUSE ($4);
1768
1769                    $$ = $2;
1770                  }
1771                ;
1772
1773attr_list1      : attr
1774                  { $$ = new octave::tree_classdef_attribute_list ($1); }
1775                | attr_list1 ',' attr
1776                  {
1777                    OCTAVE_YYUSE ($2);
1778
1779                    $1->append ($3);
1780                    $$ = $1;
1781                  }
1782                ;
1783
1784attr            : identifier
1785                  { $$ = new octave::tree_classdef_attribute ($1); }
1786                | identifier '=' decl_param_init expression
1787                  {
1788                    OCTAVE_YYUSE ($2);
1789
1790                    lexer.m_looking_at_initializer_expression = false;
1791                    $$ = new octave::tree_classdef_attribute ($1, $4);
1792                  }
1793                | EXPR_NOT identifier
1794                  {
1795                    OCTAVE_YYUSE ($1);
1796
1797                    $$ = new octave::tree_classdef_attribute ($2, false);
1798                  }
1799                ;
1800
1801superclass_list : // empty
1802                  {
1803                    lexer.m_parsing_classdef_decl = false;
1804                    lexer.m_parsing_classdef_superclass = false;
1805
1806                    $$ = nullptr;
1807                  }
1808                | superclass_list1 opt_sep
1809                  {
1810                    OCTAVE_YYUSE ($2);
1811
1812                    lexer.m_parsing_classdef_decl = false;
1813                    lexer.m_parsing_classdef_superclass = false;
1814
1815                    $$ = $1;
1816                  }
1817                ;
1818
1819superclass_list1
1820                : EXPR_LT superclass
1821                  {
1822                    OCTAVE_YYUSE ($1);
1823
1824                    $$ = new octave::tree_classdef_superclass_list ($2);
1825                  }
1826                | superclass_list1 EXPR_AND superclass
1827                  {
1828                    OCTAVE_YYUSE ($2);
1829
1830                    $1->append ($3);
1831                    $$ = $1;
1832                  }
1833                ;
1834
1835superclass      : FQ_IDENT
1836                  { $$ = new octave::tree_classdef_superclass ($1->text ()); }
1837                ;
1838
1839class_body      : // empty
1840                  { $$ = nullptr; }
1841                | class_body1 opt_sep
1842                  {
1843                    OCTAVE_YYUSE ($2);
1844
1845                    $$ = $1;
1846                  }
1847                ;
1848
1849class_body1     : properties_block
1850                  { $$ = new octave::tree_classdef_body ($1); }
1851                | methods_block
1852                  { $$ = new octave::tree_classdef_body ($1); }
1853                | events_block
1854                  { $$ = new octave::tree_classdef_body ($1); }
1855                | enum_block
1856                  { $$ = new octave::tree_classdef_body ($1); }
1857                | class_body1 opt_sep properties_block
1858                  {
1859                    OCTAVE_YYUSE ($2);
1860
1861                    $1->append ($3);
1862                    $$ = $1;
1863                  }
1864                | class_body1 opt_sep methods_block
1865                  {
1866                    OCTAVE_YYUSE ($2);
1867
1868                    $1->append ($3);
1869                    $$ = $1;
1870                  }
1871                | class_body1 opt_sep events_block
1872                  {
1873                    OCTAVE_YYUSE ($2);
1874
1875                    $1->append ($3);
1876                    $$ = $1;
1877                  }
1878                | class_body1 opt_sep enum_block
1879                  {
1880                    OCTAVE_YYUSE ($2);
1881
1882                    $1->append ($3);
1883                    $$ = $1;
1884                  }
1885                ;
1886
1887properties_block
1888                : PROPERTIES stash_comment opt_sep attr_list property_list END
1889                  {
1890                    OCTAVE_YYUSE ($3);
1891
1892                    octave::comment_list *lc = $2;
1893                    octave::comment_list *tc = lexer.get_comment ();
1894
1895                    if (! ($$ = parser.make_classdef_properties_block
1896                           ($1, $4, $5, $6, lc, tc)))
1897                      {
1898                        // make_classdef_properties_block deleted $4,
1899                        // $5, LC, and TC.
1900                        YYABORT;
1901                      }
1902                  }
1903                ;
1904
1905property_list   : // empty
1906                  { $$ = nullptr; }
1907                | property_list1 opt_sep
1908                  {
1909                    OCTAVE_YYUSE ($2);
1910
1911                    $$ = $1;
1912                  }
1913                ;
1914
1915property_list1
1916                : class_property
1917                  { $$ = new octave::tree_classdef_property_list ($1); }
1918                | property_list1 sep class_property
1919                  {
1920                    OCTAVE_YYUSE ($2);
1921
1922                    // We don't look ahead to grab end-of-line comments.
1923                    // Instead, they are grabbed when we see the
1924                    // identifier that becomes the next element in the
1925                    // list.  If the element at the end of the list
1926                    // doesn't have a doc string, see whether the
1927                    // element we are adding is stroing an end-of-line
1928                    // comment for us to use.
1929
1930                    octave::tree_classdef_property *last_elt = $1->back ();
1931
1932                    if (! last_elt->have_doc_string ())
1933                      {
1934                        octave::comment_list *cl = $3->comments ();
1935
1936                        if (cl)
1937                          {
1938                            octave::comment_elt elt = cl->front ();
1939
1940                            if (elt.is_end_of_line ())
1941                              last_elt->doc_string (elt.text ());
1942                          }
1943                      }
1944
1945                    $1->append ($3);
1946                    $$ = $1;
1947                  }
1948                ;
1949
1950class_property  : stash_comment identifier
1951                  {
1952                    $$ = new octave::tree_classdef_property ($2, $1);
1953                  }
1954                | stash_comment identifier '=' decl_param_init expression
1955                  {
1956                    OCTAVE_YYUSE ($3);
1957
1958                    lexer.m_looking_at_initializer_expression = false;
1959
1960                    $$ = new octave::tree_classdef_property ($2, $5, $1);
1961                  }
1962                ;
1963
1964methods_block   : METHODS stash_comment opt_sep attr_list methods_list END
1965                  {
1966                    OCTAVE_YYUSE ($3);
1967
1968                    octave::comment_list *lc = $2;
1969                    octave::comment_list *tc = lexer.get_comment ();
1970
1971                    if (! ($$ = parser.make_classdef_methods_block
1972                           ($1, $4, $5, $6, lc, tc)))
1973                      {
1974                        // make_classdef_methods_block deleted $4, $5,
1975                        // LC, and TC.
1976                        YYABORT;
1977                      }
1978                  }
1979                ;
1980
1981method_decl1    : identifier
1982                  {
1983                    if (! ($$ = parser.start_classdef_external_method ($1, nullptr)))
1984                      YYABORT;
1985                  }
1986                | identifier param_list
1987                  {
1988                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))
1989                      YYABORT;
1990                  }
1991                ;
1992
1993method_decl     : stash_comment method_decl1
1994                  { $$ = parser.finish_classdef_external_method ($2, nullptr, $1); }
1995                | stash_comment return_list '='
1996                  {
1997                    OCTAVE_YYUSE ($3);
1998
1999                    lexer.m_defining_func++;
2000                    lexer.m_parsed_function_name.push (false);
2001                  }
2002                  method_decl1
2003                  {
2004                    lexer.m_defining_func--;
2005                    lexer.m_parsed_function_name.pop ();
2006
2007                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
2008                  }
2009                ;
2010
2011method          : method_decl
2012                  { $$ = $1; }
2013                | function
2014                  { $$ = $1; }
2015                ;
2016
2017methods_list    : // empty
2018                  { $$ = nullptr; }
2019                | methods_list1 opt_sep
2020                  {
2021                    OCTAVE_YYUSE ($2);
2022
2023                    $$ = $1;
2024                  }
2025                ;
2026
2027methods_list1   : method
2028                  {
2029                    octave_value fcn;
2030                    if ($1)
2031                      fcn = $1->function ();
2032                    delete $1;
2033                    $$ = new octave::tree_classdef_methods_list (fcn);
2034                  }
2035                | methods_list1 opt_sep method
2036                  {
2037                    OCTAVE_YYUSE ($2);
2038
2039                    octave_value fcn;
2040                    if ($3)
2041                      fcn = $3->function ();
2042                    delete $3;
2043
2044                    $1->append (fcn);
2045                    $$ = $1;
2046                  }
2047                ;
2048
2049events_block    : EVENTS stash_comment opt_sep attr_list events_list END
2050                  {
2051                    OCTAVE_YYUSE ($3);
2052
2053                    octave::comment_list *lc = $2;
2054                    octave::comment_list *tc = lexer.get_comment ();
2055
2056                    if (! ($$ = parser.make_classdef_events_block
2057                           ($1, $4, $5, $6, lc, tc)))
2058                      {
2059                        // make_classdef_events_block deleted $4, $5,
2060                        // LC, and TC.
2061                        YYABORT;
2062                      }
2063                  }
2064                ;
2065
2066events_list     : // empty
2067                  { $$ = nullptr; }
2068                | events_list1 opt_sep
2069                  {
2070                    OCTAVE_YYUSE ($2);
2071
2072                    $$ = $1;
2073                  }
2074                ;
2075
2076events_list1    : class_event
2077                  { $$ = new octave::tree_classdef_events_list ($1); }
2078                | events_list1 opt_sep class_event
2079                  {
2080                    OCTAVE_YYUSE ($2);
2081
2082                    $1->append ($3);
2083                    $$ = $1;
2084                  }
2085                ;
2086
2087class_event     : stash_comment identifier
2088                  { $$ = new octave::tree_classdef_event ($2, $1); }
2089                ;
2090
2091enum_block      : ENUMERATION stash_comment opt_sep attr_list enum_list END
2092                  {
2093                    OCTAVE_YYUSE ($3);
2094
2095                    octave::comment_list *lc = $2;
2096                    octave::comment_list *tc = lexer.get_comment ();
2097
2098                    if (! ($$ = parser.make_classdef_enum_block
2099                           ($1, $4, $5, $6, lc, tc)))
2100                      {
2101                        // make_classdef_enum_block deleted $4, $5, LC,
2102                        // and TC.
2103                        YYABORT;
2104                      }
2105                  }
2106                ;
2107
2108enum_list       : // empty
2109                  { $$ = nullptr; }
2110                | enum_list1 opt_sep
2111                  {
2112                    OCTAVE_YYUSE ($2);
2113
2114                    $$ = $1;
2115                  }
2116                ;
2117
2118enum_list1      : class_enum
2119                  { $$ = new octave::tree_classdef_enum_list ($1); }
2120                | enum_list1 opt_sep class_enum
2121                  {
2122                    OCTAVE_YYUSE ($2);
2123
2124                    $1->append ($3);
2125                    $$ = $1;
2126                  }
2127                ;
2128
2129class_enum      : stash_comment identifier '(' expression ')'
2130                  {
2131                    OCTAVE_YYUSE ($3);
2132                    OCTAVE_YYUSE ($5);
2133
2134                    $$ = new octave::tree_classdef_enum ($2, $4, $1);
2135                  }
2136                ;
2137
2138// =============
2139// Miscellaneous
2140// =============
2141
2142stmt_begin      : // empty
2143                  {
2144                    $$ = 0;
2145                    lexer.m_at_beginning_of_statement = true;
2146                  }
2147                ;
2148
2149anon_fcn_begin  : // empty
2150                  {
2151                    $$ = 0;
2152                    lexer.m_at_beginning_of_statement = true;
2153                    lexer.m_parsing_anon_fcn_body = true;
2154                  }
2155                ;
2156
2157stash_comment   : // empty
2158                  { $$ = lexer.get_comment (); }
2159                ;
2160
2161parse_error     : LEXICAL_ERROR
2162                  {
2163                    $$ = 0;
2164                    std::string msg = $1->text ();
2165                    parser.bison_error (msg.c_str ());
2166                  }
2167                | error
2168                  { $$ = 0; }
2169                ;
2170
2171sep_no_nl       : ','
2172                  {
2173                    OCTAVE_YYUSE ($1);
2174
2175                    $$ = ',';
2176                  }
2177                | ';'
2178                  {
2179                    OCTAVE_YYUSE ($1);
2180
2181                    $$ = ';';
2182                  }
2183                | sep_no_nl ','
2184                  {
2185                    OCTAVE_YYUSE ($2);
2186
2187                    $$ = $1;
2188                  }
2189                | sep_no_nl ';'
2190                  {
2191                    OCTAVE_YYUSE ($2);
2192
2193                    $$ = $1;
2194                  }
2195                ;
2196
2197opt_sep_no_nl   : // empty
2198                  { $$ = 0; }
2199                | sep_no_nl
2200                  { $$ = $1; }
2201                ;
2202
2203opt_nl          : // empty
2204                  { $$ = 0; }
2205                | nl
2206                  { $$ = $1; }
2207                ;
2208
2209nl              : '\n'
2210                  {
2211                    OCTAVE_YYUSE ($1);
2212
2213                    $$ = '\n';
2214                  }
2215                | nl '\n'
2216                  {
2217                    OCTAVE_YYUSE ($2);
2218
2219                    $$ = $1;
2220                  }
2221                ;
2222
2223sep             : ','
2224                  {
2225                    OCTAVE_YYUSE ($1);
2226
2227                    $$ = ',';
2228                  }
2229                | ';'
2230                  {
2231                    OCTAVE_YYUSE ($1);
2232
2233                    $$ = ';';
2234                  }
2235                | '\n'
2236                  {
2237                    OCTAVE_YYUSE ($1);
2238
2239                    $$ = '\n';
2240                  }
2241                | sep ','
2242                  {
2243                    OCTAVE_YYUSE ($2);
2244
2245                    $$ = $1;
2246                  }
2247                | sep ';'
2248                  {
2249                    OCTAVE_YYUSE ($2);
2250
2251                    $$ = $1;
2252                  }
2253                | sep '\n'
2254                  {
2255                    OCTAVE_YYUSE ($2);
2256
2257                    $$ = $1;
2258                  }
2259                ;
2260
2261opt_sep         : // empty
2262                  { $$ = 0; }
2263                | sep
2264                  { $$ = $1; }
2265                ;
2266
2267%%
2268
2269#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
2270   // Restore prevailing warning state for remainder of the file.
2271#  pragma GCC diagnostic pop
2272#endif
2273
2274// Generic error messages.
2275
2276#undef lexer
2277#undef scanner
2278
2279static void
2280yyerror (octave::base_parser& parser, const char *s)
2281{
2282  parser.bison_error (s);
2283}
2284
2285namespace octave
2286{
2287  std::size_t
2288  base_parser::parent_scope_info::size (void) const
2289  {
2290    return m_info.size ();
2291  }
2292
2293  void
2294  base_parser::parent_scope_info::push (const value_type& elt)
2295  {
2296    m_info.push_back (elt);
2297  }
2298
2299  void
2300  base_parser::parent_scope_info::push (const symbol_scope& scope)
2301  {
2302    push (value_type (scope, ""));
2303  }
2304
2305  void
2306  base_parser::parent_scope_info::pop (void)
2307  {
2308    m_info.pop_back ();
2309  }
2310
2311  bool
2312  base_parser::parent_scope_info::name_ok (const std::string& name)
2313  {
2314    // Name can't be the same as any parent function or any other
2315    // function we've already seen.  We could maintain a complex
2316    // tree structure of names, or we can just store the set of
2317    // full names of all the functions, which must be unique.
2318
2319    std::string full_name;
2320
2321    for (std::size_t i = 0; i < size()-1; i++)
2322      {
2323        const value_type& elt = m_info[i];
2324
2325        if (name == elt.second)
2326          return false;
2327
2328        full_name += elt.second + ">";
2329      }
2330
2331    full_name += name;
2332
2333    if (m_all_names.find (full_name) != m_all_names.end ())
2334      {
2335        // Return false (failure) if we are parsing a subfunction, local
2336        // function, or nested function.  Otherwise, it is OK to have a
2337        // duplicate name.
2338
2339        return ! (m_parser.parsing_subfunctions ()
2340                  || m_parser.parsing_local_functions ()
2341                  || m_parser.curr_fcn_depth () > 0);
2342      }
2343
2344    m_all_names.insert (full_name);
2345
2346    return true;
2347  }
2348
2349  bool
2350  base_parser::parent_scope_info::name_current_scope (const std::string& name)
2351  {
2352    if (! name_ok (name))
2353      return false;
2354
2355    if (size () > 0)
2356      m_info.back().second = name;
2357
2358    return true;
2359  }
2360
2361  symbol_scope
2362  base_parser::parent_scope_info::parent_scope (void) const
2363  {
2364    return size () > 1 ? m_info[size()-2].first : symbol_scope ();
2365  }
2366
2367  std::string
2368  base_parser::parent_scope_info::parent_name (void) const
2369  {
2370    return m_info[size()-2].second;
2371  }
2372
2373  void base_parser::parent_scope_info::clear (void)
2374  {
2375    m_info.clear ();
2376    m_all_names.clear ();
2377  }
2378
2379  base_parser::base_parser (base_lexer& lxr)
2380    : m_endfunction_found (false), m_autoloading (false),
2381      m_fcn_file_from_relative_lookup (false),
2382      m_parsing_subfunctions (false), m_parsing_local_functions (false),
2383      m_max_fcn_depth (-1), m_curr_fcn_depth (-1), m_primary_fcn_scope (),
2384      m_curr_class_name (), m_curr_package_name (), m_function_scopes (*this),
2385      m_primary_fcn (), m_subfunction_names (), m_classdef_object (),
2386      m_stmt_list (), m_lexer (lxr), m_parser_state (yypstate_new ())
2387  { }
2388
2389  base_parser::~base_parser (void)
2390  {
2391    delete &m_lexer;
2392
2393    // FIXME: Deleting the internal Bison parser state structure does
2394    // not clean up any partial parse trees in the event of an interrupt or
2395    // error.  It's not clear how to safely do that with the C language
2396    // parser that Bison generates.  The C++ language parser that Bison
2397    // generates would do it for us automatically whenever an exception
2398    // is thrown while parsing input, but there is currently no C++
2399    // interface for a push parser.
2400
2401    yypstate_delete (static_cast<yypstate *> (m_parser_state));
2402  }
2403
2404  void
2405  base_parser::reset (void)
2406  {
2407    m_endfunction_found = false;
2408    m_autoloading = false;
2409    m_fcn_file_from_relative_lookup = false;
2410    m_parsing_subfunctions = false;
2411    m_parsing_local_functions = false;
2412    m_max_fcn_depth = -1;
2413    m_curr_fcn_depth = -1;
2414    m_primary_fcn_scope = symbol_scope ();
2415    m_curr_class_name = "";
2416    m_curr_package_name = "";
2417    m_function_scopes.clear ();
2418    m_primary_fcn = octave_value ();
2419    m_subfunction_names.clear ();
2420    m_classdef_object.reset ();
2421    m_stmt_list.reset ();
2422
2423    m_lexer.reset ();
2424
2425    yypstate_delete (static_cast<yypstate *> (m_parser_state));
2426    m_parser_state = yypstate_new ();
2427  }
2428
2429  // Error messages for mismatched end tokens.
2430
2431  static std::string
2432  end_token_as_string (token::end_tok_type ettype)
2433  {
2434    std::string retval = "<unknown>";
2435
2436    switch (ettype)
2437      {
2438      case token::simple_end:
2439        retval = "end";
2440        break;
2441
2442      case token::classdef_end:
2443        retval = "endclassdef";
2444        break;
2445
2446      case token::enumeration_end:
2447        retval = "endenumeration";
2448        break;
2449
2450      case token::events_end:
2451        retval = "endevents";
2452        break;
2453
2454      case token::for_end:
2455        retval = "endfor";
2456        break;
2457
2458      case token::function_end:
2459        retval = "endfunction";
2460        break;
2461
2462      case token::if_end:
2463        retval = "endif";
2464        break;
2465
2466      case token::methods_end:
2467        retval = "endmethods";
2468        break;
2469
2470      case token::parfor_end:
2471        retval = "endparfor";
2472        break;
2473
2474      case token::properties_end:
2475        retval = "endproperties";
2476        break;
2477
2478      case token::switch_end:
2479        retval = "endswitch";
2480        break;
2481
2482      case token::try_catch_end:
2483        retval = "end_try_catch";
2484        break;
2485
2486      case token::unwind_protect_end:
2487        retval = "end_unwind_protect";
2488        break;
2489
2490      case token::while_end:
2491        retval = "endwhile";
2492        break;
2493
2494      default:
2495        panic_impossible ();
2496        break;
2497      }
2498
2499    return retval;
2500  }
2501
2502  void
2503  base_parser::statement_list (std::shared_ptr<tree_statement_list>& lst)
2504  {
2505    if (! lst)
2506      return;
2507
2508    if (m_stmt_list)
2509      {
2510        // Append additional code to existing statement list.
2511
2512        while (! lst->empty ())
2513          {
2514            m_stmt_list->push_back (lst->front ());
2515            lst->pop_front ();
2516          }
2517      }
2518    else
2519      m_stmt_list = lst;
2520  }
2521
2522  void
2523  base_parser::end_token_error (token *tok, token::end_tok_type expected)
2524  {
2525    std::string msg = ("'" + end_token_as_string (expected)
2526                       + "' command matched by '"
2527                       + end_token_as_string (tok->ettype ()) + "'");
2528
2529    bison_error (msg, tok->beg_pos ());
2530  }
2531
2532  // Check to see that end tokens are properly matched.
2533
2534  bool
2535  base_parser::end_token_ok (token *tok, token::end_tok_type expected)
2536  {
2537    token::end_tok_type ettype = tok->ettype ();
2538
2539    return ettype == expected || ettype == token::simple_end;
2540  }
2541
2542  bool
2543  base_parser::push_fcn_symtab (void)
2544  {
2545    m_curr_fcn_depth++;
2546
2547    if (m_max_fcn_depth < m_curr_fcn_depth)
2548      m_max_fcn_depth = m_curr_fcn_depth;
2549
2550    // Will get a real name later.
2551    m_lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_fcn_symtab"));
2552    m_function_scopes.push (m_lexer.m_symtab_context.curr_scope ());
2553
2554    if (! m_lexer.m_reading_script_file && m_curr_fcn_depth == 0
2555        && ! m_parsing_subfunctions)
2556        {
2557          m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope ();
2558          m_primary_fcn_scope.mark_primary_fcn_scope ();
2559        }
2560
2561    if (m_lexer.m_reading_script_file && m_curr_fcn_depth > 0)
2562      {
2563        bison_error ("nested functions not implemented in this context");
2564
2565        return false;
2566      }
2567
2568    return true;
2569  }
2570
2571  // Make a constant.
2572
2573  tree_constant *
2574  base_parser::make_constant (int op, token *tok_val)
2575  {
2576    int l = tok_val->line ();
2577    int c = tok_val->column ();
2578
2579    tree_constant *retval = nullptr;
2580
2581    switch (op)
2582      {
2583      case NUM:
2584        {
2585          octave_value tmp (tok_val->number ());
2586          retval = new tree_constant (tmp, l, c);
2587          retval->stash_original_text (tok_val->text_rep ());
2588        }
2589        break;
2590
2591      case IMAG_NUM:
2592        {
2593          octave_value tmp (Complex (0.0, tok_val->number ()));
2594          retval = new tree_constant (tmp, l, c);
2595          retval->stash_original_text (tok_val->text_rep ());
2596        }
2597        break;
2598
2599      case DQ_STRING:
2600      case SQ_STRING:
2601        {
2602          std::string txt = tok_val->text ();
2603
2604          char delim = op == DQ_STRING ? '"' : '\'';
2605          octave_value tmp (txt, delim);
2606
2607          if (txt.empty ())
2608            {
2609              if (op == DQ_STRING)
2610                tmp = octave_null_str::instance;
2611              else
2612                tmp = octave_null_sq_str::instance;
2613            }
2614
2615          retval = new tree_constant (tmp, l, c);
2616
2617          if (op == DQ_STRING)
2618            txt = undo_string_escapes (txt);
2619
2620          // FIXME: maybe this should also be handled by
2621          // tok_val->text_rep () for character strings?
2622          retval->stash_original_text (delim + txt + delim);
2623        }
2624        break;
2625
2626      default:
2627        panic_impossible ();
2628        break;
2629      }
2630
2631    return retval;
2632  }
2633
2634  // Make a function handle.
2635
2636  tree_fcn_handle *
2637  base_parser::make_fcn_handle (token *tok_val)
2638  {
2639    int l = tok_val->line ();
2640    int c = tok_val->column ();
2641
2642    tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
2643
2644    return retval;
2645  }
2646
2647  // Make an anonymous function handle.
2648
2649  tree_anon_fcn_handle *
2650  base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
2651                                     tree_expression *expr,
2652                                     const filepos& at_pos)
2653  {
2654    // FIXME: We need to examine EXPR and issue an error if any
2655    // sub-expression contains an assignment, compound assignment,
2656    // increment, or decrement operator.
2657
2658    anon_fcn_validator validator (param_list, expr);
2659
2660    if (! validator.ok ())
2661      {
2662        delete param_list;
2663        delete expr;
2664
2665        bison_error (validator.message (), validator.line (),
2666                     validator.column ());
2667
2668        return nullptr;
2669      }
2670
2671    symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();
2672    symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();
2673
2674    m_lexer.m_symtab_context.pop ();
2675
2676    expr->set_print_flag (false);
2677
2678    fcn_scope.mark_static ();
2679
2680    int at_line = at_pos.line ();
2681    int at_column = at_pos.column ();
2682
2683    tree_anon_fcn_handle *retval
2684      = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
2685                                  parent_scope, at_line, at_column);
2686
2687    std::ostringstream buf;
2688
2689    tree_print_code tpc (buf);
2690
2691    retval->accept (tpc);
2692
2693    std::string file = m_lexer.m_fcn_file_full_name;
2694    if (! file.empty ())
2695      buf << ": file: " << file;
2696    else if (m_lexer.input_from_terminal ())
2697      buf << ": *terminal input*";
2698    else if (m_lexer.input_from_eval_string ())
2699      buf << ": *eval string*";
2700    buf << ": line: " << at_line << " column: " << at_column;
2701
2702    std::string scope_name = buf.str ();
2703
2704    fcn_scope.cache_name (scope_name);
2705
2706    // FIXME: Stash the filename.  This does not work and produces
2707    // errors when executed.
2708    //retval->stash_file_name (m_lexer.m_fcn_file_name);
2709
2710    return retval;
2711  }
2712
2713  // Build a colon expression.
2714
2715  tree_expression *
2716  base_parser::make_colon_expression (tree_expression *base,
2717                                      tree_expression *limit,
2718                                      tree_expression *incr)
2719  {
2720    tree_expression *retval = nullptr;
2721
2722    if (! base || ! limit)
2723      {
2724        delete base;
2725        delete limit;
2726        delete incr;
2727
2728        return retval;
2729      }
2730
2731    int l = base->line ();
2732    int c = base->column ();
2733
2734    tree_colon_expression *expr
2735      = new tree_colon_expression (base, limit, incr, l, c);
2736
2737    retval = expr;
2738
2739    if (base->is_constant () && limit->is_constant ()
2740        && (! incr || incr->is_constant ()))
2741      {
2742        interpreter& interp = __get_interpreter__ ("finish_colon_expression");
2743
2744        try
2745          {
2746            // If the evaluation generates a warning message, restore
2747            // the previous value of last_warning_message and skip the
2748            // conversion to a constant value.
2749
2750            unwind_protect frame;
2751
2752            error_system& es = interp.get_error_system ();
2753
2754            frame.add_method (es, &error_system::set_last_warning_message,
2755                              es.last_warning_message (""));
2756
2757            frame.add_method (es, &error_system::set_discard_warning_messages,
2758                              es.discard_warning_messages (true));
2759
2760            tree_evaluator& tw = interp.get_evaluator ();
2761
2762            octave_value tmp = expr->evaluate (tw);
2763
2764            std::string msg = es.last_warning_message ();
2765
2766            if (msg.empty ())
2767              {
2768                tree_constant *tc_retval
2769                  = new tree_constant (tmp, expr->line (), expr->column ());
2770
2771                std::ostringstream buf;
2772
2773                tree_print_code tpc (buf);
2774
2775                expr->accept (tpc);
2776
2777                tc_retval->stash_original_text (buf.str ());
2778
2779                delete expr;
2780
2781                retval = tc_retval;
2782              }
2783          }
2784        catch (const execution_exception&)
2785          {
2786            interp.recover_from_exception ();
2787          }
2788      }
2789
2790    return retval;
2791  }
2792
2793  // Build a binary expression.
2794
2795  tree_expression *
2796  base_parser::make_binary_op (int op, tree_expression *op1,
2797                               token *tok_val, tree_expression *op2)
2798  {
2799    octave_value::binary_op t = octave_value::unknown_binary_op;
2800
2801    switch (op)
2802      {
2803      case POW:
2804        t = octave_value::op_pow;
2805        break;
2806
2807      case EPOW:
2808        t = octave_value::op_el_pow;
2809        break;
2810
2811      case '+':
2812        t = octave_value::op_add;
2813        break;
2814
2815      case '-':
2816        t = octave_value::op_sub;
2817        break;
2818
2819      case '*':
2820        t = octave_value::op_mul;
2821        break;
2822
2823      case '/':
2824        t = octave_value::op_div;
2825        break;
2826
2827      case EMUL:
2828        t = octave_value::op_el_mul;
2829        break;
2830
2831      case EDIV:
2832        t = octave_value::op_el_div;
2833        break;
2834
2835      case LEFTDIV:
2836        t = octave_value::op_ldiv;
2837        break;
2838
2839      case ELEFTDIV:
2840        t = octave_value::op_el_ldiv;
2841        break;
2842
2843      case EXPR_LT:
2844        t = octave_value::op_lt;
2845        break;
2846
2847      case EXPR_LE:
2848        t = octave_value::op_le;
2849        break;
2850
2851      case EXPR_EQ:
2852        t = octave_value::op_eq;
2853        break;
2854
2855      case EXPR_GE:
2856        t = octave_value::op_ge;
2857        break;
2858
2859      case EXPR_GT:
2860        t = octave_value::op_gt;
2861        break;
2862
2863      case EXPR_NE:
2864        t = octave_value::op_ne;
2865        break;
2866
2867      case EXPR_AND:
2868        t = octave_value::op_el_and;
2869        break;
2870
2871      case EXPR_OR:
2872        t = octave_value::op_el_or;
2873        break;
2874
2875      default:
2876        panic_impossible ();
2877        break;
2878      }
2879
2880    int l = tok_val->line ();
2881    int c = tok_val->column ();
2882
2883    return maybe_compound_binary_expression (op1, op2, l, c, t);
2884  }
2885
2886  // Build a boolean expression.
2887
2888  tree_expression *
2889  base_parser::make_boolean_op (int op, tree_expression *op1,
2890                                token *tok_val, tree_expression *op2)
2891  {
2892    tree_boolean_expression::type t;
2893
2894    switch (op)
2895      {
2896      case EXPR_AND_AND:
2897        t = tree_boolean_expression::bool_and;
2898        break;
2899
2900      case EXPR_OR_OR:
2901        t = tree_boolean_expression::bool_or;
2902        break;
2903
2904      default:
2905        panic_impossible ();
2906        break;
2907      }
2908
2909    int l = tok_val->line ();
2910    int c = tok_val->column ();
2911
2912    return new tree_boolean_expression (op1, op2, l, c, t);
2913  }
2914
2915  // Build a prefix expression.
2916
2917  tree_expression *
2918  base_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
2919  {
2920    octave_value::unary_op t = octave_value::unknown_unary_op;
2921
2922    switch (op)
2923      {
2924      case EXPR_NOT:
2925        t = octave_value::op_not;
2926        break;
2927
2928      case '+':
2929        t = octave_value::op_uplus;
2930        break;
2931
2932      case '-':
2933        t = octave_value::op_uminus;
2934        break;
2935
2936      case PLUS_PLUS:
2937        t = octave_value::op_incr;
2938        break;
2939
2940      case MINUS_MINUS:
2941        t = octave_value::op_decr;
2942        break;
2943
2944      default:
2945        panic_impossible ();
2946        break;
2947      }
2948
2949    int l = tok_val->line ();
2950    int c = tok_val->column ();
2951
2952    return new tree_prefix_expression (op1, l, c, t);
2953  }
2954
2955  // Build a postfix expression.
2956
2957  tree_expression *
2958  base_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
2959  {
2960    octave_value::unary_op t = octave_value::unknown_unary_op;
2961
2962    switch (op)
2963      {
2964      case HERMITIAN:
2965        t = octave_value::op_hermitian;
2966        break;
2967
2968      case TRANSPOSE:
2969        t = octave_value::op_transpose;
2970        break;
2971
2972      case PLUS_PLUS:
2973        t = octave_value::op_incr;
2974        break;
2975
2976      case MINUS_MINUS:
2977        t = octave_value::op_decr;
2978        break;
2979
2980      default:
2981        panic_impossible ();
2982        break;
2983      }
2984
2985    int l = tok_val->line ();
2986    int c = tok_val->column ();
2987
2988    return new tree_postfix_expression (op1, l, c, t);
2989  }
2990
2991  // Build an unwind-protect command.
2992
2993  tree_command *
2994  base_parser::make_unwind_command (token *unwind_tok,
2995                                    tree_statement_list *body,
2996                                    tree_statement_list *cleanup_stmts,
2997                                    token *end_tok,
2998                                    comment_list *lc,
2999                                    comment_list *mc)
3000  {
3001    tree_command *retval = nullptr;
3002
3003    if (end_token_ok (end_tok, token::unwind_protect_end))
3004      {
3005        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3006
3007        int l = unwind_tok->line ();
3008        int c = unwind_tok->column ();
3009
3010        retval = new tree_unwind_protect_command (body, cleanup_stmts,
3011                                                  lc, mc, tc, l, c);
3012      }
3013    else
3014      {
3015        delete body;
3016        delete cleanup_stmts;
3017
3018        end_token_error (end_tok, token::unwind_protect_end);
3019      }
3020
3021    return retval;
3022  }
3023
3024  // Build a try-catch command.
3025
3026  tree_command *
3027  base_parser::make_try_command (token *try_tok,
3028                                 tree_statement_list *body,
3029                                 char catch_sep,
3030                                 tree_statement_list *cleanup_stmts,
3031                                 token *end_tok,
3032                                 comment_list *lc,
3033                                 comment_list *mc)
3034  {
3035    tree_command *retval = nullptr;
3036
3037    if (end_token_ok (end_tok, token::try_catch_end))
3038      {
3039        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3040
3041        int l = try_tok->line ();
3042        int c = try_tok->column ();
3043
3044        tree_identifier *id = nullptr;
3045
3046        if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
3047          {
3048            tree_statement *stmt = cleanup_stmts->front ();
3049
3050            if (stmt)
3051              {
3052                tree_expression *expr = stmt->expression ();
3053
3054                if (expr && expr->is_identifier ())
3055                  {
3056                    id = dynamic_cast<tree_identifier *> (expr);
3057
3058                    cleanup_stmts->pop_front ();
3059
3060                    stmt->set_expression (nullptr);
3061                    delete stmt;
3062                  }
3063              }
3064          }
3065
3066        retval = new tree_try_catch_command (body, cleanup_stmts, id,
3067                                             lc, mc, tc, l, c);
3068      }
3069    else
3070      {
3071        delete body;
3072        delete cleanup_stmts;
3073
3074        end_token_error (end_tok, token::try_catch_end);
3075      }
3076
3077    return retval;
3078  }
3079
3080  // Build a while command.
3081
3082  tree_command *
3083  base_parser::make_while_command (token *while_tok,
3084                                   tree_expression *expr,
3085                                   tree_statement_list *body,
3086                                   token *end_tok,
3087                                   comment_list *lc)
3088  {
3089    tree_command *retval = nullptr;
3090
3091    maybe_warn_assign_as_truth_value (expr);
3092
3093    if (end_token_ok (end_tok, token::while_end))
3094      {
3095        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3096
3097        m_lexer.m_looping--;
3098
3099        int l = while_tok->line ();
3100        int c = while_tok->column ();
3101
3102        retval = new tree_while_command (expr, body, lc, tc, l, c);
3103      }
3104    else
3105      {
3106        delete expr;
3107        delete body;
3108
3109        end_token_error (end_tok, token::while_end);
3110      }
3111
3112    return retval;
3113  }
3114
3115  // Build a do-until command.
3116
3117  tree_command *
3118  base_parser::make_do_until_command (token *until_tok,
3119                                      tree_statement_list *body,
3120                                      tree_expression *expr,
3121                                      comment_list *lc)
3122  {
3123    maybe_warn_assign_as_truth_value (expr);
3124
3125    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3126
3127    m_lexer.m_looping--;
3128
3129    int l = until_tok->line ();
3130    int c = until_tok->column ();
3131
3132    return new tree_do_until_command (expr, body, lc, tc, l, c);
3133  }
3134
3135  // Build a for command.
3136
3137  tree_command *
3138  base_parser::make_for_command (int tok_id, token *for_tok,
3139                                 tree_argument_list *lhs,
3140                                 tree_expression *expr,
3141                                 tree_expression *maxproc,
3142                                 tree_statement_list *body,
3143                                 token *end_tok,
3144                                 comment_list *lc)
3145  {
3146    tree_command *retval = nullptr;
3147
3148    bool parfor = tok_id == PARFOR;
3149
3150    if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
3151      {
3152        expr->mark_as_for_cmd_expr ();
3153
3154        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3155
3156        m_lexer.m_looping--;
3157
3158        int l = for_tok->line ();
3159        int c = for_tok->column ();
3160
3161        if (lhs->length () == 1)
3162          {
3163            tree_expression *tmp = lhs->remove_front ();
3164
3165            retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
3166                                                  body, lc, tc, l, c);
3167
3168            delete lhs;
3169          }
3170        else
3171          {
3172            if (parfor)
3173              {
3174                delete lhs;
3175                delete expr;
3176                delete maxproc;
3177                delete body;
3178
3179                bison_error ("invalid syntax for parfor statement");
3180              }
3181            else
3182              retval = new tree_complex_for_command (lhs, expr, body,
3183                                                     lc, tc, l, c);
3184          }
3185      }
3186    else
3187      {
3188        delete lhs;
3189        delete expr;
3190        delete maxproc;
3191        delete body;
3192
3193        end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
3194      }
3195
3196    return retval;
3197  }
3198
3199  // Build a break command.
3200
3201  tree_command *
3202  base_parser::make_break_command (token *break_tok)
3203  {
3204    int l = break_tok->line ();
3205    int c = break_tok->column ();
3206
3207    if (! m_lexer.m_looping)
3208      {
3209        bison_error ("break must appear within a loop");
3210        return nullptr;
3211      }
3212    else
3213      return new tree_break_command (l, c);
3214  }
3215
3216  // Build a continue command.
3217
3218  tree_command *
3219  base_parser::make_continue_command (token *continue_tok)
3220  {
3221    int l = continue_tok->line ();
3222    int c = continue_tok->column ();
3223
3224    if (! m_lexer.m_looping)
3225      {
3226        bison_error ("continue must appear within a loop");
3227        return nullptr;
3228      }
3229    else
3230      return new tree_continue_command (l, c);
3231  }
3232
3233  // Build a return command.
3234
3235  tree_command *
3236  base_parser::make_return_command (token *return_tok)
3237  {
3238    int l = return_tok->line ();
3239    int c = return_tok->column ();
3240
3241    return new tree_return_command (l, c);
3242  }
3243
3244  // Start an if command.
3245
3246  tree_if_command_list *
3247  base_parser::start_if_command (tree_expression *expr,
3248                                 tree_statement_list *list)
3249  {
3250    maybe_warn_assign_as_truth_value (expr);
3251
3252    tree_if_clause *t = new tree_if_clause (expr, list);
3253
3254    return new tree_if_command_list (t);
3255  }
3256
3257  // Finish an if command.
3258
3259  tree_if_command *
3260  base_parser::finish_if_command (token *if_tok,
3261                                  tree_if_command_list *list,
3262                                  token *end_tok,
3263                                  comment_list *lc)
3264  {
3265    tree_if_command *retval = nullptr;
3266
3267    if (end_token_ok (end_tok, token::if_end))
3268      {
3269        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3270
3271        int l = if_tok->line ();
3272        int c = if_tok->column ();
3273
3274        if (list && ! list->empty ())
3275          {
3276            tree_if_clause *elt = list->front ();
3277
3278            if (elt)
3279              {
3280                elt->line (l);
3281                elt->column (c);
3282              }
3283          }
3284
3285        retval = new tree_if_command (list, lc, tc, l, c);
3286      }
3287    else
3288      {
3289        delete list;
3290
3291        end_token_error (end_tok, token::if_end);
3292      }
3293
3294    return retval;
3295  }
3296
3297  // Build an elseif clause.
3298
3299  tree_if_clause *
3300  base_parser::make_elseif_clause (token *elseif_tok,
3301                                   tree_expression *expr,
3302                                   tree_statement_list *list,
3303                                   comment_list *lc)
3304  {
3305    maybe_warn_assign_as_truth_value (expr);
3306
3307    int l = elseif_tok->line ();
3308    int c = elseif_tok->column ();
3309
3310    return new tree_if_clause (expr, list, lc, l, c);
3311  }
3312
3313  // Finish a switch command.
3314
3315  tree_switch_command *
3316  base_parser::finish_switch_command (token *switch_tok,
3317                                      tree_expression *expr,
3318                                      tree_switch_case_list *list,
3319                                      token *end_tok,
3320                                      comment_list *lc)
3321  {
3322    tree_switch_command *retval = nullptr;
3323
3324    if (end_token_ok (end_tok, token::switch_end))
3325      {
3326        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3327
3328        int l = switch_tok->line ();
3329        int c = switch_tok->column ();
3330
3331        if (list && ! list->empty ())
3332          {
3333            tree_switch_case *elt = list->front ();
3334
3335            if (elt)
3336              {
3337                elt->line (l);
3338                elt->column (c);
3339              }
3340          }
3341
3342        retval = new tree_switch_command (expr, list, lc, tc, l, c);
3343      }
3344    else
3345      {
3346        delete expr;
3347        delete list;
3348
3349        end_token_error (end_tok, token::switch_end);
3350      }
3351
3352    return retval;
3353  }
3354
3355  // Build a switch case.
3356
3357  tree_switch_case *
3358  base_parser::make_switch_case (token *case_tok,
3359                                 tree_expression *expr,
3360                                 tree_statement_list *list,
3361                                 comment_list *lc)
3362  {
3363    maybe_warn_variable_switch_label (expr);
3364
3365    int l = case_tok->line ();
3366    int c = case_tok->column ();
3367
3368    return new tree_switch_case (expr, list, lc, l, c);
3369  }
3370
3371  // Build an assignment to a variable.
3372
3373  tree_expression *
3374  base_parser::make_assign_op (int op, tree_argument_list *lhs,
3375                               token *eq_tok, tree_expression *rhs)
3376  {
3377    octave_value::assign_op t = octave_value::unknown_assign_op;
3378
3379    switch (op)
3380      {
3381      case '=':
3382        t = octave_value::op_asn_eq;
3383        break;
3384
3385      case ADD_EQ:
3386        t = octave_value::op_add_eq;
3387        break;
3388
3389      case SUB_EQ:
3390        t = octave_value::op_sub_eq;
3391        break;
3392
3393      case MUL_EQ:
3394        t = octave_value::op_mul_eq;
3395        break;
3396
3397      case DIV_EQ:
3398        t = octave_value::op_div_eq;
3399        break;
3400
3401      case LEFTDIV_EQ:
3402        t = octave_value::op_ldiv_eq;
3403        break;
3404
3405      case POW_EQ:
3406        t = octave_value::op_pow_eq;
3407        break;
3408
3409      case EMUL_EQ:
3410        t = octave_value::op_el_mul_eq;
3411        break;
3412
3413      case EDIV_EQ:
3414        t = octave_value::op_el_div_eq;
3415        break;
3416
3417      case ELEFTDIV_EQ:
3418        t = octave_value::op_el_ldiv_eq;
3419        break;
3420
3421      case EPOW_EQ:
3422        t = octave_value::op_el_pow_eq;
3423        break;
3424
3425      case AND_EQ:
3426        t = octave_value::op_el_and_eq;
3427        break;
3428
3429      case OR_EQ:
3430        t = octave_value::op_el_or_eq;
3431        break;
3432
3433      default:
3434        panic_impossible ();
3435        break;
3436      }
3437
3438    int l = eq_tok->line ();
3439    int c = eq_tok->column ();
3440
3441    if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
3442      {
3443        // Multiple assignments like [x,y] OP= rhs are only valid for
3444        // '=', not '+=', etc.
3445
3446        delete lhs;
3447        delete rhs;
3448
3449        bison_error ("computed multiple assignment not allowed",
3450                     eq_tok->beg_pos ());
3451
3452        return nullptr;
3453      }
3454
3455    if (lhs->is_simple_assign_lhs ())
3456      {
3457        // We are looking at a simple assignment statement like x = rhs;
3458
3459        tree_expression *tmp = lhs->remove_front ();
3460
3461        if ((tmp->is_identifier () || tmp->is_index_expression ())
3462            && iskeyword (tmp->name ()))
3463          {
3464            std::string kw = tmp->name ();
3465
3466            delete tmp;
3467            delete lhs;
3468            delete rhs;
3469
3470            bison_error ("invalid assignment to keyword \"" + kw + "\"",
3471                         eq_tok->beg_pos ());
3472
3473            return nullptr;
3474          }
3475
3476        delete lhs;
3477
3478        return new tree_simple_assignment (tmp, rhs, false, l, c, t);
3479      }
3480    else
3481      {
3482        std::list<std::string> names = lhs->variable_names ();
3483
3484        for (const auto& kw : names)
3485          {
3486            if (iskeyword (kw))
3487              {
3488                delete lhs;
3489                delete rhs;
3490
3491                bison_error ("invalid assignment to keyword \"" + kw + "\"",
3492                             eq_tok->beg_pos ());
3493
3494                return nullptr;
3495              }
3496          }
3497
3498        return new tree_multi_assignment (lhs, rhs, false, l, c);
3499      }
3500  }
3501
3502  // Define a script.
3503
3504  void
3505  base_parser::make_script (tree_statement_list *cmds,
3506                            tree_statement *end_script)
3507  {
3508    if (! cmds)
3509      cmds = new tree_statement_list ();
3510
3511    cmds->append (end_script);
3512
3513    symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();
3514
3515    script_scope.cache_name (m_lexer.m_fcn_file_full_name);
3516    script_scope.cache_fcn_file_name (m_lexer.m_fcn_file_full_name);
3517    script_scope.cache_dir_name (m_lexer.m_dir_name);
3518
3519    octave_user_script *script
3520      = new octave_user_script (m_lexer.m_fcn_file_full_name,
3521                                m_lexer.m_fcn_file_name, script_scope,
3522                                cmds, m_lexer.m_help_text);
3523
3524    m_lexer.m_symtab_context.pop ();
3525    m_lexer.m_help_text = "";
3526
3527    sys::time now;
3528
3529    script->stash_fcn_file_time (now);
3530    script->stash_dir_name (m_lexer.m_dir_name);
3531
3532    m_primary_fcn = octave_value (script);
3533  }
3534
3535  tree_identifier *
3536  base_parser::make_fcn_name (tree_identifier *id)
3537  {
3538    std::string id_name = id->name ();
3539
3540    // Make classdef local functions unique from classdef methods.
3541
3542    if (m_parsing_local_functions && m_curr_fcn_depth == 0)
3543      id_name = m_lexer.m_fcn_file_name + ">" + id_name;
3544
3545    if (! m_function_scopes.name_current_scope (id_name))
3546      {
3547        bison_error ("duplicate subfunction or nested function name",
3548                     id->line (), id->column ());
3549
3550        delete id;
3551        return nullptr;
3552      }
3553
3554    octave::symbol_scope curr_scope = m_lexer.m_symtab_context.curr_scope ();
3555    curr_scope.cache_name (id_name);
3556
3557    m_lexer.m_parsed_function_name.top () = true;
3558    m_lexer.m_maybe_classdef_get_set_method = false;
3559
3560    return id;
3561  }
3562
3563  // Define a function.
3564
3565  // FIXME: combining start_function, finish_function, and
3566  // recover_from_parsing_function should be possible, but it makes
3567  // for a large mess.  Maybe this could be a bit better organized?
3568
3569  tree_function_def *
3570  base_parser::make_function (token *fcn_tok,
3571                              tree_parameter_list *ret_list,
3572                              tree_identifier *id,
3573                              tree_parameter_list *param_list,
3574                              tree_statement_list *body,
3575                              tree_statement *end_fcn_stmt,
3576                              comment_list *lc)
3577  {
3578    int l = fcn_tok->line ();
3579    int c = fcn_tok->column ();
3580
3581    octave_user_function *tmp_fcn
3582      = start_function (id, param_list, body, end_fcn_stmt);
3583
3584    tree_function_def *retval = finish_function (ret_list, tmp_fcn, lc, l, c);
3585
3586    recover_from_parsing_function ();
3587
3588    return retval;
3589  }
3590
3591  // Begin defining a function.
3592
3593  octave_user_function *
3594  base_parser::start_function (tree_identifier *id,
3595                               tree_parameter_list *param_list,
3596                               tree_statement_list *body,
3597                               tree_statement *end_fcn_stmt)
3598  {
3599    // We'll fill in the return list later.
3600
3601    std::string id_name = id->name ();
3602
3603    delete id;
3604
3605    if (m_lexer.m_parsing_classdef_get_method)
3606      id_name.insert (0, "get.");
3607    else if (m_lexer.m_parsing_classdef_set_method)
3608      id_name.insert (0, "set.");
3609
3610    m_lexer.m_parsing_classdef_get_method = false;
3611    m_lexer.m_parsing_classdef_set_method = false;
3612
3613    if (! body)
3614      body = new tree_statement_list ();
3615
3616    body->append (end_fcn_stmt);
3617
3618    octave_user_function *fcn
3619      = new octave_user_function (m_lexer.m_symtab_context.curr_scope (),
3620                                  param_list, nullptr, body);
3621
3622    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
3623
3624    fcn->stash_trailing_comment (tc);
3625    fcn->stash_fcn_end_location (end_fcn_stmt->line (),
3626                                 end_fcn_stmt->column ());
3627
3628    // If input is coming from a file, issue a warning if the name of
3629    // the file does not match the name of the function stated in the
3630    // file.  Matlab doesn't provide a diagnostic (it ignores the stated
3631    // name).
3632    if (! m_autoloading && m_lexer.m_reading_fcn_file
3633        && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
3634      {
3635        // FIXME: should m_lexer.m_fcn_file_name already be
3636        // preprocessed when we get here?  It seems to only be a
3637        // problem with relative filenames.
3638
3639        std::string nm = m_lexer.m_fcn_file_name;
3640
3641        std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
3642
3643        if (pos != std::string::npos)
3644          nm = m_lexer.m_fcn_file_name.substr (pos+1);
3645
3646        if (nm != id_name)
3647          {
3648            warning_with_id
3649              ("Octave:function-name-clash",
3650               "function name '%s' does not agree with function filename '%s'",
3651               id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
3652
3653            id_name = nm;
3654          }
3655      }
3656
3657    sys::time now;
3658
3659    fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);
3660    fcn->stash_fcn_file_time (now);
3661    fcn->stash_dir_name (m_lexer.m_dir_name);
3662    fcn->stash_package_name (m_lexer.m_package_name);
3663    fcn->mark_as_system_fcn_file ();
3664    fcn->stash_function_name (id_name);
3665
3666    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)
3667      {
3668        if (m_fcn_file_from_relative_lookup)
3669          fcn->mark_relative ();
3670
3671        if (m_lexer.m_parsing_class_method)
3672          {
3673            if (m_lexer.m_parsing_classdef)
3674              {
3675                if (m_curr_class_name == id_name)
3676                  fcn->mark_as_classdef_constructor ();
3677                else
3678                  fcn->mark_as_classdef_method ();
3679              }
3680            else
3681              {
3682                if (m_curr_class_name == id_name)
3683                  fcn->mark_as_legacy_constructor ();
3684                else
3685                  fcn->mark_as_legacy_method ();
3686              }
3687
3688            fcn->stash_dispatch_class (m_curr_class_name);
3689          }
3690
3691        std::string nm = fcn->fcn_file_name ();
3692
3693        sys::file_stat fs (nm);
3694
3695        if (fs && fs.is_newer (now))
3696          warning_with_id ("Octave:future-time-stamp",
3697                           "time stamp for '%s' is in the future", nm.c_str ());
3698      }
3699    else if (! m_lexer.input_from_tmp_history_file ()
3700             && ! m_lexer.m_force_script
3701             && m_lexer.m_reading_script_file
3702             && m_lexer.m_fcn_file_name == id_name)
3703      {
3704        warning ("function '%s' defined within script file '%s'",
3705                 id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
3706      }
3707
3708    // Record help text for functions other than nested functions.
3709    // We cannot currently record help for nested functions (bug #46008)
3710    // because the doc_string of the outermost function is read first,
3711    // whereas this function is called for the innermost function first.
3712    // We could have a stack of help_text in lexer.
3713    if (! m_lexer.m_help_text.empty () && m_curr_fcn_depth == 0)
3714      {
3715        fcn->document (m_lexer.m_help_text);
3716
3717        m_lexer.m_help_text = "";
3718      }
3719
3720    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0
3721        && ! m_parsing_subfunctions)
3722      m_primary_fcn = octave_value (fcn);
3723
3724    return fcn;
3725  }
3726
3727  tree_statement *
3728  base_parser::make_end (const std::string& type, bool eof,
3729                         const filepos& beg_pos, const filepos& /*end_pos*/)
3730  {
3731    int l = beg_pos.line ();
3732    int c = beg_pos.column ();
3733
3734    return make_statement (new tree_no_op_command (type, eof, l, c));
3735  }
3736
3737  tree_function_def *
3738  base_parser::finish_function (tree_parameter_list *ret_list,
3739                                octave_user_function *fcn,
3740                                comment_list *lc,
3741                                int l, int c)
3742  {
3743    tree_function_def *retval = nullptr;
3744
3745    if (! ret_list)
3746      ret_list = new tree_parameter_list (tree_parameter_list::out);
3747
3748    ret_list->mark_as_formal_parameters ();
3749
3750    if (fcn)
3751      {
3752        std::string fcn_nm = fcn->name ();
3753        std::string file = fcn->fcn_file_name ();
3754
3755        std::string tmp = fcn_nm;
3756        if (! file.empty ())
3757          tmp += ": " + file;
3758
3759        symbol_scope fcn_scope = fcn->scope ();
3760        fcn_scope.cache_name (tmp);
3761        fcn_scope.cache_fcn_name (fcn_nm);
3762        fcn_scope.cache_fcn_file_name (file);
3763        fcn_scope.cache_dir_name (m_lexer.m_dir_name);
3764
3765        if (lc)
3766          fcn->stash_leading_comment (lc);
3767
3768        fcn->define_ret_list (ret_list);
3769
3770        if (m_curr_fcn_depth > 0 || m_parsing_subfunctions)
3771          {
3772            fcn->stash_fcn_location (l, c);
3773            fcn->stash_parent_fcn_name (m_lexer.m_fcn_file_name);
3774
3775            octave_value ov_fcn (fcn);
3776
3777            if (m_endfunction_found && m_function_scopes.size () > 1)
3778              {
3779                fcn->mark_as_nested_function ();
3780                fcn_scope.set_nesting_depth (m_curr_fcn_depth);
3781
3782                symbol_scope pscope = m_function_scopes.parent_scope ();
3783                fcn_scope.set_parent (pscope);
3784                fcn_scope.set_primary_parent (m_primary_fcn_scope);
3785                pscope.install_nestfunction (fcn_nm, ov_fcn, fcn_scope);
3786
3787                // For nested functions, the list of parent functions is
3788                // set in symbol_scope::update_nest.
3789              }
3790            else
3791              {
3792                fcn->mark_as_subfunction ();
3793                m_subfunction_names.push_back (fcn_nm);
3794                fcn_scope.set_parent (m_primary_fcn_scope);
3795                if (m_parsing_subfunctions)
3796                  fcn_scope.set_primary_parent (m_primary_fcn_scope);
3797                m_primary_fcn_scope.install_subfunction (fcn_nm, ov_fcn);
3798
3799                // Prepend name of primary fucntion to list of parent
3800                // functions (if any) for subfunction.
3801
3802                std::list<std::string> plst
3803                  = fcn_scope.parent_fcn_names ();
3804                plst.push_front (m_primary_fcn_scope.fcn_name ());
3805                fcn_scope.cache_parent_fcn_names (plst);
3806              }
3807          }
3808
3809        if (m_curr_fcn_depth == 0)
3810          fcn_scope.update_nest ();
3811
3812        if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0)
3813          {
3814            // We are either reading a script file or defining a function
3815            // at the command line, so this definition creates a
3816            // tree_function object that is placed in the parse tree.
3817            // Otherwise, it is just inserted in the symbol table,
3818            // either as a subfunction or nested function (see above),
3819            // or as the primary function for the file, via
3820            // m_primary_fcn (see also load_fcn_from_file,,
3821            // parse_fcn_file, and
3822            // fcn_info::fcn_info_rep::find_user_function).
3823
3824            if (m_lexer.m_buffer_function_text)
3825              {
3826                fcn->cache_function_text (m_lexer.m_function_text,
3827                                          fcn->time_parsed ());
3828                m_lexer.m_buffer_function_text = false;
3829              }
3830
3831            retval = new tree_function_def (fcn);
3832          }
3833      }
3834
3835    return retval;
3836  }
3837
3838  void
3839  base_parser::recover_from_parsing_function (void)
3840  {
3841    m_lexer.m_symtab_context.pop ();
3842
3843    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0
3844        && ! m_parsing_subfunctions)
3845      m_parsing_subfunctions = true;
3846
3847    m_curr_fcn_depth--;
3848    m_function_scopes.pop ();
3849
3850    m_lexer.m_defining_func--;
3851    m_lexer.m_parsed_function_name.pop ();
3852    m_lexer.m_looking_at_return_list = false;
3853    m_lexer.m_looking_at_parameter_list = false;
3854  }
3855
3856  // A CLASSDEF block defines a class that has a constructor and other
3857  // methods, but it is not an executable command.  Parsing the block
3858  // makes some changes in the symbol table (inserting the constructor
3859  // and methods, and adding to the list of known objects) and creates
3860  // a parse tree containing meta information about the class.
3861
3862  // LC contains comments appearing before the classdef keyword.
3863  // TC contains comments appearing between the classdef elements
3864  // and the final end token for the classdef block.
3865
3866  tree_classdef *
3867  base_parser::make_classdef (token *tok_val,
3868                              tree_classdef_attribute_list *a,
3869                              tree_identifier *id,
3870                              tree_classdef_superclass_list *sc,
3871                              tree_classdef_body *body, token *end_tok,
3872                              comment_list *lc, comment_list *tc)
3873  {
3874    tree_classdef *retval = nullptr;
3875
3876    m_lexer.m_symtab_context.pop ();
3877
3878    std::string cls_name = id->name ();
3879
3880    std::string nm = m_lexer.m_fcn_file_name;
3881
3882    std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
3883
3884    if (pos != std::string::npos)
3885      nm = m_lexer.m_fcn_file_name.substr (pos+1);
3886
3887    if (nm != cls_name)
3888      {
3889        int l = id->line ();
3890        int c = id->column ();
3891
3892        delete a;
3893        delete id;
3894        delete sc;
3895        delete body;
3896        delete lc;
3897        delete tc;
3898
3899        bison_error ("invalid classdef definition, the class name must match the filename", l, c);
3900
3901      }
3902    else
3903      {
3904        if (end_token_ok (end_tok, token::classdef_end))
3905          {
3906            int l = tok_val->line ();
3907            int c = tok_val->column ();
3908
3909            if (! body)
3910              body = new tree_classdef_body ();
3911
3912            retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (),
3913                                        a, id, sc, body, lc, tc,
3914                                        m_curr_package_name, l, c);
3915          }
3916        else
3917          {
3918            delete a;
3919            delete id;
3920            delete sc;
3921            delete body;
3922            delete lc;
3923            delete tc;
3924
3925            end_token_error (end_tok, token::switch_end);
3926          }
3927      }
3928
3929    return retval;
3930  }
3931
3932  // LC contains comments appearing before the properties keyword.
3933  // If this properties block appears first in the list of classdef
3934  // elements, this comment list will be used for the help text for the
3935  // classdef block.
3936
3937  // TC contains comments appearing between the list of properties
3938  // and the final end token for the properties block and may be used to
3939  // find the doc string for the final property in the list.
3940
3941  tree_classdef_properties_block *
3942  base_parser::make_classdef_properties_block (token *tok_val,
3943                                               tree_classdef_attribute_list *a,
3944                                               tree_classdef_property_list *plist,
3945                                               token *end_tok,
3946                                               comment_list *lc,
3947                                               comment_list *tc)
3948  {
3949    tree_classdef_properties_block *retval = nullptr;
3950
3951    if (end_token_ok (end_tok, token::properties_end))
3952      {
3953        int l = tok_val->line ();
3954        int c = tok_val->column ();
3955
3956        if (plist)
3957          {
3958            // If the element at the end of the list doesn't have a doc
3959            // string, see whether the first element of TC is an
3960            // end-of-line comment for us to use.
3961
3962            if (tc)
3963              {
3964                tree_classdef_property *last_elt = plist->back ();
3965
3966                if (! last_elt->have_doc_string ())
3967                  {
3968                    comment_elt first_comment_elt = tc->front ();
3969
3970                    if (first_comment_elt.is_end_of_line ())
3971                      {
3972                        std::string eol_comment = first_comment_elt.text ();
3973
3974                        last_elt->doc_string (eol_comment);
3975                      }
3976                  }
3977              }
3978          }
3979        else
3980          plist = new tree_classdef_property_list ();
3981
3982        retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
3983      }
3984    else
3985      {
3986        delete a;
3987        delete plist;
3988        delete lc;
3989        delete tc;
3990
3991        end_token_error (end_tok, token::properties_end);
3992      }
3993
3994    return retval;
3995  }
3996
3997  // LC contains comments appearing before the methods keyword.
3998  // If this methods block appears first in the list of classdef
3999  // elements, this comment list will be used for the help text for the
4000  // classdef block.
4001
4002  tree_classdef_methods_block *
4003  base_parser::make_classdef_methods_block (token *tok_val,
4004                                            tree_classdef_attribute_list *a,
4005                                            tree_classdef_methods_list *mlist,
4006                                            token *end_tok, comment_list *lc,
4007                                            comment_list *tc)
4008  {
4009    tree_classdef_methods_block *retval = nullptr;
4010
4011    if (end_token_ok (end_tok, token::methods_end))
4012      {
4013        int l = tok_val->line ();
4014        int c = tok_val->column ();
4015
4016        if (! mlist)
4017          mlist = new tree_classdef_methods_list ();
4018
4019        retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
4020      }
4021    else
4022      {
4023        delete a;
4024        delete mlist;
4025        delete lc;
4026        delete tc;
4027
4028        end_token_error (end_tok, token::methods_end);
4029      }
4030
4031    return retval;
4032  }
4033
4034  // LC contains comments appearing before the events keyword.
4035  // If this events block appears first in the list of classdef
4036  // elements, this comment list will be used for the help text for the
4037  // classdef block.
4038
4039  // TC contains comments appearing between the list of events and
4040  // the final end token for the events block and may be used to find
4041  // the doc string for the final event in the list.
4042
4043  tree_classdef_events_block *
4044  base_parser::make_classdef_events_block (token *tok_val,
4045                                           tree_classdef_attribute_list *a,
4046                                           tree_classdef_events_list *elist,
4047                                           token *end_tok,
4048                                           comment_list *lc,
4049                                           comment_list *tc)
4050  {
4051    tree_classdef_events_block *retval = nullptr;
4052
4053    if (end_token_ok (end_tok, token::events_end))
4054      {
4055        int l = tok_val->line ();
4056        int c = tok_val->column ();
4057
4058        if (! elist)
4059          elist = new tree_classdef_events_list ();
4060
4061        retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
4062      }
4063    else
4064      {
4065        delete a;
4066        delete elist;
4067        delete lc;
4068        delete tc;
4069
4070        end_token_error (end_tok, token::events_end);
4071      }
4072
4073    return retval;
4074  }
4075
4076  // LC contains comments appearing before the enumeration keyword.
4077  // If this enumeration block appears first in the list of classdef
4078  // elements, this comment list will be used for the help text for the
4079  // classdef block.
4080
4081  // TC contains comments appearing between the list of
4082  // enumerations and the final end token for the enumeration block and
4083  // may be used to find the doc string for the final enumeration in the
4084  // list.
4085
4086  tree_classdef_enum_block *
4087  base_parser::make_classdef_enum_block (token *tok_val,
4088                                         tree_classdef_attribute_list *a,
4089                                         tree_classdef_enum_list *elist,
4090                                         token *end_tok,
4091                                         comment_list *lc,
4092                                         comment_list *tc)
4093  {
4094    tree_classdef_enum_block *retval = nullptr;
4095
4096    if (end_token_ok (end_tok, token::enumeration_end))
4097      {
4098        int l = tok_val->line ();
4099        int c = tok_val->column ();
4100
4101        if (! elist)
4102          elist = new tree_classdef_enum_list ();
4103
4104        retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
4105      }
4106    else
4107      {
4108        delete a;
4109        delete elist;
4110        delete lc;
4111        delete tc;
4112
4113        end_token_error (end_tok, token::enumeration_end);
4114      }
4115
4116    return retval;
4117  }
4118
4119  octave_user_function*
4120  base_parser::start_classdef_external_method (tree_identifier *id,
4121                                               tree_parameter_list *pl)
4122  {
4123    octave_user_function* retval = nullptr;
4124
4125    // External methods are only allowed within @-folders. In this case,
4126    // m_curr_class_name will be non-empty.
4127
4128    if (! m_curr_class_name.empty ())
4129      {
4130
4131        std::string mname = id->name ();
4132
4133        // Methods that cannot be declared outside the classdef file:
4134        // - methods with '.' character (e.g. property accessors)
4135        // - class constructor
4136        // - 'delete'
4137
4138        if (mname.find_first_of (".") == std::string::npos
4139            && mname != "delete"
4140            && mname != m_curr_class_name)
4141          {
4142            // Create a dummy function that is used until the real method
4143            // is loaded.
4144
4145            retval = new octave_user_function (symbol_scope (), pl);
4146
4147            retval->stash_function_name (mname);
4148
4149            int l = id->line ();
4150            int c = id->column ();
4151
4152            retval->stash_fcn_location (l, c);
4153          }
4154        else
4155          bison_error ("invalid external method declaration, an external "
4156                       "method cannot be the class constructor, 'delete' "
4157                       "or have a dot (.) character in its name");
4158      }
4159    else
4160      bison_error ("external methods are only allowed in @-folders");
4161
4162    if (! retval)
4163      delete id;
4164
4165    return retval;
4166  }
4167
4168  tree_function_def *
4169  base_parser::finish_classdef_external_method (octave_user_function *fcn,
4170                                                tree_parameter_list *ret_list,
4171                                                comment_list *cl)
4172  {
4173    if (! ret_list)
4174      ret_list = new tree_parameter_list (tree_parameter_list::out);
4175
4176    fcn->define_ret_list (ret_list);
4177
4178    if (cl)
4179      fcn->stash_leading_comment (cl);
4180
4181    int l = fcn->beginning_line ();
4182    int c = fcn->beginning_column ();
4183
4184    return new tree_function_def (fcn, l, c);
4185  }
4186
4187  void
4188  base_parser::finish_classdef_file (tree_classdef *cls,
4189                                     tree_statement_list *local_fcns)
4190  {
4191    if (m_lexer.m_reading_classdef_file)
4192      m_classdef_object = std::shared_ptr<tree_classdef> (cls);
4193
4194    if (local_fcns)
4195      {
4196        symbol_table& symtab
4197          = __get_symbol_table__ ("base_parser::finish_classdef_file");
4198
4199        for (tree_statement *elt : *local_fcns)
4200          {
4201            tree_command *cmd = elt->command ();
4202
4203            tree_function_def *fcn_def
4204              = dynamic_cast<tree_function_def *> (cmd);
4205
4206            octave_value ov_fcn = fcn_def->function ();
4207            octave_function *fcn = ov_fcn.function_value ();
4208            std::string nm = fcn->name ();
4209            std::string file = fcn->fcn_file_name ();
4210
4211            symtab.install_local_function (nm, ov_fcn, file);
4212          }
4213
4214        delete local_fcns;
4215      }
4216  }
4217
4218  // Make an index expression.
4219
4220  tree_index_expression *
4221  base_parser::make_index_expression (tree_expression *expr,
4222                                      tree_argument_list *args,
4223                                      char type)
4224  {
4225    tree_index_expression *retval = nullptr;
4226
4227    if (args && args->has_magic_tilde ())
4228      {
4229        delete expr;
4230        delete args;
4231
4232        bison_error ("invalid use of empty argument (~) in index expression");
4233      }
4234    else
4235      {
4236        int l = expr->line ();
4237        int c = expr->column ();
4238
4239        if (! expr->is_postfix_indexed ())
4240          expr->set_postfix_index (type);
4241
4242        if (expr->is_index_expression ())
4243          {
4244            tree_index_expression *tmp
4245              = dynamic_cast<tree_index_expression *> (expr);
4246
4247            tmp->append (args, type);
4248
4249            retval = tmp;
4250          }
4251        else
4252          retval = new tree_index_expression (expr, args, l, c, type);
4253      }
4254
4255    return retval;
4256  }
4257
4258  // Make an indirect reference expression.
4259
4260  tree_index_expression *
4261  base_parser::make_indirect_ref (tree_expression *expr,
4262                                  const std::string& elt)
4263  {
4264    tree_index_expression *retval = nullptr;
4265
4266    int l = expr->line ();
4267    int c = expr->column ();
4268
4269    if (! expr->is_postfix_indexed ())
4270      expr->set_postfix_index ('.');
4271
4272    if (expr->is_index_expression ())
4273      {
4274        tree_index_expression *tmp
4275          = dynamic_cast<tree_index_expression *> (expr);
4276
4277        tmp->append (elt);
4278
4279        retval = tmp;
4280      }
4281    else
4282      retval = new tree_index_expression (expr, elt, l, c);
4283
4284    m_lexer.m_looking_at_indirect_ref = false;
4285
4286    return retval;
4287  }
4288
4289  // Make an indirect reference expression with dynamic field name.
4290
4291  tree_index_expression *
4292  base_parser::make_indirect_ref (tree_expression *expr,
4293                                  tree_expression *elt)
4294  {
4295    tree_index_expression *retval = nullptr;
4296
4297    int l = expr->line ();
4298    int c = expr->column ();
4299
4300    if (! expr->is_postfix_indexed ())
4301      expr->set_postfix_index ('.');
4302
4303    if (expr->is_index_expression ())
4304      {
4305        tree_index_expression *tmp
4306          = dynamic_cast<tree_index_expression *> (expr);
4307
4308        tmp->append (elt);
4309
4310        retval = tmp;
4311      }
4312    else
4313      retval = new tree_index_expression (expr, elt, l, c);
4314
4315    m_lexer.m_looking_at_indirect_ref = false;
4316
4317    return retval;
4318  }
4319
4320  // Make a declaration command.
4321
4322  tree_decl_command *
4323  base_parser::make_decl_command (int tok, token *tok_val,
4324                                  tree_decl_init_list *lst)
4325  {
4326    tree_decl_command *retval = nullptr;
4327
4328    int l = tok_val->line ();
4329    int c = tok_val->column ();
4330
4331    if (lst)
4332      m_lexer.mark_as_variables (lst->variable_names ());
4333
4334    switch (tok)
4335      {
4336      case GLOBAL:
4337        {
4338          retval = new tree_decl_command ("global", lst, l, c);
4339          retval->mark_global ();
4340        }
4341        break;
4342
4343      case PERSISTENT:
4344        if (m_curr_fcn_depth >= 0)
4345          {
4346            retval = new tree_decl_command ("persistent", lst, l, c);
4347            retval->mark_persistent ();
4348          }
4349        else
4350          {
4351            if (m_lexer.m_reading_script_file)
4352              warning ("ignoring persistent declaration near line %d of file '%s'",
4353                       l, m_lexer.m_fcn_file_full_name.c_str ());
4354            else
4355              warning ("ignoring persistent declaration near line %d", l);
4356          }
4357        break;
4358
4359      default:
4360        panic_impossible ();
4361        break;
4362      }
4363
4364    return retval;
4365  }
4366
4367  bool
4368  base_parser::validate_param_list (tree_parameter_list *lst,
4369                                    tree_parameter_list::in_or_out type)
4370  {
4371    std::set<std::string> dict;
4372
4373    for (tree_decl_elt *elt : *lst)
4374      {
4375        tree_identifier *id = elt->ident ();
4376
4377        if (id)
4378          {
4379            std::string name = id->name ();
4380
4381            if (id->is_black_hole ())
4382              {
4383                if (type != tree_parameter_list::in)
4384                  {
4385                    bison_error ("invalid use of ~ in output list");
4386                    return false;
4387                  }
4388              }
4389            else if (dict.find (name) != dict.end ())
4390              {
4391                bison_error ("'" + name
4392                             + "' appears more than once in parameter list");
4393                return false;
4394              }
4395            else
4396              dict.insert (name);
4397          }
4398      }
4399
4400    std::string va_type = (type == tree_parameter_list::in
4401                           ? "varargin" : "varargout");
4402
4403    std::size_t len = lst->length ();
4404
4405    if (len > 0)
4406      {
4407        tree_decl_elt *elt = lst->back ();
4408
4409        tree_identifier *id = elt->ident ();
4410
4411        if (id && id->name () == va_type)
4412          {
4413            if (len == 1)
4414              lst->mark_varargs_only ();
4415            else
4416              lst->mark_varargs ();
4417
4418            tree_parameter_list::iterator p = lst->end ();
4419            --p;
4420            delete *p;
4421            lst->erase (p);
4422          }
4423      }
4424
4425    return true;
4426  }
4427
4428  bool
4429  base_parser::validate_array_list (tree_expression *e)
4430  {
4431    bool retval = true;
4432
4433    tree_array_list *al = dynamic_cast<tree_array_list *> (e);
4434
4435    for (tree_argument_list* row : *al)
4436      {
4437        if (row && row->has_magic_tilde ())
4438          {
4439            retval = false;
4440
4441            if (e->is_matrix ())
4442              bison_error ("invalid use of tilde (~) in matrix expression");
4443            else
4444              bison_error ("invalid use of tilde (~) in cell expression");
4445
4446            break;
4447          }
4448      }
4449
4450    return retval;
4451  }
4452
4453  tree_argument_list *
4454  base_parser::validate_matrix_for_assignment (tree_expression *e)
4455  {
4456    tree_argument_list *retval = nullptr;
4457
4458    if (e->is_constant ())
4459      {
4460        tree_evaluator& tw
4461          = __get_evaluator__ ("validate_matrix_for_assignment");
4462
4463        octave_value ov = e->evaluate (tw);
4464
4465        delete e;
4466
4467        if (ov.isempty ())
4468          bison_error ("invalid empty left hand side of assignment");
4469        else
4470          bison_error ("invalid constant left hand side of assignment");
4471      }
4472    else
4473      {
4474        bool is_simple_assign = true;
4475
4476        tree_argument_list *tmp = nullptr;
4477
4478        if (e->is_matrix ())
4479          {
4480            tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
4481
4482            if (mat && mat->size () == 1)
4483              {
4484                tmp = mat->front ();
4485                mat->pop_front ();
4486                delete e;
4487                is_simple_assign = false;
4488              }
4489          }
4490        else
4491          tmp = new tree_argument_list (e);
4492
4493        if (tmp && tmp->is_valid_lvalue_list ())
4494          {
4495            m_lexer.mark_as_variables (tmp->variable_names ());
4496            retval = tmp;
4497          }
4498        else
4499          {
4500            delete tmp;
4501
4502            bison_error ("invalid left hand side of assignment");
4503          }
4504
4505        if (retval && is_simple_assign)
4506          retval->mark_as_simple_assign_lhs ();
4507      }
4508
4509    return retval;
4510  }
4511
4512  // Finish building an array_list.
4513
4514  tree_expression *
4515  base_parser::finish_array_list (tree_array_list *array_list,
4516                                  token */*open_delim*/, token *close_delim)
4517  {
4518    tree_expression *retval = array_list;
4519
4520    array_list->set_location (close_delim->line (), close_delim->column ());
4521
4522    if (array_list->all_elements_are_constant ())
4523      {
4524        interpreter& interp = __get_interpreter__ ("finish_array_list");
4525
4526        try
4527          {
4528            // If the evaluation generates a warning message, restore
4529            // the previous value of last_warning_message and skip the
4530            // conversion to a constant value.
4531
4532            unwind_protect frame;
4533
4534            error_system& es = interp.get_error_system ();
4535
4536            frame.add_method (es, &error_system::set_last_warning_message,
4537                              es.last_warning_message (""));
4538
4539            frame.add_method (es, &error_system::set_discard_warning_messages,
4540                              es.discard_warning_messages (true));
4541
4542            tree_evaluator& tw = interp.get_evaluator ();
4543
4544            octave_value tmp = array_list->evaluate (tw);
4545
4546            std::string msg = es.last_warning_message ();
4547
4548            if (msg.empty ())
4549              {
4550                tree_constant *tc_retval
4551                  = new tree_constant (tmp, close_delim->line (),
4552                                       close_delim->column ());
4553
4554                std::ostringstream buf;
4555
4556                tree_print_code tpc (buf);
4557
4558                array_list->accept (tpc);
4559
4560                tc_retval->stash_original_text (buf.str ());
4561
4562                delete array_list;
4563
4564                retval = tc_retval;
4565              }
4566          }
4567        catch (const execution_exception&)
4568          {
4569            interp.recover_from_exception ();
4570          }
4571      }
4572
4573    return retval;
4574  }
4575
4576  // Finish building a matrix list.
4577
4578  tree_expression *
4579  base_parser::finish_matrix (tree_matrix *m, token *open_delim,
4580                              token *close_delim)
4581  {
4582    return (m
4583            ? finish_array_list (m, open_delim, close_delim)
4584            : new tree_constant (octave_null_matrix::instance,
4585                                 close_delim->line (), close_delim->column ()));
4586  }
4587
4588  // Finish building a cell list.
4589
4590  tree_expression *
4591  base_parser::finish_cell (tree_cell *c, token *open_delim,
4592                            token *close_delim)
4593  {
4594    return (c
4595            ? finish_array_list (c, open_delim, close_delim)
4596            : new tree_constant (octave_value (Cell ()),
4597                                 close_delim->line (), close_delim->column ()));
4598  }
4599
4600  tree_statement_list *
4601  base_parser::set_stmt_print_flag (tree_statement_list *list,
4602                                    char sep, bool warn_missing_semi)
4603  {
4604    tree_statement *tmp = list->back ();
4605
4606    switch (sep)
4607      {
4608      case ';':
4609        tmp->set_print_flag (false);
4610        break;
4611
4612      case 0:
4613      case ',':
4614      case '\n':
4615        tmp->set_print_flag (true);
4616        if (warn_missing_semi)
4617          maybe_warn_missing_semi (list);
4618        break;
4619
4620      default:
4621        warning ("unrecognized separator type!");
4622        break;
4623      }
4624
4625    // Even if a statement is null, we add it to the list then remove it
4626    // here so that the print flag is applied to the correct statement.
4627
4628    if (tmp->is_null_statement ())
4629      {
4630        list->pop_back ();
4631        delete tmp;
4632      }
4633
4634    return list;
4635  }
4636
4637  // Finish building a statement.
4638  template <typename T>
4639  tree_statement *
4640  base_parser::make_statement (T *arg)
4641  {
4642    comment_list *comment = m_lexer.get_comment ();
4643
4644    return new tree_statement (arg, comment);
4645  }
4646
4647  tree_statement_list *
4648  base_parser::make_statement_list (tree_statement *stmt)
4649  {
4650    return new tree_statement_list (stmt);
4651  }
4652
4653  tree_statement_list *
4654  base_parser::append_statement_list (tree_statement_list *list,
4655                                      char sep, tree_statement *stmt,
4656                                      bool warn_missing_semi)
4657  {
4658    set_stmt_print_flag (list, sep, warn_missing_semi);
4659
4660    list->append (stmt);
4661
4662    return list;
4663  }
4664
4665  void
4666  base_parser::disallow_command_syntax (void)
4667  {
4668    m_lexer.m_allow_command_syntax = false;
4669  }
4670
4671  // FIXME: this function partially duplicates do_dbtype in debug.cc.
4672  static std::string
4673  get_file_line (const std::string& name, int line)
4674  {
4675    // NAME should be an absolute file name and the file should exist.
4676
4677    std::ifstream fs = sys::ifstream (name.c_str (), std::ios::in);
4678
4679    std::string text;
4680
4681    if (fs)
4682      {
4683        int i = 1;
4684
4685        do
4686          {
4687            if (! std::getline (fs, text))
4688              {
4689                text = "";
4690                break;
4691              }
4692          }
4693        while (i++ < line);
4694      }
4695
4696    return text;
4697  }
4698
4699  void
4700  base_parser::bison_error (const std::string& str)
4701  {
4702    bison_error (str, m_lexer.m_filepos);
4703  }
4704
4705  void
4706  base_parser::bison_error (const std::string& str, const filepos& pos)
4707  {
4708    bison_error (str, pos.line (), pos.column ());
4709  }
4710
4711  void
4712  base_parser::bison_error (const std::string& str, int err_line, int err_col)
4713  {
4714    std::ostringstream output_buf;
4715
4716    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
4717        || m_lexer.m_reading_classdef_file)
4718      output_buf << "parse error near line " << err_line
4719                 << " of file " << m_lexer.m_fcn_file_full_name;
4720    else
4721      output_buf << "parse error:";
4722
4723    if (str != "parse error")
4724      output_buf << "\n\n  " << str;
4725
4726    output_buf << "\n\n";
4727
4728    std::string curr_line;
4729
4730    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
4731        || m_lexer.m_reading_classdef_file)
4732      curr_line = get_file_line (m_lexer.m_fcn_file_full_name, err_line);
4733    else
4734      curr_line = m_lexer.m_current_input_line;
4735
4736    // Adjust the error column for display because it is 1-based in the
4737    // lexer for easier reporting.
4738    err_col--;
4739
4740    if (! curr_line.empty ())
4741      {
4742        // FIXME: we could do better if we just cached lines from the
4743        // input file in a list.  See also functions for managing input
4744        // buffers in lex.ll.
4745
4746        std::size_t len = curr_line.length ();
4747
4748        if (curr_line[len-1] == '\n')
4749          curr_line.resize (len-1);
4750
4751        // Print the line, maybe with a pointer near the error token.
4752
4753        output_buf << ">>> " << curr_line << "\n";
4754
4755        if (err_col == 0)
4756          err_col = len;
4757
4758        for (int i = 0; i < err_col + 3; i++)
4759          output_buf << " ";
4760
4761        output_buf << "^";
4762      }
4763
4764    output_buf << "\n";
4765
4766    m_parse_error_msg = output_buf.str ();
4767  }
4768
4769  int
4770  parser::run (void)
4771  {
4772    int status = -1;
4773
4774    yypstate *pstate = static_cast<yypstate *> (m_parser_state);
4775
4776    try
4777      {
4778        status = octave_pull_parse (pstate, *this);
4779      }
4780    catch (const execution_exception&)
4781      {
4782        // FIXME: In previous versions, we emitted a parse error here
4783        // but that is not always correct because the error could have
4784        // happened inside a GUI callback functions executing in the
4785        // readline event_hook loop.  Maybe we need a separate exception
4786        // class for parse errors?
4787
4788        throw;
4789      }
4790    catch (const exit_exception&)
4791      {
4792        throw;
4793      }
4794    catch (const interrupt_exception&)
4795      {
4796        throw;
4797      }
4798    catch (...)
4799      {
4800        std::string file = m_lexer.m_fcn_file_full_name;
4801
4802        if (file.empty ())
4803          error ("unexpected exception while parsing input");
4804        else
4805          error ("unexpected exception while parsing %s", file.c_str ());
4806      }
4807
4808    if (status != 0)
4809      parse_error ("%s", m_parse_error_msg.c_str ());
4810
4811    return status;
4812  }
4813
4814  // Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
4815  // finish the parse.
4816
4817  int
4818  push_parser::run (const std::string& input, bool eof)
4819  {
4820    int status = -1;
4821
4822    dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);
4823
4824    do
4825      {
4826        YYSTYPE lval;
4827
4828        int token = octave_lex (&lval, m_lexer.m_scanner);
4829
4830        if (token < 0)
4831          {
4832            // TOKEN == -2 means that the lexer recognized a comment
4833            // and we should be at the end of the buffer but not the
4834            // end of the file so we should return 0 to indicate
4835            // "complete input" instead of -1 to request more input.
4836
4837            status = (token == -2 ? 0 : -1);
4838
4839            if (! eof && m_lexer.at_end_of_buffer ())
4840              return status;
4841
4842            break;
4843          }
4844
4845        yypstate *pstate = static_cast<yypstate *> (m_parser_state);
4846
4847        try
4848          {
4849            status = octave_push_parse (pstate, token, &lval, *this);
4850          }
4851        catch (execution_exception& e)
4852          {
4853            std::string file = m_lexer.m_fcn_file_full_name;
4854
4855            if (file.empty ())
4856              error (e, "parse error");
4857            else
4858              error (e, "parse error in %s", file.c_str ());
4859          }
4860        catch (const exit_exception&)
4861          {
4862            throw;
4863          }
4864        catch (interrupt_exception &)
4865          {
4866            throw;
4867          }
4868        catch (...)
4869          {
4870            std::string file = m_lexer.m_fcn_file_full_name;
4871
4872            if (file.empty ())
4873              error ("unexpected exception while parsing input");
4874            else
4875              error ("unexpected exception while parsing %s", file.c_str ());
4876          }
4877      }
4878    while (status == YYPUSH_MORE || ! m_lexer.at_end_of_buffer ());
4879
4880    if (status != 0)
4881      parse_error ("%s", m_parse_error_msg.c_str ());
4882
4883    return status;
4884  }
4885
4886  int
4887  push_parser::run (void)
4888  {
4889    if (! m_reader)
4890      error ("push_parser::run requires valid input_reader");
4891
4892    int exit_status = 0;
4893
4894    input_system&  input_sys = m_interpreter.get_input_system ();
4895
4896    std::string prompt
4897      = command_editor::decode_prompt_string (input_sys.PS1 ());
4898
4899    do
4900      {
4901        // Reset status each time through the read loop so that
4902        // it won't be set to -1 and cause us to exit the outer
4903        // loop early if there is an exception while reading
4904        // input or parsing.
4905
4906        exit_status = 0;
4907
4908        bool eof = false;
4909        std::string input_line = m_reader->get_input (prompt, eof);
4910
4911        if (eof)
4912          {
4913            exit_status = EOF;
4914            break;
4915          }
4916
4917        exit_status = run (input_line, false);
4918
4919        prompt = command_editor::decode_prompt_string (input_sys.PS2 ());
4920      }
4921    while (exit_status < 0);
4922
4923    return exit_status;
4924  }
4925
4926  octave_value
4927  parse_fcn_file (interpreter& interp, const std::string& full_file,
4928                  const std::string& file, const std::string& dir_name,
4929                  const std::string& dispatch_type,
4930                  const std::string& package_name, bool require_file,
4931                  bool force_script, bool autoload, bool relative_lookup)
4932  {
4933    octave_value retval;
4934
4935    FILE *ffile = nullptr;
4936
4937    if (! full_file.empty ())
4938      ffile = sys::fopen (full_file, "rb");
4939
4940    if (! ffile)
4941      {
4942        if (require_file)
4943          error ("no such file, '%s'", full_file.c_str ());
4944
4945        return octave_value ();
4946      }
4947
4948    unwind_action act ([ffile] (void)
4949                       {
4950                         fclose (ffile);
4951                       });
4952
4953    parser parser (ffile, interp);
4954
4955    parser.m_curr_class_name = dispatch_type;
4956    parser.m_curr_package_name = package_name;
4957    parser.m_autoloading = autoload;
4958    parser.m_fcn_file_from_relative_lookup = relative_lookup;
4959
4960    parser.m_lexer.m_force_script = force_script;
4961    parser.m_lexer.prep_for_file ();
4962    parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
4963
4964    parser.m_lexer.m_fcn_file_name = file;
4965    parser.m_lexer.m_fcn_file_full_name = full_file;
4966    parser.m_lexer.m_dir_name = dir_name;
4967    parser.m_lexer.m_package_name = package_name;
4968
4969    int err = parser.run ();
4970
4971    if (err)
4972      error ("parse error while reading file %s", full_file.c_str ());
4973
4974    octave_value ov_fcn = parser.m_primary_fcn;
4975
4976    if (parser.m_lexer.m_reading_classdef_file
4977        && parser.classdef_object ())
4978      {
4979        // Convert parse tree for classdef object to
4980        // meta.class info (and stash it in the symbol
4981        // table?).  Return pointer to constructor?
4982
4983        if (ov_fcn.is_defined ())
4984          panic_impossible ();
4985
4986        bool is_at_folder = ! dispatch_type.empty ();
4987
4988        std::shared_ptr<tree_classdef> cdef_obj
4989          = parser.classdef_object();
4990
4991        return cdef_obj->make_meta_class (interp, is_at_folder);
4992      }
4993    else if (ov_fcn.is_defined ())
4994      {
4995        octave_function *fcn = ov_fcn.function_value ();
4996
4997        fcn->maybe_relocate_end ();
4998
4999        if (parser.m_parsing_subfunctions)
5000          {
5001            if (! parser.m_endfunction_found)
5002              parser.m_subfunction_names.reverse ();
5003
5004            fcn->stash_subfunction_names (parser.m_subfunction_names);
5005          }
5006
5007        return ov_fcn;
5008      }
5009
5010    return octave_value ();
5011  }
5012
5013  // Maybe print a warning if an assignment expression is used as the
5014  // test in a logical expression.
5015
5016  void
5017  base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
5018  {
5019    if (expr->is_assignment_expression ()
5020        && expr->paren_count () < 2)
5021      {
5022        if (m_lexer.m_fcn_file_full_name.empty ())
5023          warning_with_id
5024            ("Octave:assign-as-truth-value",
5025             "suggest parenthesis around assignment used as truth value");
5026        else
5027          warning_with_id
5028            ("Octave:assign-as-truth-value",
5029             "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
5030             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
5031      }
5032  }
5033
5034  // Maybe print a warning about switch labels that aren't constants.
5035
5036  void
5037  base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
5038  {
5039    if (! expr->is_constant ())
5040      {
5041        if (m_lexer.m_fcn_file_full_name.empty ())
5042          warning_with_id ("Octave:variable-switch-label",
5043                           "variable switch label");
5044        else
5045          warning_with_id
5046            ("Octave:variable-switch-label",
5047             "variable switch label near line %d, column %d in file '%s'",
5048             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
5049      }
5050  }
5051
5052  void
5053  base_parser::maybe_warn_missing_semi (tree_statement_list *t)
5054  {
5055    if (m_curr_fcn_depth >= 0)
5056      {
5057        tree_statement *tmp = t->back ();
5058
5059        if (tmp->is_expression ())
5060          warning_with_id
5061            ("Octave:missing-semicolon",
5062             "missing semicolon near line %d, column %d in file '%s'",
5063             tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());
5064      }
5065  }
5066
5067  std::string
5068  get_help_from_file (const std::string& nm, bool& symbol_found,
5069                      std::string& full_file)
5070  {
5071    std::string retval;
5072
5073    full_file = fcn_file_in_path (nm);
5074
5075    std::string file = full_file;
5076
5077    std::size_t file_len = file.length ();
5078
5079    if ((file_len > 4 && file.substr (file_len-4) == ".oct")
5080        || (file_len > 4 && file.substr (file_len-4) == ".mex")
5081        || (file_len > 2 && file.substr (file_len-2) == ".m"))
5082      {
5083        file = sys::env::base_pathname (file);
5084        file = file.substr (0, file.find_last_of ('.'));
5085
5086        std::size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());
5087        if (pos != std::string::npos)
5088          file = file.substr (pos+1);
5089      }
5090
5091    if (! file.empty ())
5092      {
5093        interpreter& interp = __get_interpreter__ ("get_help_from_file");
5094
5095        symbol_found = true;
5096
5097        octave_value ov_fcn
5098          = parse_fcn_file (interp, full_file, file, "", "", "", true,
5099                            false, false, false);
5100
5101        if (ov_fcn.is_defined ())
5102          {
5103            octave_function *fcn = ov_fcn.function_value ();
5104
5105            if (fcn)
5106              retval = fcn->doc_string ();
5107          }
5108      }
5109
5110    return retval;
5111  }
5112
5113  std::string
5114  get_help_from_file (const std::string& nm, bool& symbol_found)
5115  {
5116    std::string file;
5117    return get_help_from_file (nm, symbol_found, file);
5118  }
5119
5120  octave_value
5121  load_fcn_from_file (const std::string& file_name,
5122                      const std::string& dir_name,
5123                      const std::string& dispatch_type,
5124                      const std::string& package_name,
5125                      const std::string& fcn_name, bool autoload)
5126  {
5127    octave_value retval;
5128
5129    unwind_protect frame;
5130
5131    std::string nm = file_name;
5132
5133    std::size_t nm_len = nm.length ();
5134
5135    std::string file;
5136
5137    bool relative_lookup = false;
5138
5139    file = nm;
5140
5141    if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
5142        || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
5143        || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
5144      {
5145        nm = sys::env::base_pathname (file);
5146        nm = nm.substr (0, nm.find_last_of ('.'));
5147
5148        std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());
5149        if (pos != std::string::npos)
5150          nm = nm.substr (pos+1);
5151      }
5152
5153    relative_lookup = ! sys::env::absolute_pathname (file);
5154
5155    file = sys::env::make_absolute (file);
5156
5157    int len = file.length ();
5158
5159    interpreter& interp = __get_interpreter__ ("load_fcn_from_file");
5160
5161    dynamic_loader& dyn_loader = interp.get_dynamic_loader ();
5162
5163    if (len > 4 && file.substr (len-4, len-1) == ".oct")
5164      {
5165        if (autoload && ! fcn_name.empty ())
5166          nm = fcn_name;
5167
5168        octave_function *tmpfcn
5169          = dyn_loader.load_oct (nm, file, relative_lookup);
5170
5171        if (tmpfcn)
5172          {
5173            tmpfcn->stash_package_name (package_name);
5174            retval = octave_value (tmpfcn);
5175          }
5176      }
5177    else if (len > 4 && file.substr (len-4, len-1) == ".mex")
5178      {
5179        // Temporarily load m-file version of mex-file, if it exists,
5180        // to get the help-string to use.
5181
5182        std::string doc_string;
5183
5184        octave_value ov_fcn
5185          = parse_fcn_file (interp, file.substr (0, len - 2), nm, dir_name,
5186                            dispatch_type, package_name, false,
5187                            autoload, autoload, relative_lookup);
5188
5189        if (ov_fcn.is_defined ())
5190          {
5191            octave_function *tmpfcn = ov_fcn.function_value ();
5192
5193            if (tmpfcn)
5194              doc_string = tmpfcn->doc_string ();
5195          }
5196
5197        octave_function *tmpfcn
5198          = dyn_loader.load_mex (nm, file, relative_lookup);
5199
5200        if (tmpfcn)
5201          {
5202            tmpfcn->document (doc_string);
5203            tmpfcn->stash_package_name (package_name);
5204
5205            retval = octave_value (tmpfcn);
5206          }
5207      }
5208    else if (len > 2)
5209      {
5210        retval = parse_fcn_file (interp, file, nm, dir_name,
5211                                 dispatch_type, package_name, true,
5212                                 autoload, autoload, relative_lookup);
5213      }
5214
5215    return retval;
5216  }
5217}
5218
5219DEFMETHOD (autoload, interp, args, ,
5220           doc: /* -*- texinfo -*-
5221@deftypefn  {} {@var{autoload_map} =} autoload ()
5222@deftypefnx {} {} autoload (@var{function}, @var{file})
5223@deftypefnx {} {} autoload (@dots{}, "remove")
5224Define @var{function} to autoload from @var{file}.
5225
5226The second argument, @var{file}, should be an absolute filename or a file
5227name in the same directory as the function or script from which the autoload
5228command was run.  @var{file} @emph{should not} depend on the Octave load
5229path.
5230
5231Normally, calls to @code{autoload} appear in PKG_ADD script files that are
5232evaluated when a directory is added to Octave's load path.  To avoid having
5233to hardcode directory names in @var{file}, if @var{file} is in the same
5234directory as the PKG_ADD script then
5235
5236@example
5237autoload ("foo", "bar.oct");
5238@end example
5239
5240@noindent
5241will load the function @code{foo} from the file @code{bar.oct}.  The above
5242usage when @code{bar.oct} is not in the same directory, or usages such as
5243
5244@example
5245autoload ("foo", file_in_loadpath ("bar.oct"))
5246@end example
5247
5248@noindent
5249are strongly discouraged, as their behavior may be unpredictable.
5250
5251With no arguments, return a structure containing the current autoload map.
5252
5253If a third argument @qcode{"remove"} is given, the function is cleared and
5254not loaded anymore during the current Octave session.
5255
5256@seealso{PKG_ADD}
5257@end deftypefn */)
5258{
5259  int nargin = args.length ();
5260
5261  if (nargin == 1 || nargin > 3)
5262    print_usage ();
5263
5264  octave::tree_evaluator& tw = interp.get_evaluator ();
5265
5266  if (nargin == 0)
5267    return octave_value (tw.get_autoload_map ());
5268  else
5269    {
5270      string_vector argv = args.make_argv ("autoload");
5271
5272      if (nargin == 2)
5273        tw.add_autoload (argv[1], argv[2]);
5274      else if (nargin == 3)
5275        {
5276          if (argv[3] != "remove")
5277            error_with_id ("Octave:invalid-input-arg",
5278                           "autoload: third argument can only be 'remove'");
5279
5280          tw.remove_autoload (argv[1], argv[2]);
5281        }
5282    }
5283
5284  return octave_value_list ();
5285}
5286
5287DEFMETHOD (mfilename, interp, args, ,
5288           doc: /* -*- texinfo -*-
5289@deftypefn  {} {} mfilename ()
5290@deftypefnx {} {} mfilename ("fullpath")
5291@deftypefnx {} {} mfilename ("fullpathext")
5292Return the name of the currently executing file.
5293
5294The base name of the currently executing script or function is returned without
5295any extension.  If called from outside an m-file, such as the command line,
5296return the empty string.
5297
5298Given the argument @qcode{"fullpath"}, include the directory part of the
5299filename, but not the extension.
5300
5301Given the argument @qcode{"fullpathext"}, include the directory part of
5302the filename and the extension.
5303@seealso{inputname, dbstack}
5304@end deftypefn */)
5305{
5306  int nargin = args.length ();
5307
5308  if (nargin > 1)
5309    print_usage ();
5310
5311  std::string opt;
5312
5313  if (nargin == 1)
5314    opt = args(0).xstring_value ("mfilename: option argument must be a string");
5315
5316  return octave_value (interp.mfilename (opt));
5317}
5318
5319namespace octave
5320{
5321  // Execute the contents of a script file.  For compatibility with
5322  // Matlab, also execute a function file by calling the function it
5323  // defines with no arguments and nargout = 0.
5324
5325  void
5326  source_file (const std::string& file_name, const std::string& context,
5327               bool verbose, bool require_file)
5328  {
5329    interpreter& interp = __get_interpreter__ ("source_file");
5330
5331    interp.source_file (file_name, context, verbose, require_file);
5332  }
5333}
5334
5335DEFMETHOD (source, interp, args, ,
5336           doc: /* -*- texinfo -*-
5337@deftypefn  {} {} source (@var{file})
5338@deftypefnx {} {} source (@var{file}, @var{context})
5339Parse and execute the contents of @var{file}.
5340
5341Without specifying @var{context}, this is equivalent to executing commands
5342from a script file, but without requiring the file to be named
5343@file{@var{file}.m} or to be on the execution path.
5344
5345Instead of the current context, the script may be executed in either the
5346context of the function that called the present function
5347(@qcode{"caller"}), or the top-level context (@qcode{"base"}).
5348@seealso{run}
5349@end deftypefn */)
5350{
5351  int nargin = args.length ();
5352
5353  if (nargin < 1 || nargin > 2)
5354    print_usage ();
5355
5356  std::string file_name
5357    = args(0).xstring_value ("source: FILE must be a string");
5358
5359  std::string context;
5360  if (nargin == 2)
5361    context = args(1).xstring_value ("source: CONTEXT must be a string");
5362
5363  interp.source_file (file_name, context);
5364
5365  return octave_value_list ();
5366}
5367
5368namespace octave
5369{
5370  //! Evaluate an Octave function (built-in or interpreted) and return
5371  //! the list of result values.
5372  //!
5373  //! @param name The name of the function to call.
5374  //! @param args The arguments to the function.
5375  //! @param nargout The number of output arguments expected.
5376  //! @return A list of output values.  The length of the list is not
5377  //!         necessarily the same as @c nargout.
5378
5379  octave_value_list
5380  feval (const char *name, const octave_value_list& args, int nargout)
5381  {
5382    interpreter& interp = __get_interpreter__ ("feval");
5383
5384    return interp.feval (name, args, nargout);
5385  }
5386
5387  octave_value_list
5388  feval (const std::string& name, const octave_value_list& args, int nargout)
5389  {
5390    interpreter& interp = __get_interpreter__ ("feval");
5391
5392    return interp.feval (name, args, nargout);
5393  }
5394
5395  octave_value_list
5396  feval (octave_function *fcn, const octave_value_list& args, int nargout)
5397  {
5398    interpreter& interp = __get_interpreter__ ("feval");
5399
5400    return interp.feval (fcn, args, nargout);
5401  }
5402
5403  octave_value_list
5404  feval (const octave_value& val, const octave_value_list& args, int nargout)
5405  {
5406    interpreter& interp = __get_interpreter__ ("feval");
5407
5408    return interp.feval (val, args, nargout);
5409  }
5410
5411  octave_value_list
5412  feval (const octave_value_list& args, int nargout)
5413  {
5414    interpreter& interp = __get_interpreter__ ("feval");
5415
5416    return interp.feval (args, nargout);
5417  }
5418}
5419
5420DEFMETHOD (feval, interp, args, nargout,
5421           doc: /* -*- texinfo -*-
5422@deftypefn {} {} feval (@var{name}, @dots{})
5423Evaluate the function named @var{name}.
5424
5425Any arguments after the first are passed as inputs to the named function.
5426For example,
5427
5428@example
5429@group
5430feval ("acos", -1)
5431     @result{} 3.1416
5432@end group
5433@end example
5434
5435@noindent
5436calls the function @code{acos} with the argument @samp{-1}.
5437
5438The function @code{feval} can also be used with function handles of any sort
5439(@pxref{Function Handles}).  Historically, @code{feval} was the only way to
5440call user-supplied functions in strings, but function handles are now
5441preferred due to the cleaner syntax they offer.  For example,
5442
5443@example
5444@group
5445@var{f} = @@exp;
5446feval (@var{f}, 1)
5447    @result{} 2.7183
5448@var{f} (1)
5449    @result{} 2.7183
5450@end group
5451@end example
5452
5453@noindent
5454are equivalent ways to call the function referred to by @var{f}.  If it
5455cannot be predicted beforehand whether @var{f} is a function handle,
5456function name in a string, or inline function then @code{feval} can be used
5457instead.
5458@end deftypefn */)
5459{
5460  if (args.length () == 0)
5461    print_usage ();
5462
5463  return interp.feval (args, nargout);
5464}
5465
5466DEFMETHOD (builtin, interp, args, nargout,
5467           doc: /* -*- texinfo -*-
5468@deftypefn {} {[@dots{}] =} builtin (@var{f}, @dots{})
5469Call the base function @var{f} even if @var{f} is overloaded to another
5470function for the given type signature.
5471
5472This is normally useful when doing object-oriented programming and there is
5473a requirement to call one of Octave's base functions rather than the
5474overloaded one of a new class.
5475
5476A trivial example which redefines the @code{sin} function to be the
5477@code{cos} function shows how @code{builtin} works.
5478
5479@example
5480@group
5481sin (0)
5482  @result{} 0
5483function y = sin (x), y = cos (x); endfunction
5484sin (0)
5485  @result{} 1
5486builtin ("sin", 0)
5487  @result{} 0
5488@end group
5489@end example
5490@end deftypefn */)
5491{
5492  octave_value_list retval;
5493
5494  if (args.length () == 0)
5495    print_usage ();
5496
5497  const std::string name (args(0).xstring_value ("builtin: function name (F) must be a string"));
5498
5499  octave::symbol_table& symtab = interp.get_symbol_table ();
5500
5501  octave_value fcn = symtab.builtin_find (name);
5502
5503  if (fcn.is_defined ())
5504    retval = interp.feval (fcn.function_value (), args.splice (0, 1), nargout);
5505  else
5506    error ("builtin: lookup for symbol '%s' failed", name.c_str ());
5507
5508  return retval;
5509}
5510
5511namespace octave
5512{
5513  octave_value_list
5514  eval_string (const std::string& eval_str, bool silent,
5515               int& parse_status, int nargout)
5516  {
5517    interpreter& interp = __get_interpreter__ ("eval_string");
5518
5519    return interp.eval_string (eval_str, silent, parse_status, nargout);
5520  }
5521
5522  octave_value
5523  eval_string (const std::string& eval_str, bool silent, int& parse_status)
5524  {
5525    interpreter& interp = __get_interpreter__ ("eval_string");
5526
5527    return interp.eval_string (eval_str, silent, parse_status);
5528  }
5529
5530  void
5531  cleanup_statement_list (tree_statement_list **lst)
5532  {
5533    if (*lst)
5534      {
5535        delete *lst;
5536        *lst = nullptr;
5537      }
5538  }
5539}
5540
5541DEFMETHOD (eval, interp, args, nargout,
5542           doc: /* -*- texinfo -*-
5543@deftypefn  {} {} eval (@var{try})
5544@deftypefnx {} {} eval (@var{try}, @var{catch})
5545Parse the string @var{try} and evaluate it as if it were an Octave
5546program.
5547
5548If execution fails, evaluate the optional string @var{catch}.
5549
5550The string @var{try} is evaluated in the current context, so any results
5551remain available after @code{eval} returns.
5552
5553The following example creates the variable @var{A} with the approximate
5554value of 3.1416 in the current workspace.
5555
5556@example
5557eval ("A = acos(-1);");
5558@end example
5559
5560If an error occurs during the evaluation of @var{try} then the @var{catch}
5561string is evaluated, as the following example shows:
5562
5563@example
5564@group
5565eval ('error ("This is a bad example");',
5566      'printf ("This error occurred:\n%s\n", lasterr ());');
5567     @print{} This error occurred:
5568        This is a bad example
5569@end group
5570@end example
5571
5572Programming Note: if you are only using @code{eval} as an error-capturing
5573mechanism, rather than for the execution of arbitrary code strings,
5574Consider using try/catch blocks or unwind_protect/unwind_protect_cleanup
5575blocks instead.  These techniques have higher performance and don't
5576introduce the security considerations that the evaluation of arbitrary code
5577does.
5578@seealso{evalin, evalc, assignin, feval}
5579@end deftypefn */)
5580{
5581  int nargin = args.length ();
5582
5583  if (nargin < 1 || nargin > 2)
5584    print_usage ();
5585
5586  if (! args(0).is_string () || args(0).rows () > 1 || args(0).ndims () != 2)
5587    error ("eval: TRY must be a string");
5588
5589  std::string try_code = args(0).string_value ();
5590
5591  if (nargin == 1)
5592    return interp.eval (try_code, nargout);
5593  else
5594    {
5595      if (! args(1).is_string () || args(1).rows () > 1
5596          || args(1).ndims () != 2)
5597        error ("eval: CATCH must be a string");
5598
5599      std::string catch_code = args(1).string_value ();
5600
5601      return interp.eval (try_code, catch_code, nargout);
5602    }
5603}
5604
5605/*
5606
5607%!shared x
5608%! x = 1;
5609
5610%!assert (eval ("x"), 1)
5611%!assert (eval ("x;"))
5612%!assert (eval ("x;"), 1)
5613
5614%!test
5615%! y = eval ("x");
5616%! assert (y, 1);
5617
5618%!test
5619%! y = eval ("x;");
5620%! assert (y, 1);
5621
5622%!test
5623%! eval ("x = 1;");
5624%! assert (x,1);
5625
5626%!test
5627%! eval ("flipud = 2;");
5628%! assert (flipud, 2);
5629
5630%!function y = __f ()
5631%!  eval ("flipud = 2;");
5632%!  y = flipud;
5633%!endfunction
5634%!assert (__f(), 2)
5635
5636%!test <*35645>
5637%! [a,] = gcd (1,2);
5638%! [a,b,] = gcd (1, 2);
5639
5640## Can't assign to a keyword
5641%!error eval ("switch = 13;")
5642
5643%!shared str
5644%! str = "disp ('hello');";
5645%! str(:,:,2) = str(:,:,1);
5646
5647%!error <TRY must be a string> eval (1)
5648%!error <TRY must be a string> eval (['a';'b'])
5649%!error <TRY must be a string> eval (str)
5650
5651%!error <CATCH must be a string> eval (str(:,:,1), 1)
5652%!error <CATCH must be a string> eval (str(:,:,1), ['a';'b'])
5653%!error <CATCH must be a string> eval (str(:,:,1), str)
5654
5655*/
5656
5657DEFMETHOD (assignin, interp, args, ,
5658           doc: /* -*- texinfo -*-
5659@deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})
5660Assign @var{value} to @var{varname} in context @var{context}, which
5661may be either @qcode{"base"} or @qcode{"caller"}.
5662@seealso{evalin}
5663@end deftypefn */)
5664{
5665  if (args.length () != 3)
5666    print_usage ();
5667
5668  std::string context
5669    = args(0).xstring_value ("assignin: CONTEXT must be a string");
5670
5671  std::string varname
5672    = args(1).xstring_value ("assignin: VARNAME must be a string");
5673
5674  interp.assignin (context, varname, args(2));
5675
5676  return octave_value_list ();
5677}
5678
5679/*
5680
5681%!error assignin ("base", "switch", "13")
5682
5683*/
5684
5685DEFMETHOD (evalin, interp, args, nargout,
5686           doc: /* -*- texinfo -*-
5687@deftypefn  {} {} evalin (@var{context}, @var{try})
5688@deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})
5689Like @code{eval}, except that the expressions are evaluated in the context
5690@var{context}, which may be either @qcode{"caller"} or @qcode{"base"}.
5691@seealso{eval, assignin}
5692@end deftypefn */)
5693{
5694  int nargin = args.length ();
5695
5696  if (nargin < 2 || nargin > 3)
5697    print_usage ();
5698
5699  std::string context
5700    = args(0).xstring_value ("evalin: CONTEXT must be a string");
5701
5702  std::string try_code
5703    = args(1).xstring_value ("evalin: TRY must be a string");
5704
5705  if (nargin == 3)
5706    {
5707      std::string catch_code
5708        = args(2).xstring_value ("evalin: CATCH must be a string");
5709
5710      return interp.evalin (context, try_code, catch_code, nargout);
5711    }
5712
5713  return interp.evalin (context, try_code, nargout);
5714}
5715
5716DEFMETHOD (evalc, interp, args, nargout,
5717           doc: /* -*- texinfo -*-
5718@deftypefn  {} {@var{s} =} evalc (@var{try})
5719@deftypefnx {} {@var{s} =} evalc (@var{try}, @var{catch})
5720Parse and evaluate the string @var{try} as if it were an Octave program,
5721while capturing the output into the return variable @var{s}.
5722
5723If execution fails, evaluate the optional string @var{catch}.
5724
5725This function behaves like @code{eval}, but any output or warning messages
5726which would normally be written to the console are captured and returned in
5727the string @var{s}.
5728
5729The @code{diary} is disabled during the execution of this function.  When
5730@code{system} is used, any output produced by external programs is
5731@emph{not} captured, unless their output is captured by the @code{system}
5732function itself.
5733
5734@example
5735@group
5736s = evalc ("t = 42"), t
5737  @result{} s = t =  42
5738
5739  @result{} t =  42
5740@end group
5741@end example
5742@seealso{eval, diary}
5743@end deftypefn */)
5744{
5745  int nargin = args.length ();
5746
5747  if (nargin == 0 || nargin > 2)
5748    print_usage ();
5749
5750  // Flush pending output and redirect stdout/stderr to capturing
5751  // buffer.
5752
5753  octave_stdout.flush ();
5754  std::cerr.flush ();
5755
5756  std::stringbuf buffer;
5757
5758  std::streambuf *old_out_buf = octave_stdout.rdbuf (&buffer);
5759  std::streambuf *old_err_buf = std::cerr.rdbuf (&buffer);
5760
5761  // Restore previous output buffers no matter how control exits this
5762  // function.  There's no need to flush here.  That has already
5763  // happened for the normal execution path.  If an error happens during
5764  // the eval, then the message is stored in the exception object and we
5765  // will display it later, after the buffers have been restored.
5766
5767  octave::unwind_action act ([old_out_buf, old_err_buf] (void)
5768                             {
5769                               octave_stdout.rdbuf (old_out_buf);
5770                               std::cerr.rdbuf (old_err_buf);
5771                             });
5772
5773  // Call standard eval function.
5774
5775  int eval_nargout = std::max (0, nargout - 1);
5776
5777  octave_value_list retval = Feval (interp, args, eval_nargout);
5778
5779  // Make sure we capture all pending output.
5780
5781  octave_stdout.flush ();
5782  std::cerr.flush ();
5783
5784  retval.prepend (buffer.str ());
5785
5786  return retval;
5787}
5788
5789/*
5790
5791%!test
5792%! [old_fmt, old_spacing] = format ();
5793%! unwind_protect
5794%!   format short;
5795%!   str = evalc ("1");
5796%!   assert (str, "ans = 1\n");
5797%! unwind_protect_cleanup
5798%!   format (old_fmt);
5799%!   format (old_spacing);
5800%! end_unwind_protect
5801
5802%!assert (evalc ("1;"), "")
5803
5804%!test
5805%! [s, y] = evalc ("1");
5806%! assert (s, "");
5807%! assert (y, 1);
5808
5809%!test
5810%! [s, y] = evalc ("1;");
5811%! assert (s, "");
5812%! assert (y, 1);
5813
5814%!test
5815%! [old_fmt, old_spacing] = format ();
5816%! unwind_protect
5817%!   format short;
5818%!   str = evalc ("y = 2");
5819%!   assert (str, "y = 2\n");
5820%!   assert (y, 2);
5821%! unwind_protect_cleanup
5822%!   format (old_fmt);
5823%!   format (old_spacing);
5824%! end_unwind_protect
5825
5826%!test
5827%! assert (evalc ("y = 3;"), "");
5828%! assert (y, 3);
5829
5830%!test
5831%! [s, a, b] = evalc ("deal (1, 2)");
5832%! assert (s, "");
5833%! assert (a, 1);
5834%! assert (b, 2);
5835
5836%!function [a, b] = __f_evalc ()
5837%!  printf ("foo");
5838%!  fprintf (stdout, "bar ");
5839%!  disp (pi);
5840%!  a = 1;
5841%!  b = 2;
5842%!endfunction
5843%!test
5844%! [old_fmt, old_spacing] = format ();
5845%! unwind_protect
5846%!   format short;
5847%!   [s, a, b] = evalc ("__f_evalc ()");
5848%!   assert (s, "foobar 3.1416\n");
5849%!   assert (a, 1);
5850%!   assert (b, 2);
5851%! unwind_protect_cleanup
5852%!   format (old_fmt);
5853%!   format (old_spacing);
5854%! end_unwind_protect
5855
5856%!error <foo> (evalc ("error ('foo')"))
5857%!error <bar> (evalc ("error ('foo')", "error ('bar')"))
5858
5859%!test
5860%! warning ("off", "quiet", "local");
5861%! str = evalc ("warning ('foo')");
5862%! assert (str(1:13), "warning: foo\n");
5863
5864%!test
5865%! warning ("off", "quiet", "local");
5866%! str = evalc ("error ('foo')", "warning ('bar')");
5867%! assert (str(1:13), "warning: bar\n");
5868
5869%!error evalc ("switch = 13;")
5870
5871*/
5872
5873DEFUN (__parser_debug_flag__, args, nargout,
5874       doc: /* -*- texinfo -*-
5875@deftypefn  {} {@var{val} =} __parser_debug_flag__ ()
5876@deftypefnx {} {@var{old_val} =} __parser_debug_flag__ (@var{new_val})
5877Query or set the internal flag that determines whether Octave's parser
5878prints debug information as it processes an expression.
5879@seealso{__lexer_debug_flag__}
5880@end deftypefn */)
5881{
5882  octave_value retval;
5883
5884  bool debug_flag = octave_debug;
5885
5886  retval = set_internal_variable (debug_flag, args, nargout,
5887                                  "__parser_debug_flag__");
5888
5889  octave_debug = debug_flag;
5890
5891  return retval;
5892}
5893
5894DEFMETHOD (__parse_file__, interp, args, ,
5895           doc: /* -*- texinfo -*-
5896@deftypefn {} {} __parse_file__ (@var{file}, @var{verbose})
5897Undocumented internal function.
5898@end deftypefn */)
5899{
5900  octave_value retval;
5901
5902  int nargin = args.length ();
5903
5904  if (nargin < 1 || nargin > 2)
5905    print_usage ();
5906
5907  std::string file = args(0).xstring_value ("__parse_file__: expecting filename as argument");
5908
5909  std::string full_file
5910      = octave::sys::file_ops::tilde_expand (file);
5911
5912  full_file = octave::sys::env::make_absolute (full_file);
5913
5914  std::string dir_name;
5915
5916  std::size_t file_len = file.length ();
5917
5918  if ((file_len > 4 && file.substr (file_len-4) == ".oct")
5919      || (file_len > 4 && file.substr (file_len-4) == ".mex")
5920      || (file_len > 2 && file.substr (file_len-2) == ".m"))
5921    {
5922      file = octave::sys::env::base_pathname (file);
5923      file = file.substr (0, file.find_last_of ('.'));
5924
5925      std::size_t pos = file.find_last_of (octave::sys::file_ops::dir_sep_str ());
5926      if (pos != std::string::npos)
5927        {
5928          dir_name = file.substr (0, pos);
5929          file = file.substr (pos+1);
5930        }
5931    }
5932
5933  if (nargin == 2)
5934    octave_stdout << "parsing " << full_file << std::endl;
5935
5936  octave_value ov_fcn
5937    = parse_fcn_file (interp, full_file, file, dir_name, "", "", true,
5938                      false, false, false);
5939
5940  return retval;
5941}
5942