comparison src/oct-parse.yy @ 9794:0d4613a736e9

convert build system to use automake and libtool
author John W. Eaton <jwe@octave.org>
date Tue, 10 Nov 2009 15:02:25 -0500
parents src/parse.y@5f8971be8e12
children 6f79338c269b
comparison
equal deleted inserted replaced
9793:7161e9b41cf6 9794:0d4613a736e9
1 /*
2
3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5 Copyright (C) 2009 David Grundberg
6
7 This file is part of Octave.
8
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22
23 */
24
25 // Parser for Octave.
26
27 // C decarations.
28
29 %{
30 #define YYDEBUG 1
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <cassert>
37 #include <cstdio>
38
39 #ifdef YYBYACC
40 #include <cstdlib>
41 #endif
42
43 #include <iostream>
44 #include <map>
45 #include <sstream>
46
47 #include "Cell.h"
48 #include "Matrix.h"
49 #include "cmd-edit.h"
50 #include "cmd-hist.h"
51 #include "file-ops.h"
52 #include "file-stat.h"
53 #include "oct-env.h"
54 #include "oct-time.h"
55 #include "quit.h"
56
57 #include "comment-list.h"
58 #include "defaults.h"
59 #include "defun.h"
60 #include "dirfns.h"
61 #include "dynamic-ld.h"
62 #include "error.h"
63 #include "input.h"
64 #include "lex.h"
65 #include "load-path.h"
66 #include "oct-hist.h"
67 #include "oct-map.h"
68 #include "ov-fcn-handle.h"
69 #include "ov-usr-fcn.h"
70 #include "ov-null-mat.h"
71 #include "toplev.h"
72 #include "pager.h"
73 #include "parse.h"
74 #include "pt-all.h"
75 #include "pt-eval.h"
76 #include "symtab.h"
77 #include "token.h"
78 #include "unwind-prot.h"
79 #include "utils.h"
80 #include "variables.h"
81
82 // The current input line number.
83 int input_line_number = 1;
84
85 // The column of the current token.
86 int current_input_column = 1;
87
88 // Buffer for help text snagged from function files.
89 std::stack<std::string> help_buf;
90
91 // Buffer for comments appearing before a function statement.
92 static std::string fcn_comment_header;
93
94 // TRUE means we are using readline.
95 // (--no-line-editing)
96 bool line_editing = true;
97
98 // TRUE means we printed messages about reading startup files.
99 bool reading_startup_message_printed = false;
100
101 // TRUE means input is coming from startup file.
102 bool input_from_startup_file = false;
103
104 // = 0 currently outside any function.
105 // = 1 inside the primary function or a subfunction.
106 // > 1 means we are looking at a function definition that seems to be
107 // inside a function. Note that the function still might not be a
108 // nested function.
109 static int current_function_depth = 0;
110
111 // Maximum function depth detected. Just here to determine whether
112 // we have nested functions or just implicitly ended subfunctions.
113 static int max_function_depth = 0;
114
115 // FALSE if we are still at the primary function. Subfunctions can
116 // only be declared inside function files.
117 static int parsing_subfunctions = false;
118
119 // Have we found an explicit end to a function?
120 static bool endfunction_found = false;
121
122 // Keep track of symbol table information when parsing functions.
123 std::stack<symbol_table::scope_id> symtab_context;
124
125 // Name of the current class when we are parsing class methods or
126 // constructors.
127 std::string current_class_name;
128
129 // TRUE means we are in the process of autoloading a function.
130 static bool autoloading = false;
131
132 // TRUE means the current function file was found in a relative path
133 // element.
134 static bool fcn_file_from_relative_lookup = false;
135
136 // Pointer to the primary user function or user script function.
137 static octave_function *primary_fcn_ptr = 0;
138
139 // Scope where we install all subfunctions and nested functions. Only
140 // used while reading function files.
141 static symbol_table::scope_id primary_fcn_scope;
142
143 // List of autoloads (function -> file mapping).
144 static std::map<std::string, std::string> autoload_map;
145
146 // Forward declarations for some functions defined at the bottom of
147 // the file.
148
149 // Generic error messages.
150 static void
151 yyerror (const char *s);
152
153 // Error mesages for mismatched end tokens.
154 static void
155 end_error (const char *type, token::end_tok_type ettype, int l, int c);
156
157 // Check to see that end tokens are properly matched.
158 static bool
159 end_token_ok (token *tok, token::end_tok_type expected);
160
161 // Maybe print a warning if an assignment expression is used as the
162 // test in a logical expression.
163 static void
164 maybe_warn_assign_as_truth_value (tree_expression *expr);
165
166 // Maybe print a warning about switch labels that aren't constants.
167 static void
168 maybe_warn_variable_switch_label (tree_expression *expr);
169
170 // Finish building a range.
171 static tree_expression *
172 finish_colon_expression (tree_colon_expression *e);
173
174 // Build a constant.
175 static tree_constant *
176 make_constant (int op, token *tok_val);
177
178 // Build a function handle.
179 static tree_fcn_handle *
180 make_fcn_handle (token *tok_val);
181
182 // Build an anonymous function handle.
183 static tree_anon_fcn_handle *
184 make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
185
186 // Build a binary expression.
187 static tree_expression *
188 make_binary_op (int op, tree_expression *op1, token *tok_val,
189 tree_expression *op2);
190
191 // Build a boolean expression.
192 static tree_expression *
193 make_boolean_op (int op, tree_expression *op1, token *tok_val,
194 tree_expression *op2);
195
196 // Build a prefix expression.
197 static tree_expression *
198 make_prefix_op (int op, tree_expression *op1, token *tok_val);
199
200 // Build a postfix expression.
201 static tree_expression *
202 make_postfix_op (int op, tree_expression *op1, token *tok_val);
203
204 // Build an unwind-protect command.
205 static tree_command *
206 make_unwind_command (token *unwind_tok, tree_statement_list *body,
207 tree_statement_list *cleanup, token *end_tok,
208 octave_comment_list *lc, octave_comment_list *mc);
209
210 // Build a try-catch command.
211 static tree_command *
212 make_try_command (token *try_tok, tree_statement_list *body,
213 tree_statement_list *cleanup, token *end_tok,
214 octave_comment_list *lc, octave_comment_list *mc);
215
216 // Build a while command.
217 static tree_command *
218 make_while_command (token *while_tok, tree_expression *expr,
219 tree_statement_list *body, token *end_tok,
220 octave_comment_list *lc);
221
222 // Build a do-until command.
223 static tree_command *
224 make_do_until_command (token *until_tok, tree_statement_list *body,
225 tree_expression *expr, octave_comment_list *lc);
226
227 // Build a for command.
228 static tree_command *
229 make_for_command (token *for_tok, tree_argument_list *lhs,
230 tree_expression *expr, tree_statement_list *body,
231 token *end_tok, octave_comment_list *lc);
232
233 // Build a break command.
234 static tree_command *
235 make_break_command (token *break_tok);
236
237 // Build a continue command.
238 static tree_command *
239 make_continue_command (token *continue_tok);
240
241 // Build a return command.
242 static tree_command *
243 make_return_command (token *return_tok);
244
245 // Start an if command.
246 static tree_if_command_list *
247 start_if_command (tree_expression *expr, tree_statement_list *list);
248
249 // Finish an if command.
250 static tree_if_command *
251 finish_if_command (token *if_tok, tree_if_command_list *list,
252 token *end_tok, octave_comment_list *lc);
253
254 // Build an elseif clause.
255 static tree_if_clause *
256 make_elseif_clause (token *elseif_tok, tree_expression *expr,
257 tree_statement_list *list, octave_comment_list *lc);
258
259 // Finish a switch command.
260 static tree_switch_command *
261 finish_switch_command (token *switch_tok, tree_expression *expr,
262 tree_switch_case_list *list, token *end_tok,
263 octave_comment_list *lc);
264
265 // Build a switch case.
266 static tree_switch_case *
267 make_switch_case (token *case_tok, tree_expression *expr,
268 tree_statement_list *list, octave_comment_list *lc);
269
270 // Build an assignment to a variable.
271 static tree_expression *
272 make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
273 tree_expression *rhs);
274
275 // Define a script.
276 static void
277 make_script (tree_statement_list *cmds, tree_statement *end_script);
278
279 // Begin defining a function.
280 static octave_user_function *
281 start_function (tree_parameter_list *param_list, tree_statement_list *body,
282 tree_statement *end_function);
283
284 // Create a no-op statement for end_function.
285 static tree_statement *
286 make_end (const std::string& type, int l, int c);
287
288 // Do most of the work for defining a function.
289 static octave_user_function *
290 frob_function (const std::string& fname, octave_user_function *fcn);
291
292 // Finish defining a function.
293 static tree_function_def *
294 finish_function (tree_parameter_list *ret_list,
295 octave_user_function *fcn, octave_comment_list *lc);
296
297 // Reset state after parsing function.
298 static void
299 recover_from_parsing_function (void);
300
301 // Make an index expression.
302 static tree_index_expression *
303 make_index_expression (tree_expression *expr,
304 tree_argument_list *args, char type);
305
306 // Make an indirect reference expression.
307 static tree_index_expression *
308 make_indirect_ref (tree_expression *expr, const std::string&);
309
310 // Make an indirect reference expression with dynamic field name.
311 static tree_index_expression *
312 make_indirect_ref (tree_expression *expr, tree_expression *field);
313
314 // Make a declaration command.
315 static tree_decl_command *
316 make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
317
318 // Finish building a matrix list.
319 static tree_expression *
320 finish_matrix (tree_matrix *m);
321
322 // Finish building a cell list.
323 static tree_expression *
324 finish_cell (tree_cell *c);
325
326 // Maybe print a warning. Duh.
327 static void
328 maybe_warn_missing_semi (tree_statement_list *);
329
330 // Set the print flag for a statement based on the separator type.
331 static tree_statement_list *
332 set_stmt_print_flag (tree_statement_list *, char, bool);
333
334 // Create a statement list.
335 static tree_statement_list *make_statement_list (tree_statement *stmt);
336
337 // Append a statement to an existing statement list.
338 static tree_statement_list *
339 append_statement_list (tree_statement_list *list, char sep,
340 tree_statement *stmt, bool warn_missing_semi);
341
342 // Finish building a statement.
343 template <class T>
344 static tree_statement *
345 make_statement (T *arg)
346 {
347 octave_comment_list *comment = octave_comment_buffer::get_comment ();
348
349 return new tree_statement (arg, comment);
350 }
351
352 #define ABORT_PARSE \
353 do \
354 { \
355 global_command = 0; \
356 yyerrok; \
357 if (! symtab_context.empty ()) \
358 { \
359 symbol_table::set_scope (symtab_context.top ()); \
360 symtab_context.pop (); \
361 } \
362 if (interactive || forced_interactive) \
363 YYACCEPT; \
364 else \
365 YYABORT; \
366 } \
367 while (0)
368
369 %}
370
371 // Bison declarations.
372
373 // Don't add spaces around the = here; it causes some versions of
374 // bison to fail to properly recognize the directive.
375
376 %name-prefix="octave_"
377
378 %union
379 {
380 // The type of the basic tokens returned by the lexer.
381 token *tok_val;
382
383 // Comment strings that we need to deal with mid-rule.
384 octave_comment_list *comment_type;
385
386 // Types for the nonterminals we generate.
387 char sep_type;
388 tree *tree_type;
389 tree_matrix *tree_matrix_type;
390 tree_cell *tree_cell_type;
391 tree_expression *tree_expression_type;
392 tree_constant *tree_constant_type;
393 tree_fcn_handle *tree_fcn_handle_type;
394 tree_anon_fcn_handle *tree_anon_fcn_handle_type;
395 tree_identifier *tree_identifier_type;
396 tree_index_expression *tree_index_expression_type;
397 tree_colon_expression *tree_colon_expression_type;
398 tree_argument_list *tree_argument_list_type;
399 tree_parameter_list *tree_parameter_list_type;
400 tree_command *tree_command_type;
401 tree_if_command *tree_if_command_type;
402 tree_if_clause *tree_if_clause_type;
403 tree_if_command_list *tree_if_command_list_type;
404 tree_switch_command *tree_switch_command_type;
405 tree_switch_case *tree_switch_case_type;
406 tree_switch_case_list *tree_switch_case_list_type;
407 tree_decl_elt *tree_decl_elt_type;
408 tree_decl_init_list *tree_decl_init_list_type;
409 tree_decl_command *tree_decl_command_type;
410 tree_statement *tree_statement_type;
411 tree_statement_list *tree_statement_list_type;
412 octave_user_function *octave_user_function_type;
413 void *dummy_type;
414 }
415
416 // Tokens with line and column information.
417 %token <tok_val> '=' ':' '-' '+' '*' '/'
418 %token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
419 %token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
420 %token <tok_val> LSHIFT_EQ RSHIFT_EQ LSHIFT RSHIFT
421 %token <tok_val> EXPR_AND_AND EXPR_OR_OR
422 %token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
423 %token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
424 %token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
425 %token <tok_val> QUOTE TRANSPOSE
426 %token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
427 %token <tok_val> NUM IMAG_NUM
428 %token <tok_val> STRUCT_ELT
429 %token <tok_val> NAME
430 %token <tok_val> END
431 %token <tok_val> DQ_STRING SQ_STRING
432 %token <tok_val> FOR WHILE DO UNTIL
433 %token <tok_val> IF ELSEIF ELSE
434 %token <tok_val> SWITCH CASE OTHERWISE
435 %token <tok_val> BREAK CONTINUE FUNC_RET
436 %token <tok_val> UNWIND CLEANUP
437 %token <tok_val> TRY CATCH
438 %token <tok_val> GLOBAL STATIC
439 %token <tok_val> FCN_HANDLE
440 %token <tok_val> PROPERTIES
441 %token <tok_val> METHODS
442 %token <tok_val> EVENTS
443 %token <tok_val> METAQUERY
444 %token <tok_val> SUPERCLASSREF
445 %token <tok_val> GET SET
446
447 // Other tokens.
448 %token END_OF_INPUT LEXICAL_ERROR
449 %token FCN SCRIPT_FILE FUNCTION_FILE CLASSDEF
450 // %token VARARGIN VARARGOUT
451 %token CLOSE_BRACE
452
453 // Nonterminals we construct.
454 %type <comment_type> stash_comment function_beg classdef_beg
455 %type <comment_type> properties_beg methods_beg events_beg
456 %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep
457 %type <tree_type> input
458 %type <tree_constant_type> string constant magic_colon
459 %type <tree_anon_fcn_handle_type> anon_fcn_handle
460 %type <tree_fcn_handle_type> fcn_handle
461 %type <tree_matrix_type> matrix_rows matrix_rows1
462 %type <tree_cell_type> cell_rows cell_rows1
463 %type <tree_expression_type> matrix cell
464 %type <tree_expression_type> primary_expr postfix_expr prefix_expr binary_expr
465 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
466 %type <tree_identifier_type> identifier fcn_name
467 %type <tree_identifier_type> superclass_identifier meta_identifier
468 %type <octave_user_function_type> function1 function2 classdef1
469 %type <tree_index_expression_type> word_list_cmd
470 %type <tree_colon_expression_type> colon_expr1
471 %type <tree_argument_list_type> arg_list word_list assign_lhs
472 %type <tree_argument_list_type> cell_or_matrix_row
473 %type <tree_parameter_list_type> param_list param_list1 param_list2
474 %type <tree_parameter_list_type> return_list return_list1
475 %type <tree_parameter_list_type> superclasses opt_superclasses
476 %type <tree_command_type> command select_command loop_command
477 %type <tree_command_type> jump_command except_command function
478 %type <tree_command_type> script_file classdef
479 %type <tree_command_type> function_file function_list
480 %type <tree_if_command_type> if_command
481 %type <tree_if_clause_type> elseif_clause else_clause
482 %type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
483 %type <tree_switch_command_type> switch_command
484 %type <tree_switch_case_type> switch_case default_case
485 %type <tree_switch_case_list_type> case_list1 case_list
486 %type <tree_decl_elt_type> decl2
487 %type <tree_decl_init_list_type> decl1
488 %type <tree_decl_command_type> declaration
489 %type <tree_statement_type> statement function_end classdef_end
490 %type <tree_statement_list_type> simple_list simple_list1 list list1
491 %type <tree_statement_list_type> opt_list input1
492 // These types need to be specified.
493 %type <dummy_type> attr
494 %type <dummy_type> class_event
495 %type <dummy_type> class_property
496 %type <dummy_type> properties_list
497 %type <dummy_type> properties_block
498 %type <dummy_type> methods_list
499 %type <dummy_type> methods_block
500 %type <dummy_type> opt_attr_list
501 %type <dummy_type> attr_list
502 %type <dummy_type> events_list
503 %type <dummy_type> events_block
504 %type <dummy_type> class_body
505
506 // Precedence and associativity.
507 %left ';' ',' '\n'
508 %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 LSHIFT_EQ RSHIFT_EQ
509 %left EXPR_OR_OR
510 %left EXPR_AND_AND
511 %left EXPR_OR
512 %left EXPR_AND
513 %left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
514 %left LSHIFT RSHIFT
515 %left ':'
516 %left '-' '+' EPLUS EMINUS
517 %left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
518 %left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT
519 %left POW EPOW QUOTE TRANSPOSE
520 %left '(' '.' '{'
521
522 // Where to start.
523 %start input
524
525 %%
526
527 // ==============================
528 // Statements and statement lists
529 // ==============================
530
531 input : input1
532 {
533 global_command = $1;
534 promptflag = 1;
535 YYACCEPT;
536 }
537 | function_file
538 {
539 YYACCEPT;
540 }
541 | simple_list parse_error
542 { ABORT_PARSE; }
543 | parse_error
544 { ABORT_PARSE; }
545 ;
546
547 input1 : '\n'
548 { $$ = 0; }
549 | END_OF_INPUT
550 {
551 parser_end_of_input = 1;
552 $$ = 0;
553 }
554 | simple_list
555 { $$ = $1; }
556 | simple_list '\n'
557 { $$ = $1; }
558 | simple_list END_OF_INPUT
559 { $$ = $1; }
560 ;
561
562 simple_list : simple_list1 opt_sep_no_nl
563 { $$ = set_stmt_print_flag ($1, $2, false); }
564 ;
565
566 simple_list1 : statement
567 { $$ = make_statement_list ($1); }
568 | simple_list1 sep_no_nl statement
569 { $$ = append_statement_list ($1, $2, $3, false); }
570 ;
571
572 opt_list : // empty
573 { $$ = new tree_statement_list (); }
574 | list
575 { $$ = $1; }
576 ;
577
578 list : list1 opt_sep
579 { $$ = set_stmt_print_flag ($1, $2, true); }
580 ;
581
582 list1 : statement
583 { $$ = make_statement_list ($1); }
584 | list1 sep statement
585 { $$ = append_statement_list ($1, $2, $3, true); }
586 ;
587
588 statement : expression
589 { $$ = make_statement ($1); }
590 | command
591 { $$ = make_statement ($1); }
592 | word_list_cmd
593 { $$ = make_statement ($1); }
594 ;
595
596 // =================
597 // Word-list command
598 // =================
599
600 // These are not really like expressions since they can't appear on
601 // the RHS of an assignment. But they are also not like commands (IF,
602 // WHILE, etc.
603
604 word_list_cmd : identifier word_list
605 { $$ = make_index_expression ($1, $2, '('); }
606 ;
607
608 word_list : string
609 { $$ = new tree_argument_list ($1); }
610 | word_list string
611 {
612 $1->append ($2);
613 $$ = $1;
614 }
615 ;
616
617 // ===========
618 // Expressions
619 // ===========
620
621 identifier : NAME
622 {
623 symbol_table::symbol_record *sr = $1->sym_rec ();
624 $$ = new tree_identifier (*sr, $1->line (), $1->column ());
625 }
626 ;
627
628 superclass_identifier
629 : SUPERCLASSREF
630 { $$ = new tree_identifier ($1->line (), $1->column ()); }
631 ;
632
633 meta_identifier : METAQUERY
634 { $$ = new tree_identifier ($1->line (), $1->column ()); }
635 ;
636
637 string : DQ_STRING
638 { $$ = make_constant (DQ_STRING, $1); }
639 | SQ_STRING
640 { $$ = make_constant (SQ_STRING, $1); }
641 ;
642
643 constant : NUM
644 { $$ = make_constant (NUM, $1); }
645 | IMAG_NUM
646 { $$ = make_constant (IMAG_NUM, $1); }
647 | string
648 { $$ = $1; }
649 ;
650
651 matrix : '[' ']'
652 {
653 $$ = new tree_constant (octave_null_matrix::instance);
654 lexer_flags.looking_at_matrix_or_assign_lhs = false;
655 lexer_flags.pending_local_variables.clear ();
656 }
657 | '[' ';' ']'
658 {
659 $$ = new tree_constant (octave_null_matrix::instance);
660 lexer_flags.looking_at_matrix_or_assign_lhs = false;
661 lexer_flags.pending_local_variables.clear ();
662 }
663 | '[' ',' ']'
664 {
665 $$ = new tree_constant (octave_null_matrix::instance);
666 lexer_flags.looking_at_matrix_or_assign_lhs = false;
667 lexer_flags.pending_local_variables.clear ();
668 }
669 | '[' matrix_rows ']'
670 {
671 $$ = finish_matrix ($2);
672 lexer_flags.looking_at_matrix_or_assign_lhs = false;
673 lexer_flags.pending_local_variables.clear ();
674 }
675 ;
676
677 matrix_rows : matrix_rows1
678 { $$ = $1; }
679 | matrix_rows1 ';' // Ignore trailing semicolon.
680 { $$ = $1; }
681 ;
682
683 matrix_rows1 : cell_or_matrix_row
684 { $$ = new tree_matrix ($1); }
685 | matrix_rows1 ';' cell_or_matrix_row
686 {
687 $1->append ($3);
688 $$ = $1;
689 }
690 ;
691
692 cell : '{' '}'
693 { $$ = new tree_constant (octave_value (Cell ())); }
694 | '{' ';' '}'
695 { $$ = new tree_constant (octave_value (Cell ())); }
696 | '{' cell_rows '}'
697 { $$ = finish_cell ($2); }
698 ;
699
700 cell_rows : cell_rows1
701 { $$ = $1; }
702 | cell_rows1 ';' // Ignore trailing semicolon.
703 { $$ = $1; }
704 ;
705
706 cell_rows1 : cell_or_matrix_row
707 { $$ = new tree_cell ($1); }
708 | cell_rows1 ';' cell_or_matrix_row
709 {
710 $1->append ($3);
711 $$ = $1;
712 }
713 ;
714
715 cell_or_matrix_row
716 : arg_list
717 { $$ = $1; }
718 | arg_list ',' // Ignore trailing comma.
719 { $$ = $1; }
720 ;
721
722 fcn_handle : '@' FCN_HANDLE
723 {
724 $$ = make_fcn_handle ($2);
725 lexer_flags.looking_at_function_handle--;
726 }
727 ;
728
729 anon_fcn_handle : '@' param_list statement
730 { $$ = make_anon_fcn_handle ($2, $3); }
731 ;
732
733 primary_expr : identifier
734 { $$ = $1; }
735 | constant
736 { $$ = $1; }
737 | fcn_handle
738 { $$ = $1; }
739 | matrix
740 { $$ = $1; }
741 | cell
742 { $$ = $1; }
743 | meta_identifier
744 { $$ = $1; }
745 | superclass_identifier
746 { $$ = $1; }
747 | '(' expression ')'
748 { $$ = $2->mark_in_parens (); }
749 ;
750
751 magic_colon : ':'
752 {
753 octave_value tmp (octave_value::magic_colon_t);
754 $$ = new tree_constant (tmp);
755 }
756 ;
757
758 arg_list : expression
759 { $$ = new tree_argument_list ($1); }
760 | magic_colon
761 { $$ = new tree_argument_list ($1); }
762 | arg_list ',' magic_colon
763 {
764 $1->append ($3);
765 $$ = $1;
766 }
767 | arg_list ',' expression
768 {
769 $1->append ($3);
770 $$ = $1;
771 }
772 ;
773
774 indirect_ref_op : '.'
775 { lexer_flags.looking_at_indirect_ref = true; }
776 ;
777
778 postfix_expr : primary_expr
779 { $$ = $1; }
780 | postfix_expr '(' ')'
781 { $$ = make_index_expression ($1, 0, '('); }
782 | postfix_expr '(' arg_list ')'
783 { $$ = make_index_expression ($1, $3, '('); }
784 | postfix_expr '{' '}'
785 { $$ = make_index_expression ($1, 0, '{'); }
786 | postfix_expr '{' arg_list '}'
787 { $$ = make_index_expression ($1, $3, '{'); }
788 | postfix_expr PLUS_PLUS
789 { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
790 | postfix_expr MINUS_MINUS
791 { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
792 | postfix_expr QUOTE
793 { $$ = make_postfix_op (QUOTE, $1, $2); }
794 | postfix_expr TRANSPOSE
795 { $$ = make_postfix_op (TRANSPOSE, $1, $2); }
796 | postfix_expr indirect_ref_op STRUCT_ELT
797 { $$ = make_indirect_ref ($1, $3->text ()); }
798 | postfix_expr indirect_ref_op '(' expression ')'
799 { $$ = make_indirect_ref ($1, $4); }
800 ;
801
802 prefix_expr : postfix_expr
803 { $$ = $1; }
804 | binary_expr
805 { $$ = $1; }
806 | PLUS_PLUS prefix_expr %prec UNARY
807 { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
808 | MINUS_MINUS prefix_expr %prec UNARY
809 { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
810 | EXPR_NOT prefix_expr %prec UNARY
811 { $$ = make_prefix_op (EXPR_NOT, $2, $1); }
812 | '+' prefix_expr %prec UNARY
813 { $$ = make_prefix_op ('+', $2, $1); }
814 | '-' prefix_expr %prec UNARY
815 { $$ = make_prefix_op ('-', $2, $1); }
816 ;
817
818 binary_expr : prefix_expr POW prefix_expr
819 { $$ = make_binary_op (POW, $1, $2, $3); }
820 | prefix_expr EPOW prefix_expr
821 { $$ = make_binary_op (EPOW, $1, $2, $3); }
822 | prefix_expr '+' prefix_expr
823 { $$ = make_binary_op ('+', $1, $2, $3); }
824 | prefix_expr '-' prefix_expr
825 { $$ = make_binary_op ('-', $1, $2, $3); }
826 | prefix_expr '*' prefix_expr
827 { $$ = make_binary_op ('*', $1, $2, $3); }
828 | prefix_expr '/' prefix_expr
829 { $$ = make_binary_op ('/', $1, $2, $3); }
830 | prefix_expr EPLUS prefix_expr
831 { $$ = make_binary_op ('+', $1, $2, $3); }
832 | prefix_expr EMINUS prefix_expr
833 { $$ = make_binary_op ('-', $1, $2, $3); }
834 | prefix_expr EMUL prefix_expr
835 { $$ = make_binary_op (EMUL, $1, $2, $3); }
836 | prefix_expr EDIV prefix_expr
837 { $$ = make_binary_op (EDIV, $1, $2, $3); }
838 | prefix_expr LEFTDIV prefix_expr
839 { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
840 | prefix_expr ELEFTDIV prefix_expr
841 { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
842 ;
843
844 colon_expr : colon_expr1
845 { $$ = finish_colon_expression ($1); }
846 ;
847
848 colon_expr1 : prefix_expr
849 { $$ = new tree_colon_expression ($1); }
850 | colon_expr1 ':' prefix_expr
851 {
852 if (! ($$ = $1->append ($3)))
853 ABORT_PARSE;
854 }
855 ;
856
857 simple_expr : colon_expr
858 { $$ = $1; }
859 | simple_expr LSHIFT simple_expr
860 { $$ = make_binary_op (LSHIFT, $1, $2, $3); }
861 | simple_expr RSHIFT simple_expr
862 { $$ = make_binary_op (RSHIFT, $1, $2, $3); }
863 | simple_expr EXPR_LT simple_expr
864 { $$ = make_binary_op (EXPR_LT, $1, $2, $3); }
865 | simple_expr EXPR_LE simple_expr
866 { $$ = make_binary_op (EXPR_LE, $1, $2, $3); }
867 | simple_expr EXPR_EQ simple_expr
868 { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); }
869 | simple_expr EXPR_GE simple_expr
870 { $$ = make_binary_op (EXPR_GE, $1, $2, $3); }
871 | simple_expr EXPR_GT simple_expr
872 { $$ = make_binary_op (EXPR_GT, $1, $2, $3); }
873 | simple_expr EXPR_NE simple_expr
874 { $$ = make_binary_op (EXPR_NE, $1, $2, $3); }
875 | simple_expr EXPR_AND simple_expr
876 { $$ = make_binary_op (EXPR_AND, $1, $2, $3); }
877 | simple_expr EXPR_OR simple_expr
878 { $$ = make_binary_op (EXPR_OR, $1, $2, $3); }
879 | simple_expr EXPR_AND_AND simple_expr
880 { $$ = make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
881 | simple_expr EXPR_OR_OR simple_expr
882 { $$ = make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
883 ;
884
885 // Arrange for the lexer to return CLOSE_BRACE for `]' by looking ahead
886 // one token for an assignment op.
887
888 assign_lhs : simple_expr
889 {
890 $$ = new tree_argument_list ($1);
891 $$->mark_as_simple_assign_lhs ();
892 }
893 | '[' arg_list CLOSE_BRACE
894 {
895 $$ = $2;
896 lexer_flags.looking_at_matrix_or_assign_lhs = false;
897 for (std::set<std::string>::const_iterator p = lexer_flags.pending_local_variables.begin ();
898 p != lexer_flags.pending_local_variables.end ();
899 p++)
900 {
901 symbol_table::force_variable (*p);
902 }
903 lexer_flags.pending_local_variables.clear ();
904 }
905 ;
906
907 assign_expr : assign_lhs '=' expression
908 { $$ = make_assign_op ('=', $1, $2, $3); }
909 | assign_lhs ADD_EQ expression
910 { $$ = make_assign_op (ADD_EQ, $1, $2, $3); }
911 | assign_lhs SUB_EQ expression
912 { $$ = make_assign_op (SUB_EQ, $1, $2, $3); }
913 | assign_lhs MUL_EQ expression
914 { $$ = make_assign_op (MUL_EQ, $1, $2, $3); }
915 | assign_lhs DIV_EQ expression
916 { $$ = make_assign_op (DIV_EQ, $1, $2, $3); }
917 | assign_lhs LEFTDIV_EQ expression
918 { $$ = make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
919 | assign_lhs POW_EQ expression
920 { $$ = make_assign_op (POW_EQ, $1, $2, $3); }
921 | assign_lhs LSHIFT_EQ expression
922 { $$ = make_assign_op (LSHIFT_EQ, $1, $2, $3); }
923 | assign_lhs RSHIFT_EQ expression
924 { $$ = make_assign_op (RSHIFT_EQ, $1, $2, $3); }
925 | assign_lhs EMUL_EQ expression
926 { $$ = make_assign_op (EMUL_EQ, $1, $2, $3); }
927 | assign_lhs EDIV_EQ expression
928 { $$ = make_assign_op (EDIV_EQ, $1, $2, $3); }
929 | assign_lhs ELEFTDIV_EQ expression
930 { $$ = make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
931 | assign_lhs EPOW_EQ expression
932 { $$ = make_assign_op (EPOW_EQ, $1, $2, $3); }
933 | assign_lhs AND_EQ expression
934 { $$ = make_assign_op (AND_EQ, $1, $2, $3); }
935 | assign_lhs OR_EQ expression
936 { $$ = make_assign_op (OR_EQ, $1, $2, $3); }
937 ;
938
939 expression : simple_expr
940 { $$ = $1; }
941 | assign_expr
942 { $$ = $1; }
943 | anon_fcn_handle
944 { $$ = $1; }
945 ;
946
947 // ================================================
948 // Commands, declarations, and function definitions
949 // ================================================
950
951 command : declaration
952 { $$ = $1; }
953 | select_command
954 { $$ = $1; }
955 | loop_command
956 { $$ = $1; }
957 | jump_command
958 { $$ = $1; }
959 | except_command
960 { $$ = $1; }
961 | function
962 { $$ = $1; }
963 | script_file
964 { $$ = $1; }
965 | classdef
966 { $$ = $1; }
967 ;
968
969 // =====================
970 // Declaration statemnts
971 // =====================
972
973 parsing_decl_list
974 : // empty
975 { lexer_flags.looking_at_decl_list = true; }
976
977 declaration : GLOBAL parsing_decl_list decl1
978 {
979 $$ = make_decl_command (GLOBAL, $1, $3);
980 lexer_flags.looking_at_decl_list = false;
981 }
982 | STATIC parsing_decl_list decl1
983 {
984 $$ = make_decl_command (STATIC, $1, $3);
985 lexer_flags.looking_at_decl_list = false;
986 }
987 ;
988
989 decl1 : decl2
990 { $$ = new tree_decl_init_list ($1); }
991 | decl1 decl2
992 {
993 $1->append ($2);
994 $$ = $1;
995 }
996 ;
997
998 decl_param_init : // empty
999 { lexer_flags.looking_at_initializer_expression = true; }
1000
1001 decl2 : identifier
1002 { $$ = new tree_decl_elt ($1); }
1003 | identifier '=' decl_param_init expression
1004 {
1005 lexer_flags.looking_at_initializer_expression = false;
1006 $$ = new tree_decl_elt ($1, $4);
1007 }
1008 ;
1009
1010 // ====================
1011 // Selection statements
1012 // ====================
1013
1014 select_command : if_command
1015 { $$ = $1; }
1016 | switch_command
1017 { $$ = $1; }
1018 ;
1019
1020 // ============
1021 // If statement
1022 // ============
1023
1024 if_command : IF stash_comment if_cmd_list END
1025 {
1026 if (! ($$ = finish_if_command ($1, $3, $4, $2)))
1027 ABORT_PARSE;
1028 }
1029 ;
1030
1031 if_cmd_list : if_cmd_list1
1032 { $$ = $1; }
1033 | if_cmd_list1 else_clause
1034 {
1035 $1->append ($2);
1036 $$ = $1;
1037 }
1038 ;
1039
1040 if_cmd_list1 : expression opt_sep opt_list
1041 { $$ = start_if_command ($1, $3); }
1042 | if_cmd_list1 elseif_clause
1043 {
1044 $1->append ($2);
1045 $$ = $1;
1046 }
1047 ;
1048
1049 elseif_clause : ELSEIF stash_comment opt_sep expression opt_sep opt_list
1050 { $$ = make_elseif_clause ($1, $4, $6, $2); }
1051 ;
1052
1053 else_clause : ELSE stash_comment opt_sep opt_list
1054 { $$ = new tree_if_clause ($4, $2); }
1055 ;
1056
1057 // ================
1058 // Switch statement
1059 // ================
1060
1061 switch_command : SWITCH stash_comment expression opt_sep case_list END
1062 {
1063 if (! ($$ = finish_switch_command ($1, $3, $5, $6, $2)))
1064 ABORT_PARSE;
1065 }
1066 ;
1067
1068 case_list : // empty
1069 { $$ = new tree_switch_case_list (); }
1070 | case_list1
1071 { $$ = $1; }
1072 | case_list1 default_case
1073 {
1074 $1->append ($2);
1075 $$ = $1;
1076 }
1077 ;
1078
1079 case_list1 : switch_case
1080 { $$ = new tree_switch_case_list ($1); }
1081 | case_list1 switch_case
1082 {
1083 $1->append ($2);
1084 $$ = $1;
1085 }
1086 ;
1087
1088 switch_case : CASE stash_comment opt_sep expression opt_sep opt_list
1089 { $$ = make_switch_case ($1, $4, $6, $2); }
1090 ;
1091
1092 default_case : OTHERWISE stash_comment opt_sep opt_list
1093 {
1094 $$ = new tree_switch_case ($4, $2);
1095 }
1096 ;
1097
1098 // =======
1099 // Looping
1100 // =======
1101
1102 loop_command : WHILE stash_comment expression opt_sep opt_list END
1103 {
1104 if (! ($$ = make_while_command ($1, $3, $5, $6, $2)))
1105 ABORT_PARSE;
1106 }
1107 | DO stash_comment opt_sep opt_list UNTIL expression
1108 {
1109 if (! ($$ = make_do_until_command ($5, $4, $6, $2)))
1110 ABORT_PARSE;
1111 }
1112 | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END
1113 {
1114 if (! ($$ = make_for_command ($1, $3, $5, $7, $8, $2)))
1115 ABORT_PARSE;
1116 }
1117 | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
1118 {
1119 if (! ($$ = make_for_command ($1, $4, $6, $9, $10, $2)))
1120 ABORT_PARSE;
1121 }
1122 ;
1123
1124 // =======
1125 // Jumping
1126 // =======
1127
1128 jump_command : BREAK
1129 {
1130 if (! ($$ = make_break_command ($1)))
1131 ABORT_PARSE;
1132 }
1133 | CONTINUE
1134 {
1135 if (! ($$ = make_continue_command ($1)))
1136 ABORT_PARSE;
1137 }
1138 | FUNC_RET
1139 {
1140 if (! ($$ = make_return_command ($1)))
1141 ABORT_PARSE;
1142 }
1143 ;
1144
1145 // ==========
1146 // Exceptions
1147 // ==========
1148
1149 except_command : UNWIND stash_comment opt_sep opt_list CLEANUP
1150 stash_comment opt_sep opt_list END
1151 {
1152 if (! ($$ = make_unwind_command ($1, $4, $8, $9, $2, $6)))
1153 ABORT_PARSE;
1154 }
1155 | TRY stash_comment opt_sep opt_list CATCH
1156 stash_comment opt_sep opt_list END
1157 {
1158 if (! ($$ = make_try_command ($1, $4, $8, $9, $2, $6)))
1159 ABORT_PARSE;
1160 }
1161 | TRY stash_comment opt_sep opt_list END
1162 {
1163 if (! ($$ = make_try_command ($1, $4, 0, $5, $2, 0)))
1164 ABORT_PARSE;
1165 }
1166 ;
1167
1168 // ===========================================
1169 // Some `subroutines' for function definitions
1170 // ===========================================
1171
1172 push_fcn_symtab : // empty
1173 {
1174 current_function_depth++;
1175
1176 if (max_function_depth < current_function_depth)
1177 max_function_depth = current_function_depth;
1178
1179 symtab_context.push (symbol_table::current_scope ());
1180 symbol_table::set_scope (symbol_table::alloc_scope ());
1181
1182 if (! reading_script_file && current_function_depth == 1
1183 && ! parsing_subfunctions)
1184 primary_fcn_scope = symbol_table::current_scope ();
1185
1186 if (reading_script_file && current_function_depth > 1)
1187 yyerror ("nested functions not implemented in this context");
1188 }
1189 ;
1190
1191 // ===========================
1192 // List of function parameters
1193 // ===========================
1194
1195 param_list_beg : '('
1196 {
1197 lexer_flags.looking_at_parameter_list = true;
1198
1199 if (lexer_flags.looking_at_function_handle)
1200 {
1201 symtab_context.push (symbol_table::current_scope ());
1202 symbol_table::set_scope (symbol_table::alloc_scope ());
1203 lexer_flags.looking_at_function_handle--;
1204 }
1205 }
1206 ;
1207
1208 param_list_end : ')'
1209 {
1210 lexer_flags.looking_at_parameter_list = false;
1211 lexer_flags.looking_for_object_index = false;
1212 }
1213 ;
1214
1215 param_list : param_list_beg param_list1 param_list_end
1216 {
1217 lexer_flags.quote_is_transpose = false;
1218 $$ = $2;
1219 }
1220 | param_list_beg error
1221 {
1222 yyerror ("invalid parameter list");
1223 $$ = 0;
1224 ABORT_PARSE;
1225 }
1226 ;
1227
1228 param_list1 : // empty
1229 { $$ = 0; }
1230 | param_list2
1231 {
1232 $1->mark_as_formal_parameters ();
1233 if ($1->validate (tree_parameter_list::in))
1234 $$ = $1;
1235 else
1236 ABORT_PARSE;
1237 }
1238 ;
1239
1240 param_list2 : decl2
1241 { $$ = new tree_parameter_list ($1); }
1242 | param_list2 ',' decl2
1243 {
1244 $1->append ($3);
1245 $$ = $1;
1246 }
1247 ;
1248
1249 // ===================================
1250 // List of function return value names
1251 // ===================================
1252
1253 return_list : '[' ']'
1254 {
1255 lexer_flags.looking_at_return_list = false;
1256 $$ = new tree_parameter_list ();
1257 }
1258 | return_list1
1259 {
1260 lexer_flags.looking_at_return_list = false;
1261 if ($1->validate (tree_parameter_list::out))
1262 $$ = $1;
1263 else
1264 ABORT_PARSE;
1265 }
1266 | '[' return_list1 ']'
1267 {
1268 lexer_flags.looking_at_return_list = false;
1269 if ($2->validate (tree_parameter_list::out))
1270 $$ = $2;
1271 else
1272 ABORT_PARSE;
1273 }
1274 ;
1275
1276 return_list1 : identifier
1277 { $$ = new tree_parameter_list (new tree_decl_elt ($1)); }
1278 | return_list1 ',' identifier
1279 {
1280 $1->append (new tree_decl_elt ($3));
1281 $$ = $1;
1282 }
1283 ;
1284
1285 // ===========
1286 // Script file
1287 // ===========
1288
1289 script_file : SCRIPT_FILE opt_list END_OF_INPUT
1290 {
1291 tree_statement *end_of_script
1292 = make_end ("endscript", input_line_number,
1293 current_input_column);
1294
1295 make_script ($2, end_of_script);
1296
1297 $$ = 0;
1298 }
1299 ;
1300
1301 // =============
1302 // Function file
1303 // =============
1304
1305 function_file : FUNCTION_FILE function_list opt_sep END_OF_INPUT
1306 { $$ = 0; }
1307 ;
1308
1309 function_list : function
1310 | function_list sep function
1311 ;
1312
1313 // ===================
1314 // Function definition
1315 // ===================
1316
1317 function_beg : push_fcn_symtab FCN stash_comment
1318 {
1319 $$ = $3;
1320
1321 if (reading_classdef_file || lexer_flags.parsing_classdef)
1322 lexer_flags.maybe_classdef_get_set_method = true;
1323 }
1324 ;
1325
1326 function : function_beg function1
1327 {
1328 $$ = finish_function (0, $2, $1);
1329 recover_from_parsing_function ();
1330 }
1331 | function_beg return_list '=' function1
1332 {
1333 $$ = finish_function ($2, $4, $1);
1334 recover_from_parsing_function ();
1335 }
1336 ;
1337
1338 fcn_name : identifier
1339 {
1340 std::string id_name = $1->name ();
1341
1342 lexer_flags.parsed_function_name = true;
1343 lexer_flags.defining_func = false;
1344 lexer_flags.maybe_classdef_get_set_method = false;
1345
1346 $$ = $1;
1347 }
1348 | GET '.' identifier
1349 {
1350 lexer_flags.maybe_classdef_get_set_method = false;
1351 $$ = $3;
1352 }
1353 | SET '.' identifier
1354 {
1355 lexer_flags.maybe_classdef_get_set_method = false;
1356 $$ = $3;
1357 }
1358 ;
1359
1360 function1 : fcn_name function2
1361 {
1362 std::string fname = $1->name ();
1363
1364 delete $1;
1365
1366 if (! ($$ = frob_function (fname, $2)))
1367 ABORT_PARSE;
1368 }
1369 ;
1370
1371 function2 : param_list opt_sep opt_list function_end
1372 { $$ = start_function ($1, $3, $4); }
1373 | opt_sep opt_list function_end
1374 { $$ = start_function (0, $2, $3); }
1375 ;
1376
1377 function_end : END
1378 {
1379 endfunction_found = true;
1380 if (end_token_ok ($1, token::function_end))
1381 $$ = make_end ("endfunction", $1->line (), $1->column ());
1382 else
1383 ABORT_PARSE;
1384 }
1385 | END_OF_INPUT
1386 {
1387 // A lot of tests are based on the assumption that this is OK
1388 // if (reading_script_file)
1389 // {
1390 // yyerror ("function body open at end of script");
1391 // YYABORT;
1392 // }
1393
1394 if (endfunction_found)
1395 {
1396 yyerror ("inconsistent function endings -- "
1397 "if one function is explicitly ended, "
1398 "so must all the others");
1399 YYABORT;
1400 }
1401
1402 if (! reading_fcn_file && ! reading_script_file)
1403 {
1404 yyerror ("function body open at end of input");
1405 YYABORT;
1406 }
1407
1408 if (reading_classdef_file)
1409 {
1410 yyerror ("classdef body open at end of input");
1411 YYABORT;
1412 }
1413
1414 $$ = make_end ("endfunction", input_line_number,
1415 current_input_column);
1416 }
1417 ;
1418
1419 // ========
1420 // Classdef
1421 // ========
1422
1423 classdef_beg : CLASSDEF stash_comment
1424 {
1425 $$ = 0;
1426 lexer_flags.parsing_classdef = true;
1427 }
1428 ;
1429
1430 classdef_end : END
1431 {
1432 lexer_flags.parsing_classdef = false;
1433
1434 if (end_token_ok ($1, token::classdef_end))
1435 $$ = make_end ("endclassdef", $1->line (), $1->column ());
1436 else
1437 ABORT_PARSE;
1438 }
1439 ;
1440
1441 classdef1 : classdef_beg opt_attr_list identifier opt_superclasses
1442 { $$ = 0; }
1443 ;
1444
1445 classdef : classdef1 '\n' class_body '\n' stash_comment classdef_end
1446 { $$ = 0; }
1447 ;
1448
1449 opt_attr_list : // empty
1450 { $$ = 0; }
1451 | '(' attr_list ')'
1452 { $$ = 0; }
1453 ;
1454
1455 attr_list : attr
1456 { $$ = 0; }
1457 | attr_list ',' attr
1458 { $$ = 0; }
1459 ;
1460
1461 attr : identifier
1462 { $$ = 0; }
1463 | identifier '=' decl_param_init expression
1464 { $$ = 0; }
1465 | EXPR_NOT identifier
1466 { $$ = 0; }
1467 ;
1468
1469 opt_superclasses
1470 : // empty
1471 { $$ = 0; }
1472 | superclasses
1473 { $$ = 0; }
1474 ;
1475
1476 superclasses : EXPR_LT identifier '.' identifier
1477 { $$ = 0; }
1478 | EXPR_LT identifier
1479 { $$ = 0; }
1480 | superclasses EXPR_AND identifier '.' identifier
1481 { $$ = 0; }
1482 | superclasses EXPR_AND identifier
1483 { $$ = 0; }
1484 ;
1485
1486 class_body : properties_block
1487 { $$ = 0; }
1488 | methods_block
1489 { $$ = 0; }
1490 | events_block
1491 { $$ = 0; }
1492 | class_body '\n' properties_block
1493 { $$ = 0; }
1494 | class_body '\n' methods_block
1495 { $$ = 0; }
1496 | class_body '\n' events_block
1497 { $$ = 0; }
1498 ;
1499
1500 properties_beg : PROPERTIES stash_comment
1501 { $$ = 0; }
1502 ;
1503
1504 properties_block
1505 : properties_beg opt_attr_list '\n' properties_list '\n' END
1506 { $$ = 0; }
1507 ;
1508
1509 properties_list
1510 : class_property
1511 { $$ = 0; }
1512 | properties_list '\n' class_property
1513 { $$ = 0; }
1514 ;
1515
1516 class_property : identifier
1517 { $$ = 0; }
1518 | identifier '=' decl_param_init expression ';'
1519 { $$ = 0; }
1520 ;
1521
1522 methods_beg : METHODS stash_comment
1523 { $$ = 0; }
1524 ;
1525
1526 methods_block : methods_beg opt_attr_list '\n' methods_list '\n' END
1527 { $$ = 0; }
1528 ;
1529
1530 methods_list : function
1531 { $$ = 0; }
1532 | methods_list '\n' function
1533 { $$ = 0; }
1534 ;
1535
1536 events_beg : EVENTS stash_comment
1537 { $$ = 0; }
1538 ;
1539
1540 events_block : events_beg opt_attr_list '\n' events_list '\n' END
1541 { $$ = 0; }
1542 ;
1543
1544 events_list : class_event
1545 { $$ = 0; }
1546 | events_list '\n' class_event
1547 { $$ = 0; }
1548 ;
1549
1550 class_event : identifier
1551 { $$ = 0; }
1552 ;
1553
1554 // =============
1555 // Miscellaneous
1556 // =============
1557
1558 stash_comment : // empty
1559 { $$ = octave_comment_buffer::get_comment (); }
1560 ;
1561
1562 parse_error : LEXICAL_ERROR
1563 { yyerror ("parse error"); }
1564 | error
1565 ;
1566
1567 sep_no_nl : ','
1568 { $$ = ','; }
1569 | ';'
1570 { $$ = ';'; }
1571 | sep_no_nl ','
1572 { $$ = $1; }
1573 | sep_no_nl ';'
1574 { $$ = $1; }
1575 ;
1576
1577 opt_sep_no_nl : // empty
1578 { $$ = 0; }
1579 | sep_no_nl
1580 { $$ = $1; }
1581 ;
1582
1583 sep : ','
1584 { $$ = ','; }
1585 | ';'
1586 { $$ = ';'; }
1587 | '\n'
1588 { $$ = '\n'; }
1589 | sep ','
1590 { $$ = $1; }
1591 | sep ';'
1592 { $$ = $1; }
1593 | sep '\n'
1594 { $$ = $1; }
1595 ;
1596
1597 opt_sep : // empty
1598 { $$ = 0; }
1599 | sep
1600 { $$ = $1; }
1601 ;
1602
1603 %%
1604
1605 // Generic error messages.
1606
1607 static void
1608 yyerror (const char *s)
1609 {
1610 int err_col = current_input_column - 1;
1611
1612 std::ostringstream output_buf;
1613
1614 if (reading_fcn_file || reading_script_file || reading_classdef_file)
1615 output_buf << "parse error near line " << input_line_number
1616 << " of file " << curr_fcn_file_full_name;
1617 else
1618 output_buf << "parse error:";
1619
1620 if (s && strcmp (s, "parse error") != 0)
1621 output_buf << "\n\n " << s;
1622
1623 output_buf << "\n\n";
1624
1625 if (! current_input_line.empty ())
1626 {
1627 size_t len = current_input_line.length ();
1628
1629 if (current_input_line[len-1] == '\n')
1630 current_input_line.resize (len-1);
1631
1632 // Print the line, maybe with a pointer near the error token.
1633
1634 output_buf << ">>> " << current_input_line << "\n";
1635
1636 if (err_col == 0)
1637 err_col = len;
1638
1639 for (int i = 0; i < err_col + 3; i++)
1640 output_buf << " ";
1641
1642 output_buf << "^";
1643 }
1644
1645 output_buf << "\n";
1646
1647 std::string msg = output_buf.str ();
1648
1649 parse_error ("%s", msg.c_str ());
1650 }
1651
1652 // Error mesages for mismatched end tokens.
1653
1654 static void
1655 end_error (const char *type, token::end_tok_type ettype, int l, int c)
1656 {
1657 static const char *fmt
1658 = "`%s' command matched by `%s' near line %d column %d";
1659
1660 switch (ettype)
1661 {
1662 case token::simple_end:
1663 error (fmt, type, "end", l, c);
1664 break;
1665
1666 case token::for_end:
1667 error (fmt, type, "endfor", l, c);
1668 break;
1669
1670 case token::function_end:
1671 error (fmt, type, "endfunction", l, c);
1672 break;
1673
1674 case token::classdef_end:
1675 error (fmt, type, "endclassdef", l, c);
1676 break;
1677
1678 case token::if_end:
1679 error (fmt, type, "endif", l, c);
1680 break;
1681
1682 case token::switch_end:
1683 error (fmt, type, "endswitch", l, c);
1684 break;
1685
1686 case token::while_end:
1687 error (fmt, type, "endwhile", l, c);
1688 break;
1689
1690 case token::try_catch_end:
1691 error (fmt, type, "end_try_catch", l, c);
1692 break;
1693
1694 case token::unwind_protect_end:
1695 error (fmt, type, "end_unwind_protect", l, c);
1696 break;
1697
1698 default:
1699 panic_impossible ();
1700 break;
1701 }
1702 }
1703
1704 // Check to see that end tokens are properly matched.
1705
1706 static bool
1707 end_token_ok (token *tok, token::end_tok_type expected)
1708 {
1709 bool retval = true;
1710
1711 token::end_tok_type ettype = tok->ettype ();
1712
1713 if (ettype != expected && ettype != token::simple_end)
1714 {
1715 retval = false;
1716
1717 yyerror ("parse error");
1718
1719 int l = tok->line ();
1720 int c = tok->column ();
1721
1722 switch (expected)
1723 {
1724 case token::classdef_end:
1725 end_error ("classdef", ettype, l, c);
1726 break;
1727
1728 case token::for_end:
1729 end_error ("for", ettype, l, c);
1730 break;
1731
1732 case token::function_end:
1733 end_error ("function", ettype, l, c);
1734 break;
1735
1736 case token::if_end:
1737 end_error ("if", ettype, l, c);
1738 break;
1739
1740 case token::try_catch_end:
1741 end_error ("try", ettype, l, c);
1742 break;
1743
1744 case token::switch_end:
1745 end_error ("switch", ettype, l, c);
1746 break;
1747
1748 case token::unwind_protect_end:
1749 end_error ("unwind_protect", ettype, l, c);
1750 break;
1751
1752 case token::while_end:
1753 end_error ("while", ettype, l, c);
1754 break;
1755
1756 default:
1757 panic_impossible ();
1758 break;
1759 }
1760 }
1761
1762 return retval;
1763 }
1764
1765 // Maybe print a warning if an assignment expression is used as the
1766 // test in a logical expression.
1767
1768 static void
1769 maybe_warn_assign_as_truth_value (tree_expression *expr)
1770 {
1771 if (expr->is_assignment_expression ()
1772 && expr->paren_count () < 2)
1773 {
1774 if (curr_fcn_file_full_name.empty ())
1775 warning_with_id
1776 ("Octave:assign-as-truth-value",
1777 "suggest parenthesis around assignment used as truth value");
1778 else
1779 warning_with_id
1780 ("Octave:assign-as-truth-value",
1781 "suggest parenthesis around assignment used as truth value near line %d, column %d in file `%s'",
1782 expr->line (), expr->column (), curr_fcn_file_full_name.c_str ());
1783 }
1784 }
1785
1786 // Maybe print a warning about switch labels that aren't constants.
1787
1788 static void
1789 maybe_warn_variable_switch_label (tree_expression *expr)
1790 {
1791 if (! expr->is_constant ())
1792 {
1793 if (curr_fcn_file_full_name.empty ())
1794 warning_with_id ("Octave:variable-switch-label",
1795 "variable switch label");
1796 else
1797 warning_with_id
1798 ("Octave:variable-switch-label",
1799 "variable switch label near line %d, column %d in file `%s'",
1800 expr->line (), expr->column (), curr_fcn_file_full_name.c_str ());
1801 }
1802 }
1803
1804 static tree_expression *
1805 fold (tree_binary_expression *e)
1806 {
1807 tree_expression *retval = e;
1808
1809 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
1810
1811 unwind_protect::protect_var (error_state);
1812 unwind_protect::protect_var (warning_state);
1813
1814 unwind_protect::protect_var (discard_error_messages);
1815 unwind_protect::protect_var (discard_warning_messages);
1816
1817 discard_error_messages = true;
1818 discard_warning_messages = true;
1819
1820 tree_expression *op1 = e->lhs ();
1821 tree_expression *op2 = e->rhs ();
1822
1823 octave_value::binary_op op_type = e->op_type ();
1824
1825 if (op1->is_constant () && op2->is_constant ()
1826 && (! ((warning_enabled ("Octave:associativity-change")
1827 && (op_type == POW || op_type == EPOW))
1828 || (warning_enabled ("Octave:precedence-change")
1829 && (op_type == EXPR_OR || op_type == EXPR_OR_OR)))))
1830 {
1831 octave_value tmp = e->rvalue1 ();
1832
1833 if (! (error_state || warning_state))
1834 {
1835 tree_constant *tc_retval
1836 = new tree_constant (tmp, op1->line (), op1->column ());
1837
1838 std::ostringstream buf;
1839
1840 tree_print_code tpc (buf);
1841
1842 e->accept (tpc);
1843
1844 tc_retval->stash_original_text (buf.str ());
1845
1846 delete e;
1847
1848 retval = tc_retval;
1849 }
1850 }
1851
1852 unwind_protect::run_frame (uwp_frame);
1853
1854 return retval;
1855 }
1856
1857 static tree_expression *
1858 fold (tree_unary_expression *e)
1859 {
1860 tree_expression *retval = e;
1861
1862 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
1863
1864 unwind_protect::protect_var (error_state);
1865 unwind_protect::protect_var (warning_state);
1866
1867 unwind_protect::protect_var (discard_error_messages);
1868 unwind_protect::protect_var (discard_warning_messages);
1869
1870 discard_error_messages = true;
1871 discard_warning_messages = true;
1872
1873 tree_expression *op = e->operand ();
1874
1875 if (op->is_constant ())
1876 {
1877 octave_value tmp = e->rvalue1 ();
1878
1879 if (! (error_state || warning_state))
1880 {
1881 tree_constant *tc_retval
1882 = new tree_constant (tmp, op->line (), op->column ());
1883
1884 std::ostringstream buf;
1885
1886 tree_print_code tpc (buf);
1887
1888 e->accept (tpc);
1889
1890 tc_retval->stash_original_text (buf.str ());
1891
1892 delete e;
1893
1894 retval = tc_retval;
1895 }
1896 }
1897
1898 unwind_protect::run_frame (uwp_frame);
1899
1900 return retval;
1901 }
1902
1903 // Finish building a range.
1904
1905 static tree_expression *
1906 finish_colon_expression (tree_colon_expression *e)
1907 {
1908 tree_expression *retval = e;
1909
1910 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
1911
1912 unwind_protect::protect_var (error_state);
1913 unwind_protect::protect_var (warning_state);
1914
1915 unwind_protect::protect_var (discard_error_messages);
1916 unwind_protect::protect_var (discard_warning_messages);
1917
1918 discard_error_messages = true;
1919 discard_warning_messages = true;
1920
1921 tree_expression *base = e->base ();
1922 tree_expression *limit = e->limit ();
1923 tree_expression *incr = e->increment ();
1924
1925 if (base)
1926 {
1927 if (limit)
1928 {
1929 if (base->is_constant () && limit->is_constant ()
1930 && (! incr || (incr && incr->is_constant ())))
1931 {
1932 octave_value tmp = e->rvalue1 ();
1933
1934 if (! (error_state || warning_state))
1935 {
1936 tree_constant *tc_retval
1937 = new tree_constant (tmp, base->line (), base->column ());
1938
1939 std::ostringstream buf;
1940
1941 tree_print_code tpc (buf);
1942
1943 e->accept (tpc);
1944
1945 tc_retval->stash_original_text (buf.str ());
1946
1947 delete e;
1948
1949 retval = tc_retval;
1950 }
1951 }
1952 }
1953 else
1954 {
1955 e->preserve_base ();
1956 delete e;
1957
1958 // FIXME -- need to attempt constant folding here
1959 // too (we need a generic way to do that).
1960 retval = base;
1961 }
1962 }
1963
1964 unwind_protect::run_frame (uwp_frame);
1965
1966 return retval;
1967 }
1968
1969 // Make a constant.
1970
1971 static tree_constant *
1972 make_constant (int op, token *tok_val)
1973 {
1974 int l = tok_val->line ();
1975 int c = tok_val->column ();
1976
1977 tree_constant *retval = 0;
1978
1979 switch (op)
1980 {
1981 case NUM:
1982 {
1983 octave_value tmp (tok_val->number ());
1984 retval = new tree_constant (tmp, l, c);
1985 retval->stash_original_text (tok_val->text_rep ());
1986 }
1987 break;
1988
1989 case IMAG_NUM:
1990 {
1991 octave_value tmp (Complex (0.0, tok_val->number ()));
1992 retval = new tree_constant (tmp, l, c);
1993 retval->stash_original_text (tok_val->text_rep ());
1994 }
1995 break;
1996
1997 case DQ_STRING:
1998 case SQ_STRING:
1999 {
2000 std::string txt = tok_val->text ();
2001
2002 char delim = op == DQ_STRING ? '"' : '\'';
2003 octave_value tmp (txt, delim);
2004
2005 if (txt.empty ())
2006 {
2007 if (op == DQ_STRING)
2008 tmp = octave_null_str::instance;
2009 else
2010 tmp = octave_null_sq_str::instance;
2011 }
2012
2013 retval = new tree_constant (tmp, l, c);
2014
2015 if (op == DQ_STRING)
2016 txt = undo_string_escapes (txt);
2017
2018 // FIXME -- maybe this should also be handled by
2019 // tok_val->text_rep () for character strings?
2020 retval->stash_original_text (delim + txt + delim);
2021 }
2022 break;
2023
2024 default:
2025 panic_impossible ();
2026 break;
2027 }
2028
2029 return retval;
2030 }
2031
2032 // Make a function handle.
2033
2034 static tree_fcn_handle *
2035 make_fcn_handle (token *tok_val)
2036 {
2037 int l = tok_val->line ();
2038 int c = tok_val->column ();
2039
2040 tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
2041
2042 return retval;
2043 }
2044
2045 // Make an anonymous function handle.
2046
2047 static tree_anon_fcn_handle *
2048 make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt)
2049 {
2050 // FIXME -- need to get these from the location of the @ symbol.
2051
2052 int l = -1;
2053 int c = -1;
2054
2055 tree_parameter_list *ret_list = 0;
2056
2057 symbol_table::scope_id fcn_scope = symbol_table::current_scope ();
2058
2059 if (symtab_context.empty ())
2060 panic_impossible ();
2061
2062 symbol_table::set_scope (symtab_context.top ());
2063
2064 symtab_context.pop ();
2065
2066 stmt->set_print_flag (false);
2067
2068 tree_statement_list *body = new tree_statement_list (stmt);
2069
2070 body->mark_as_anon_function_body ();
2071
2072 tree_anon_fcn_handle *retval
2073 = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
2074
2075 return retval;
2076 }
2077
2078 static void
2079 maybe_warn_associativity_change (tree_expression *op)
2080 {
2081 if (op->paren_count () == 0 && op->is_binary_expression ())
2082 {
2083 tree_binary_expression *e
2084 = dynamic_cast<tree_binary_expression *> (op);
2085
2086 octave_value::binary_op op_type = e->op_type ();
2087
2088 if (op_type == octave_value::op_pow
2089 || op_type == octave_value::op_el_pow)
2090 {
2091 std::string op_str = octave_value::binary_op_as_string (op_type);
2092
2093 if (curr_fcn_file_full_name.empty ())
2094 warning_with_id
2095 ("Octave:associativity-change",
2096 "meaning may have changed due to change in associativity for %s operator",
2097 op_str.c_str ());
2098 else
2099 warning_with_id
2100 ("Octave:associativity-change",
2101 "meaning may have changed due to change in associativity for %s operator near line %d, column %d in file `%s'",
2102 op_str.c_str (), op->line (), op->column (),
2103 curr_fcn_file_full_name.c_str ());
2104 }
2105 }
2106 }
2107
2108 // Build a binary expression.
2109
2110 static tree_expression *
2111 make_binary_op (int op, tree_expression *op1, token *tok_val,
2112 tree_expression *op2)
2113 {
2114 octave_value::binary_op t = octave_value::unknown_binary_op;
2115
2116 switch (op)
2117 {
2118 case POW:
2119 t = octave_value::op_pow;
2120 maybe_warn_associativity_change (op1);
2121 break;
2122
2123 case EPOW:
2124 t = octave_value::op_el_pow;
2125 maybe_warn_associativity_change (op1);
2126 break;
2127
2128 case '+':
2129 t = octave_value::op_add;
2130 break;
2131
2132 case '-':
2133 t = octave_value::op_sub;
2134 break;
2135
2136 case '*':
2137 t = octave_value::op_mul;
2138 break;
2139
2140 case '/':
2141 t = octave_value::op_div;
2142 break;
2143
2144 case EMUL:
2145 t = octave_value::op_el_mul;
2146 break;
2147
2148 case EDIV:
2149 t = octave_value::op_el_div;
2150 break;
2151
2152 case LEFTDIV:
2153 t = octave_value::op_ldiv;
2154 break;
2155
2156 case ELEFTDIV:
2157 t = octave_value::op_el_ldiv;
2158 break;
2159
2160 case LSHIFT:
2161 t = octave_value::op_lshift;
2162 break;
2163
2164 case RSHIFT:
2165 t = octave_value::op_rshift;
2166 break;
2167
2168 case EXPR_LT:
2169 t = octave_value::op_lt;
2170 break;
2171
2172 case EXPR_LE:
2173 t = octave_value::op_le;
2174 break;
2175
2176 case EXPR_EQ:
2177 t = octave_value::op_eq;
2178 break;
2179
2180 case EXPR_GE:
2181 t = octave_value::op_ge;
2182 break;
2183
2184 case EXPR_GT:
2185 t = octave_value::op_gt;
2186 break;
2187
2188 case EXPR_NE:
2189 t = octave_value::op_ne;
2190 break;
2191
2192 case EXPR_AND:
2193 t = octave_value::op_el_and;
2194 break;
2195
2196 case EXPR_OR:
2197 t = octave_value::op_el_or;
2198 if (op2->paren_count () == 0 && op2->is_binary_expression ())
2199 {
2200 tree_binary_expression *e
2201 = dynamic_cast<tree_binary_expression *> (op2);
2202
2203 if (e->op_type () == octave_value::op_el_and)
2204 {
2205 if (curr_fcn_file_full_name.empty ())
2206 warning_with_id
2207 ("Octave:precedence-change",
2208 "meaning may have changed due to change in precedence for & and | operators");
2209 else
2210 warning_with_id
2211 ("Octave:precedence-change",
2212 "meaning may have changed due to change in precedence for & and | operators near line %d, column %d in file `%s'",
2213 op2->line (), op2->column (),
2214 curr_fcn_file_full_name.c_str ());
2215 }
2216 }
2217 break;
2218
2219 default:
2220 panic_impossible ();
2221 break;
2222 }
2223
2224 int l = tok_val->line ();
2225 int c = tok_val->column ();
2226
2227 tree_binary_expression *e
2228 = maybe_compound_binary_expression (op1, op2, l, c, t);
2229
2230 return fold (e);
2231 }
2232
2233 // Build a boolean expression.
2234
2235 static tree_expression *
2236 make_boolean_op (int op, tree_expression *op1, token *tok_val,
2237 tree_expression *op2)
2238 {
2239 tree_boolean_expression::type t;
2240
2241 switch (op)
2242 {
2243 case EXPR_AND_AND:
2244 t = tree_boolean_expression::bool_and;
2245 break;
2246
2247 case EXPR_OR_OR:
2248 t = tree_boolean_expression::bool_or;
2249 if (op2->paren_count () == 0 && op2->is_boolean_expression ())
2250 {
2251 tree_boolean_expression *e
2252 = dynamic_cast<tree_boolean_expression *> (op2);
2253
2254 if (e->op_type () == tree_boolean_expression::bool_and)
2255 warning_with_id
2256 ("Octave:precedence-change",
2257 "meaning may have changed due to change in precedence for && and || operators");
2258 }
2259 break;
2260
2261 default:
2262 panic_impossible ();
2263 break;
2264 }
2265
2266 int l = tok_val->line ();
2267 int c = tok_val->column ();
2268
2269 tree_boolean_expression *e
2270 = new tree_boolean_expression (op1, op2, l, c, t);
2271
2272 return fold (e);
2273 }
2274
2275 // Build a prefix expression.
2276
2277 static tree_expression *
2278 make_prefix_op (int op, tree_expression *op1, token *tok_val)
2279 {
2280 octave_value::unary_op t = octave_value::unknown_unary_op;
2281
2282 switch (op)
2283 {
2284 case EXPR_NOT:
2285 t = octave_value::op_not;
2286 break;
2287
2288 case '+':
2289 t = octave_value::op_uplus;
2290 break;
2291
2292 case '-':
2293 t = octave_value::op_uminus;
2294 break;
2295
2296 case PLUS_PLUS:
2297 t = octave_value::op_incr;
2298 break;
2299
2300 case MINUS_MINUS:
2301 t = octave_value::op_decr;
2302 break;
2303
2304 default:
2305 panic_impossible ();
2306 break;
2307 }
2308
2309 int l = tok_val->line ();
2310 int c = tok_val->column ();
2311
2312 tree_prefix_expression *e
2313 = new tree_prefix_expression (op1, l, c, t);
2314
2315 return fold (e);
2316 }
2317
2318 // Build a postfix expression.
2319
2320 static tree_expression *
2321 make_postfix_op (int op, tree_expression *op1, token *tok_val)
2322 {
2323 octave_value::unary_op t = octave_value::unknown_unary_op;
2324
2325 switch (op)
2326 {
2327 case QUOTE:
2328 t = octave_value::op_hermitian;
2329 break;
2330
2331 case TRANSPOSE:
2332 t = octave_value::op_transpose;
2333 break;
2334
2335 case PLUS_PLUS:
2336 t = octave_value::op_incr;
2337 break;
2338
2339 case MINUS_MINUS:
2340 t = octave_value::op_decr;
2341 break;
2342
2343 default:
2344 panic_impossible ();
2345 break;
2346 }
2347
2348 int l = tok_val->line ();
2349 int c = tok_val->column ();
2350
2351 tree_postfix_expression *e
2352 = new tree_postfix_expression (op1, l, c, t);
2353
2354 return fold (e);
2355 }
2356
2357 // Build an unwind-protect command.
2358
2359 static tree_command *
2360 make_unwind_command (token *unwind_tok, tree_statement_list *body,
2361 tree_statement_list *cleanup, token *end_tok,
2362 octave_comment_list *lc, octave_comment_list *mc)
2363 {
2364 tree_command *retval = 0;
2365
2366 if (end_token_ok (end_tok, token::unwind_protect_end))
2367 {
2368 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2369
2370 int l = unwind_tok->line ();
2371 int c = unwind_tok->column ();
2372
2373 retval = new tree_unwind_protect_command (body, cleanup,
2374 lc, mc, tc, l, c);
2375 }
2376
2377 return retval;
2378 }
2379
2380 // Build a try-catch command.
2381
2382 static tree_command *
2383 make_try_command (token *try_tok, tree_statement_list *body,
2384 tree_statement_list *cleanup, token *end_tok,
2385 octave_comment_list *lc, octave_comment_list *mc)
2386 {
2387 tree_command *retval = 0;
2388
2389 if (end_token_ok (end_tok, token::try_catch_end))
2390 {
2391 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2392
2393 int l = try_tok->line ();
2394 int c = try_tok->column ();
2395
2396 retval = new tree_try_catch_command (body, cleanup,
2397 lc, mc, tc, l, c);
2398 }
2399
2400 return retval;
2401 }
2402
2403 // Build a while command.
2404
2405 static tree_command *
2406 make_while_command (token *while_tok, tree_expression *expr,
2407 tree_statement_list *body, token *end_tok,
2408 octave_comment_list *lc)
2409 {
2410 tree_command *retval = 0;
2411
2412 maybe_warn_assign_as_truth_value (expr);
2413
2414 if (end_token_ok (end_tok, token::while_end))
2415 {
2416 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2417
2418 lexer_flags.looping--;
2419
2420 int l = while_tok->line ();
2421 int c = while_tok->column ();
2422
2423 retval = new tree_while_command (expr, body, lc, tc, l, c);
2424 }
2425
2426 return retval;
2427 }
2428
2429 // Build a do-until command.
2430
2431 static tree_command *
2432 make_do_until_command (token *until_tok, tree_statement_list *body,
2433 tree_expression *expr, octave_comment_list *lc)
2434 {
2435 tree_command *retval = 0;
2436
2437 maybe_warn_assign_as_truth_value (expr);
2438
2439 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2440
2441 lexer_flags.looping--;
2442
2443 int l = until_tok->line ();
2444 int c = until_tok->column ();
2445
2446 retval = new tree_do_until_command (expr, body, lc, tc, l, c);
2447
2448 return retval;
2449 }
2450
2451 // Build a for command.
2452
2453 static tree_command *
2454 make_for_command (token *for_tok, tree_argument_list *lhs,
2455 tree_expression *expr, tree_statement_list *body,
2456 token *end_tok, octave_comment_list *lc)
2457 {
2458 tree_command *retval = 0;
2459
2460 if (end_token_ok (end_tok, token::for_end))
2461 {
2462 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2463
2464 lexer_flags.looping--;
2465
2466 int l = for_tok->line ();
2467 int c = for_tok->column ();
2468
2469 if (lhs->length () == 1)
2470 {
2471 tree_expression *tmp = lhs->remove_front ();
2472
2473 retval = new tree_simple_for_command (tmp, expr, body,
2474 lc, tc, l, c);
2475
2476 delete lhs;
2477 }
2478 else
2479 retval = new tree_complex_for_command (lhs, expr, body,
2480 lc, tc, l, c);
2481 }
2482
2483 return retval;
2484 }
2485
2486 // Build a break command.
2487
2488 static tree_command *
2489 make_break_command (token *break_tok)
2490 {
2491 tree_command *retval = 0;
2492
2493 int l = break_tok->line ();
2494 int c = break_tok->column ();
2495
2496 // We check to see if we are evaluating a function, script, or loop
2497 // so that we don't turn eval ("break;") inside a function, script,
2498 // or loop into a no-op command.
2499
2500 if (lexer_flags.looping || current_function_depth > 0
2501 || reading_script_file || tree_evaluator::in_fcn_or_script_body
2502 || tree_evaluator::in_loop_command)
2503 retval = new tree_break_command (l, c);
2504 else
2505 retval = new tree_no_op_command ("break", l, c);
2506
2507 return retval;
2508 }
2509
2510 // Build a continue command.
2511
2512 static tree_command *
2513 make_continue_command (token *continue_tok)
2514 {
2515 tree_command *retval = 0;
2516
2517 int l = continue_tok->line ();
2518 int c = continue_tok->column ();
2519
2520 // We check to see if we are evaluating a loop so that we don't turn
2521 // eval ("continue;") into a no-op command inside a loop.
2522
2523 if (lexer_flags.looping || tree_evaluator::in_loop_command)
2524 retval = new tree_continue_command (l, c);
2525 else
2526 retval = new tree_no_op_command ("continue", l, c);
2527
2528 return retval;
2529 }
2530
2531 // Build a return command.
2532
2533 static tree_command *
2534 make_return_command (token *return_tok)
2535 {
2536 tree_command *retval = 0;
2537
2538 int l = return_tok->line ();
2539 int c = return_tok->column ();
2540
2541 if (Vdebugging)
2542 {
2543 Vdebugging = false;
2544
2545 retval = new tree_no_op_command ("return", l, c);
2546 }
2547 else
2548 {
2549 // We check to see if we are evaluating a function or script so
2550 // that we don't turn eval ("return;") inside a function, script,
2551 // or loop into a no-op command.
2552
2553 if (current_function_depth > 0 || reading_script_file
2554 || tree_evaluator::in_fcn_or_script_body)
2555 retval = new tree_return_command (l, c);
2556 else
2557 retval = new tree_no_op_command ("return", l, c);
2558 }
2559
2560 return retval;
2561 }
2562
2563 // Start an if command.
2564
2565 static tree_if_command_list *
2566 start_if_command (tree_expression *expr, tree_statement_list *list)
2567 {
2568 maybe_warn_assign_as_truth_value (expr);
2569
2570 tree_if_clause *t = new tree_if_clause (expr, list);
2571
2572 return new tree_if_command_list (t);
2573 }
2574
2575 // Finish an if command.
2576
2577 static tree_if_command *
2578 finish_if_command (token *if_tok, tree_if_command_list *list,
2579 token *end_tok, octave_comment_list *lc)
2580 {
2581 tree_if_command *retval = 0;
2582
2583 if (end_token_ok (end_tok, token::if_end))
2584 {
2585 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2586
2587 int l = if_tok->line ();
2588 int c = if_tok->column ();
2589
2590 if (list && ! list->empty ())
2591 {
2592 tree_if_clause *elt = list->front ();
2593
2594 if (elt)
2595 {
2596 elt->line (l);
2597 elt->column (c);
2598 }
2599 }
2600
2601 retval = new tree_if_command (list, lc, tc, l, c);
2602 }
2603
2604 return retval;
2605 }
2606
2607 // Build an elseif clause.
2608
2609 static tree_if_clause *
2610 make_elseif_clause (token *elseif_tok, tree_expression *expr,
2611 tree_statement_list *list, octave_comment_list *lc)
2612 {
2613 maybe_warn_assign_as_truth_value (expr);
2614
2615 int l = elseif_tok->line ();
2616 int c = elseif_tok->column ();
2617
2618 return new tree_if_clause (expr, list, lc, l, c);
2619 }
2620
2621 // Finish a switch command.
2622
2623 static tree_switch_command *
2624 finish_switch_command (token *switch_tok, tree_expression *expr,
2625 tree_switch_case_list *list, token *end_tok,
2626 octave_comment_list *lc)
2627 {
2628 tree_switch_command *retval = 0;
2629
2630 if (end_token_ok (end_tok, token::switch_end))
2631 {
2632 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2633
2634 int l = switch_tok->line ();
2635 int c = switch_tok->column ();
2636
2637 if (list && ! list->empty ())
2638 {
2639 tree_switch_case *elt = list->front ();
2640
2641 if (elt)
2642 {
2643 elt->line (l);
2644 elt->column (c);
2645 }
2646 }
2647
2648 retval = new tree_switch_command (expr, list, lc, tc, l, c);
2649 }
2650
2651 return retval;
2652 }
2653
2654 // Build a switch case.
2655
2656 static tree_switch_case *
2657 make_switch_case (token *case_tok, tree_expression *expr,
2658 tree_statement_list *list, octave_comment_list *lc)
2659 {
2660 maybe_warn_variable_switch_label (expr);
2661
2662 int l = case_tok->line ();
2663 int c = case_tok->column ();
2664
2665 return new tree_switch_case (expr, list, lc, l, c);
2666 }
2667
2668 // Build an assignment to a variable.
2669
2670 static tree_expression *
2671 make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
2672 tree_expression *rhs)
2673 {
2674 tree_expression *retval = 0;
2675
2676 octave_value::assign_op t = octave_value::unknown_assign_op;
2677
2678 switch (op)
2679 {
2680 case '=':
2681 t = octave_value::op_asn_eq;
2682 break;
2683
2684 case ADD_EQ:
2685 t = octave_value::op_add_eq;
2686 break;
2687
2688 case SUB_EQ:
2689 t = octave_value::op_sub_eq;
2690 break;
2691
2692 case MUL_EQ:
2693 t = octave_value::op_mul_eq;
2694 break;
2695
2696 case DIV_EQ:
2697 t = octave_value::op_div_eq;
2698 break;
2699
2700 case LEFTDIV_EQ:
2701 t = octave_value::op_ldiv_eq;
2702 break;
2703
2704 case POW_EQ:
2705 t = octave_value::op_pow_eq;
2706 break;
2707
2708 case LSHIFT_EQ:
2709 t = octave_value::op_lshift_eq;
2710 break;
2711
2712 case RSHIFT_EQ:
2713 t = octave_value::op_rshift_eq;
2714 break;
2715
2716 case EMUL_EQ:
2717 t = octave_value::op_el_mul_eq;
2718 break;
2719
2720 case EDIV_EQ:
2721 t = octave_value::op_el_div_eq;
2722 break;
2723
2724 case ELEFTDIV_EQ:
2725 t = octave_value::op_el_ldiv_eq;
2726 break;
2727
2728 case EPOW_EQ:
2729 t = octave_value::op_el_pow_eq;
2730 break;
2731
2732 case AND_EQ:
2733 t = octave_value::op_el_and_eq;
2734 break;
2735
2736 case OR_EQ:
2737 t = octave_value::op_el_or_eq;
2738 break;
2739
2740 default:
2741 panic_impossible ();
2742 break;
2743 }
2744
2745 int l = eq_tok->line ();
2746 int c = eq_tok->column ();
2747
2748 if (lhs->is_simple_assign_lhs ())
2749 {
2750 tree_expression *tmp = lhs->remove_front ();
2751
2752 retval = new tree_simple_assignment (tmp, rhs, false, l, c, t);
2753
2754 delete lhs;
2755 }
2756 else
2757 return new tree_multi_assignment (lhs, rhs, false, l, c, t);
2758
2759 return retval;
2760 }
2761
2762 // Define a script.
2763
2764 static void
2765 make_script (tree_statement_list *cmds, tree_statement *end_script)
2766 {
2767 std::string doc_string;
2768
2769 if (! help_buf.empty ())
2770 {
2771 doc_string = help_buf.top ();
2772 help_buf.pop ();
2773 }
2774
2775 if (! cmds)
2776 cmds = new tree_statement_list ();
2777
2778 cmds->append (end_script);
2779
2780 octave_user_script *script
2781 = new octave_user_script (curr_fcn_file_full_name, curr_fcn_file_name,
2782 cmds, doc_string);
2783
2784 octave_time now;
2785
2786 script->stash_fcn_file_time (now);
2787
2788 primary_fcn_ptr = script;
2789
2790 // Unmark any symbols that may have been tagged as local variables
2791 // while parsing (for example, by force_local_variable in lex.l).
2792
2793 symbol_table::unmark_forced_variables ();
2794 }
2795
2796 // Begin defining a function.
2797
2798 static octave_user_function *
2799 start_function (tree_parameter_list *param_list, tree_statement_list *body,
2800 tree_statement *end_fcn_stmt)
2801 {
2802 // We'll fill in the return list later.
2803
2804 if (! body)
2805 body = new tree_statement_list ();
2806
2807 body->append (end_fcn_stmt);
2808
2809 octave_user_function *fcn
2810 = new octave_user_function (symbol_table::current_scope (),
2811 param_list, 0, body);
2812
2813 if (fcn)
2814 {
2815 octave_comment_list *tc = octave_comment_buffer::get_comment ();
2816
2817 fcn->stash_trailing_comment (tc);
2818 }
2819
2820 return fcn;
2821 }
2822
2823 static tree_statement *
2824 make_end (const std::string& type, int l, int c)
2825 {
2826 return make_statement (new tree_no_op_command (type, l, c));
2827 }
2828
2829 // Do most of the work for defining a function.
2830
2831 static octave_user_function *
2832 frob_function (const std::string& fname, octave_user_function *fcn)
2833 {
2834 std::string id_name = fname;
2835
2836 // If input is coming from a file, issue a warning if the name of
2837 // the file does not match the name of the function stated in the
2838 // file. Matlab doesn't provide a diagnostic (it ignores the stated
2839 // name).
2840 if (! autoloading && reading_fcn_file
2841 && (current_function_depth == 1
2842 && ! (parsing_subfunctions || lexer_flags.parsing_class_method)))
2843 {
2844 // FIXME -- should curr_fcn_file_name already be
2845 // preprocessed when we get here? It seems to only be a
2846 // problem with relative file names.
2847
2848 std::string nm = curr_fcn_file_name;
2849
2850 size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
2851
2852 if (pos != std::string::npos)
2853 nm = curr_fcn_file_name.substr (pos+1);
2854
2855 if (nm != id_name)
2856 {
2857 warning_with_id
2858 ("Octave:function-name-clash",
2859 "function name `%s' does not agree with function file name `%s'",
2860 id_name.c_str (), curr_fcn_file_full_name.c_str ());
2861
2862 id_name = nm;
2863 }
2864 }
2865
2866 if (reading_fcn_file || reading_classdef_file || autoloading)
2867 {
2868 octave_time now;
2869
2870 fcn->stash_fcn_file_name (curr_fcn_file_full_name);
2871 fcn->stash_fcn_file_time (now);
2872 fcn->mark_as_system_fcn_file ();
2873
2874 if (fcn_file_from_relative_lookup)
2875 fcn->mark_relative ();
2876
2877 if (current_function_depth > 1 || parsing_subfunctions)
2878 {
2879 fcn->stash_parent_fcn_name (curr_fcn_file_name);
2880 fcn->stash_parent_fcn_scope (primary_fcn_scope);
2881 }
2882
2883 if (lexer_flags.parsing_class_method)
2884 {
2885 if (current_class_name == id_name)
2886 fcn->mark_as_class_constructor ();
2887 else
2888 fcn->mark_as_class_method ();
2889
2890 fcn->stash_dispatch_class (current_class_name);
2891 }
2892
2893 std::string nm = fcn->fcn_file_name ();
2894
2895 file_stat fs (nm);
2896
2897 if (fs && fs.is_newer (now))
2898 warning_with_id ("Octave:future-time-stamp",
2899 "time stamp for `%s' is in the future", nm.c_str ());
2900 }
2901 else if (! (input_from_tmp_history_file || input_from_startup_file)
2902 && reading_script_file
2903 && curr_fcn_file_name == id_name)
2904 {
2905 warning ("function `%s' defined within script file `%s'",
2906 id_name.c_str (), curr_fcn_file_full_name.c_str ());
2907 }
2908
2909 fcn->stash_function_name (id_name);
2910
2911 if (! help_buf.empty () && current_function_depth == 1
2912 && ! parsing_subfunctions)
2913 {
2914 fcn->document (help_buf.top ());
2915
2916 help_buf.pop ();
2917 }
2918
2919 if (reading_fcn_file && current_function_depth == 1
2920 && ! parsing_subfunctions)
2921 primary_fcn_ptr = fcn;
2922
2923 return fcn;
2924 }
2925
2926 static tree_function_def *
2927 finish_function (tree_parameter_list *ret_list,
2928 octave_user_function *fcn, octave_comment_list *lc)
2929 {
2930 tree_function_def *retval = 0;
2931
2932 if (ret_list)
2933 ret_list->mark_as_formal_parameters ();
2934
2935 if (fcn)
2936 {
2937 std::string nm = fcn->name ();
2938 std::string file = fcn->fcn_file_name ();
2939
2940 std::string tmp = nm;
2941 if (! file.empty ())
2942 tmp += ": " + file;
2943
2944 symbol_table::cache_name (fcn->scope (), tmp);
2945
2946 if (lc)
2947 fcn->stash_leading_comment (lc);
2948
2949 fcn->define_ret_list (ret_list);
2950
2951 if (current_function_depth > 1 || parsing_subfunctions)
2952 {
2953 // FIXME -- is this flag used to determine if the function is a
2954 // _subfunction_ somewhere?
2955 fcn->mark_as_nested_function ();
2956
2957 symbol_table::install_subfunction (nm, octave_value (fcn),
2958 primary_fcn_scope);
2959 }
2960
2961 if (! reading_fcn_file)
2962 {
2963 // We are either reading a script file or defining a function
2964 // at the command line, so this definition creates a
2965 // tree_function object that is placed in the parse tree.
2966 // Otherwise, it is just inserted in the symbol table,
2967 // either as a subfunction (see above), or as the primary
2968 // function for the file, via primary_fcn_ptr (see also
2969 // load_fcn_from_file,, parse_fcn_file, and
2970 // symbol_table::fcn_info::fcn_info_rep::find_user_function).
2971
2972 retval = new tree_function_def (fcn);
2973 }
2974
2975 // Unmark any symbols that may have been tagged as local
2976 // variables while parsing (for example, by force_local_variable
2977 // in lex.l).
2978
2979 symbol_table::unmark_forced_variables (fcn->scope ());
2980 }
2981
2982 return retval;
2983 }
2984
2985 static void
2986 recover_from_parsing_function (void)
2987 {
2988 if (symtab_context.empty ())
2989 panic_impossible ();
2990
2991 symbol_table::set_scope (symtab_context.top ());
2992 symtab_context.pop ();
2993
2994 if (reading_fcn_file && current_function_depth == 1
2995 && ! parsing_subfunctions)
2996 parsing_subfunctions = true;
2997
2998 current_function_depth--;
2999
3000 lexer_flags.parsed_function_name = false;
3001 lexer_flags.looking_at_return_list = false;
3002 lexer_flags.looking_at_parameter_list = false;
3003 }
3004
3005 // Make an index expression.
3006
3007 static tree_index_expression *
3008 make_index_expression (tree_expression *expr, tree_argument_list *args,
3009 char type)
3010 {
3011 tree_index_expression *retval = 0;
3012
3013 int l = expr->line ();
3014 int c = expr->column ();
3015
3016 expr->mark_postfix_indexed ();
3017
3018 if (expr->is_index_expression ())
3019 {
3020 tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
3021
3022 tmp->append (args, type);
3023
3024 retval = tmp;
3025 }
3026 else
3027 retval = new tree_index_expression (expr, args, l, c, type);
3028
3029 return retval;
3030 }
3031
3032 // Make an indirect reference expression.
3033
3034 static tree_index_expression *
3035 make_indirect_ref (tree_expression *expr, const std::string& elt)
3036 {
3037 tree_index_expression *retval = 0;
3038
3039 int l = expr->line ();
3040 int c = expr->column ();
3041
3042 if (expr->is_index_expression ())
3043 {
3044 tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
3045
3046 tmp->append (elt);
3047
3048 retval = tmp;
3049 }
3050 else
3051 retval = new tree_index_expression (expr, elt, l, c);
3052
3053 lexer_flags.looking_at_indirect_ref = false;
3054
3055 return retval;
3056 }
3057
3058 // Make an indirect reference expression with dynamic field name.
3059
3060 static tree_index_expression *
3061 make_indirect_ref (tree_expression *expr, tree_expression *elt)
3062 {
3063 tree_index_expression *retval = 0;
3064
3065 int l = expr->line ();
3066 int c = expr->column ();
3067
3068 if (expr->is_index_expression ())
3069 {
3070 tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
3071
3072 tmp->append (elt);
3073
3074 retval = tmp;
3075 }
3076 else
3077 retval = new tree_index_expression (expr, elt, l, c);
3078
3079 lexer_flags.looking_at_indirect_ref = false;
3080
3081 return retval;
3082 }
3083
3084 // Make a declaration command.
3085
3086 static tree_decl_command *
3087 make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst)
3088 {
3089 tree_decl_command *retval = 0;
3090
3091 int l = tok_val->line ();
3092 int c = tok_val->column ();
3093
3094 switch (tok)
3095 {
3096 case GLOBAL:
3097 retval = new tree_global_command (lst, l, c);
3098 break;
3099
3100 case STATIC:
3101 if (current_function_depth > 0)
3102 retval = new tree_static_command (lst, l, c);
3103 else
3104 {
3105 if (reading_script_file)
3106 warning ("ignoring persistent declaration near line %d of file `%s'",
3107 l, curr_fcn_file_full_name.c_str ());
3108 else
3109 warning ("ignoring persistent declaration near line %d", l);
3110 }
3111 break;
3112
3113 default:
3114 panic_impossible ();
3115 break;
3116 }
3117
3118 return retval;
3119 }
3120
3121 // Finish building a matrix list.
3122
3123 static tree_expression *
3124 finish_matrix (tree_matrix *m)
3125 {
3126 tree_expression *retval = m;
3127
3128 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
3129
3130 unwind_protect::protect_var (error_state);
3131 unwind_protect::protect_var (warning_state);
3132
3133 unwind_protect::protect_var (discard_error_messages);
3134 unwind_protect::protect_var (discard_warning_messages);
3135
3136 discard_error_messages = true;
3137 discard_warning_messages = true;
3138
3139 if (m->all_elements_are_constant ())
3140 {
3141 octave_value tmp = m->rvalue1 ();
3142
3143 if (! (error_state || warning_state))
3144 {
3145 tree_constant *tc_retval
3146 = new tree_constant (tmp, m->line (), m->column ());
3147
3148 std::ostringstream buf;
3149
3150 tree_print_code tpc (buf);
3151
3152 m->accept (tpc);
3153
3154 tc_retval->stash_original_text (buf.str ());
3155
3156 delete m;
3157
3158 retval = tc_retval;
3159 }
3160 }
3161
3162 unwind_protect::run_frame (uwp_frame);
3163
3164 return retval;
3165 }
3166
3167 // Finish building a cell list.
3168
3169 static tree_expression *
3170 finish_cell (tree_cell *c)
3171 {
3172 return finish_matrix (c);
3173 }
3174
3175 static void
3176 maybe_warn_missing_semi (tree_statement_list *t)
3177 {
3178 if (current_function_depth > 0)
3179 {
3180 tree_statement *tmp = t->back();
3181
3182 if (tmp->is_expression ())
3183 warning_with_id
3184 ("Octave:missing-semicolon",
3185 "missing semicolon near line %d, column %d in file `%s'",
3186 tmp->line (), tmp->column (), curr_fcn_file_full_name.c_str ());
3187 }
3188 }
3189
3190 static tree_statement_list *
3191 set_stmt_print_flag (tree_statement_list *list, char sep,
3192 bool warn_missing_semi)
3193 {
3194 tree_statement *tmp = list->back ();
3195
3196 switch (sep)
3197 {
3198 case ';':
3199 tmp->set_print_flag (false);
3200 break;
3201
3202 case 0:
3203 case ',':
3204 case '\n':
3205 tmp->set_print_flag (true);
3206 if (warn_missing_semi)
3207 maybe_warn_missing_semi (list);
3208 break;
3209
3210 default:
3211 warning ("unrecognized separator type!");
3212 break;
3213 }
3214
3215 // Even if a statement is null, we add it to the list then remove it
3216 // here so that the print flag is applied to the correct statement.
3217
3218 if (tmp->is_null_statement ())
3219 {
3220 list->pop_back ();
3221 delete tmp;
3222 }
3223
3224 return list;
3225 }
3226
3227 static tree_statement_list *
3228 make_statement_list (tree_statement *stmt)
3229 {
3230 return new tree_statement_list (stmt);
3231 }
3232
3233 static tree_statement_list *
3234 append_statement_list (tree_statement_list *list, char sep,
3235 tree_statement *stmt, bool warn_missing_semi)
3236 {
3237 set_stmt_print_flag (list, sep, warn_missing_semi);
3238
3239 list->append (stmt);
3240
3241 return list;
3242 }
3243
3244 static void
3245 safe_fclose (void *f)
3246 {
3247 // FIXME -- comments at the end of an input file are
3248 // discarded (otherwise, they would be appended to the next
3249 // statement, possibly from the command line or another file, which
3250 // can be quite confusing).
3251
3252 octave_comment_list *tc = octave_comment_buffer::get_comment ();
3253
3254 delete tc;
3255
3256 if (f)
3257 fclose (static_cast<FILE *> (f));
3258 }
3259
3260 static bool
3261 looks_like_copyright (const std::string& s)
3262 {
3263 bool retval = false;
3264
3265 if (! s.empty ())
3266 {
3267 size_t offset = s.find_first_not_of (" \t");
3268
3269 retval = (s.substr (offset, 9) == "Copyright");
3270 }
3271
3272 return retval;
3273 }
3274
3275 static int
3276 text_getc (FILE *f)
3277 {
3278 int c = getc (f);
3279
3280 // Convert CRLF into just LF and single CR into LF.
3281
3282 if (c == '\r')
3283 {
3284 c = getc (f);
3285
3286 if (c != '\n')
3287 {
3288 ungetc (c, f);
3289 c = '\n';
3290 }
3291 }
3292
3293 if (c == '\n')
3294 input_line_number++;
3295
3296 return c;
3297 }
3298
3299 class
3300 stdio_stream_reader : public stream_reader
3301 {
3302 public:
3303 stdio_stream_reader (FILE *f_arg) : stream_reader (), f (f_arg) { }
3304
3305 int getc (void) { return ::text_getc (f); }
3306 int ungetc (int c)
3307 {
3308 if (c == '\n')
3309 input_line_number--;
3310
3311 return ::ungetc (c, f);
3312 }
3313
3314 private:
3315 FILE *f;
3316 };
3317
3318 static bool
3319 skip_white_space (stream_reader& reader)
3320 {
3321 int c = 0;
3322
3323 while ((c = reader.getc ()) != EOF)
3324 {
3325 switch (c)
3326 {
3327 case ' ':
3328 case '\t':
3329 current_input_column++;
3330 break;
3331
3332 case '\n':
3333 current_input_column = 0;
3334 break;
3335
3336 default:
3337 current_input_column--;
3338 reader.ungetc (c);
3339 goto done;
3340 }
3341 }
3342
3343 done:
3344
3345 return (c == EOF);
3346 }
3347
3348 static bool
3349 looking_at_classdef_keyword (FILE *ffile)
3350 {
3351 bool status = false;
3352
3353 long pos = ftell (ffile);
3354
3355 char buf [10];
3356 fgets (buf, 10, ffile);
3357 size_t len = strlen (buf);
3358 if (len > 8 && strncmp (buf, "classdef", 8) == 0
3359 && ! (isalnum (buf[8]) || buf[8] == '_'))
3360 status = true;
3361
3362 fseek (ffile, pos, SEEK_SET);
3363
3364 return status;
3365 }
3366
3367 static std::string
3368 gobble_leading_white_space (FILE *ffile, bool& eof)
3369 {
3370 std::string help_txt;
3371
3372 eof = false;
3373
3374 // TRUE means we have already cached the help text.
3375 bool have_help_text = false;
3376
3377 std::string txt;
3378
3379 stdio_stream_reader stdio_reader (ffile);
3380
3381 while (true)
3382 {
3383 eof = skip_white_space (stdio_reader);
3384
3385 if (eof)
3386 break;
3387
3388 txt = grab_comment_block (stdio_reader, true, eof);
3389
3390 if (txt.empty ())
3391 break;
3392
3393 if (! (have_help_text || looks_like_copyright (txt)))
3394 {
3395 help_txt = txt;
3396 have_help_text = true;
3397 }
3398
3399 octave_comment_buffer::append (txt);
3400
3401 if (eof)
3402 break;
3403 }
3404
3405 return help_txt;
3406 }
3407
3408 static bool
3409 looking_at_function_keyword (FILE *ffile)
3410 {
3411 bool status = false;
3412
3413 long pos = ftell (ffile);
3414
3415 char buf [10];
3416 fgets (buf, 10, ffile);
3417 size_t len = strlen (buf);
3418 if (len > 8 && strncmp (buf, "function", 8) == 0
3419 && ! (isalnum (buf[8]) || buf[8] == '_'))
3420 status = true;
3421
3422 fseek (ffile, pos, SEEK_SET);
3423
3424 return status;
3425 }
3426
3427 static octave_function *
3428 parse_fcn_file (const std::string& ff, const std::string& dispatch_type,
3429 bool force_script = false, bool require_file = true,
3430 const std::string& warn_for = std::string ())
3431 {
3432 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
3433
3434 octave_function *fcn_ptr = 0;
3435
3436 // Open function file and parse.
3437
3438 FILE *in_stream = command_editor::get_input_stream ();
3439
3440 unwind_protect::add_fcn (command_editor::set_input_stream,
3441 in_stream);
3442
3443 unwind_protect::protect_var (ff_instream);
3444
3445 unwind_protect::protect_var (input_line_number);
3446 unwind_protect::protect_var (current_input_column);
3447 unwind_protect::protect_var (reading_fcn_file);
3448 unwind_protect::protect_var (line_editing);
3449 unwind_protect::protect_var (current_class_name);
3450 unwind_protect::protect_var (current_function_depth);
3451 unwind_protect::protect_var (max_function_depth);
3452 unwind_protect::protect_var (parsing_subfunctions);
3453 unwind_protect::protect_var (endfunction_found);
3454
3455 input_line_number = 1;
3456 current_input_column = 1;
3457 reading_fcn_file = true;
3458 line_editing = false;
3459 current_class_name = dispatch_type;
3460 current_function_depth = 0;
3461 max_function_depth = 0;
3462 parsing_subfunctions = false;
3463 endfunction_found = false;
3464
3465 // The next four lines must be in this order.
3466 unwind_protect::add_fcn (command_history::ignore_entries, ! Vsaving_history);
3467
3468 // FIXME -- we shouldn't need both the
3469 // command_history object and the
3470 // Vsaving_history variable...
3471 command_history::ignore_entries ();
3472
3473 unwind_protect::protect_var (Vsaving_history);
3474
3475 Vsaving_history = false;
3476
3477 FILE *ffile = get_input_from_file (ff, 0);
3478
3479 unwind_protect::add (safe_fclose, ffile);
3480
3481 if (ffile)
3482 {
3483 bool eof;
3484
3485 std::string help_txt = gobble_leading_white_space (ffile, eof);
3486
3487 if (! eof)
3488 {
3489 std::string file_type;
3490
3491 unwind_protect::protect_var (get_input_from_eval_string);
3492 unwind_protect::protect_var (parser_end_of_input);
3493 unwind_protect::protect_var (reading_fcn_file);
3494 unwind_protect::protect_var (reading_script_file);
3495 unwind_protect::protect_var (reading_classdef_file);
3496 unwind_protect::protect_var (Vecho_executing_commands);
3497
3498
3499 get_input_from_eval_string = false;
3500 parser_end_of_input = false;
3501
3502 if (! force_script && looking_at_function_keyword (ffile))
3503 {
3504 file_type = "function";
3505
3506 Vecho_executing_commands = ECHO_OFF;
3507
3508 reading_classdef_file = false;
3509 reading_fcn_file = true;
3510 reading_script_file = false;
3511 }
3512 else if (! force_script && looking_at_classdef_keyword (ffile))
3513 {
3514 file_type = "classdef";
3515
3516 Vecho_executing_commands = ECHO_OFF;
3517
3518 reading_classdef_file = true;
3519 reading_fcn_file = false;
3520 reading_script_file = false;
3521 }
3522 else
3523 {
3524 file_type = "script";
3525
3526 Vecho_executing_commands = ECHO_OFF;
3527
3528 reading_classdef_file = false;
3529 reading_fcn_file = false;
3530 reading_script_file = true;
3531 }
3532
3533 YY_BUFFER_STATE old_buf = current_buffer ();
3534 YY_BUFFER_STATE new_buf = create_buffer (ffile);
3535
3536 unwind_protect::add_fcn (switch_to_buffer, old_buf);
3537 unwind_protect::add_fcn (delete_buffer, new_buf);
3538
3539 switch_to_buffer (new_buf);
3540
3541 unwind_protect::protect_var (primary_fcn_ptr);
3542 primary_fcn_ptr = 0;
3543
3544 reset_parser ();
3545
3546 // Do this with an unwind-protect cleanup function so that
3547 // the forced variables will be unmarked in the event of an
3548 // interrupt.
3549 symbol_table::scope_id scope = symbol_table::top_scope ();
3550 unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
3551
3552 if (! help_txt.empty ())
3553 help_buf.push (help_txt);
3554
3555 if (reading_script_file)
3556 prep_lexer_for_script_file ();
3557 else
3558 prep_lexer_for_function_file ();
3559
3560 lexer_flags.parsing_class_method = ! dispatch_type.empty ();
3561
3562 int status = yyparse ();
3563
3564 fcn_ptr = primary_fcn_ptr;
3565
3566 if (reading_fcn_file && endfunction_found && max_function_depth > 1)
3567 warning_with_id ("Octave:nested-functions-coerced",
3568 "nested functions are coerced into subfunctions "
3569 "in file %s", ff.c_str ());
3570
3571 if (status != 0)
3572 error ("parse error while reading %s file %s",
3573 file_type.c_str(), ff.c_str ());
3574 }
3575 }
3576 else if (require_file)
3577 error ("no such file, `%s'", ff.c_str ());
3578 else if (! warn_for.empty ())
3579 error ("%s: unable to open file `%s'", warn_for.c_str (), ff.c_str ());
3580
3581 unwind_protect::run_frame (uwp_frame);
3582
3583 return fcn_ptr;
3584 }
3585
3586 std::string
3587 get_help_from_file (const std::string& nm, bool& symbol_found,
3588 std::string& file)
3589 {
3590 std::string retval;
3591
3592 file = fcn_file_in_path (nm);
3593
3594 if (! file.empty ())
3595 {
3596 symbol_found = true;
3597
3598 FILE *fptr = fopen (file.c_str (), "r");
3599
3600 if (fptr)
3601 {
3602 unwind_protect::add (safe_fclose, fptr);
3603
3604 bool eof;
3605 retval = gobble_leading_white_space (fptr, eof);
3606
3607 if (retval.empty ())
3608 {
3609 octave_function *fcn = parse_fcn_file (file, "");
3610
3611 if (fcn)
3612 {
3613 retval = fcn->doc_string ();
3614
3615 delete fcn;
3616 }
3617 }
3618
3619 unwind_protect::run ();
3620 }
3621 }
3622
3623 return retval;
3624 }
3625
3626 std::string
3627 get_help_from_file (const std::string& nm, bool& symbol_found)
3628 {
3629 std::string file;
3630 return get_help_from_file (nm, symbol_found, file);
3631 }
3632
3633 std::string
3634 lookup_autoload (const std::string& nm)
3635 {
3636 std::string retval;
3637
3638 typedef std::map<std::string, std::string>::const_iterator am_iter;
3639
3640 am_iter p = autoload_map.find (nm);
3641
3642 if (p != autoload_map.end ())
3643 retval = load_path::find_file (p->second);
3644
3645 return retval;
3646 }
3647
3648 string_vector
3649 autoloaded_functions (void)
3650 {
3651 string_vector names (autoload_map.size());
3652
3653 octave_idx_type i = 0;
3654 typedef std::map<std::string, std::string>::const_iterator am_iter;
3655 for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
3656 names[i++] = p->first;
3657
3658 return names;
3659 }
3660
3661 string_vector
3662 reverse_lookup_autoload (const std::string& nm)
3663 {
3664 string_vector names;
3665
3666 typedef std::map<std::string, std::string>::const_iterator am_iter;
3667 for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
3668 if (nm == p->second)
3669 names.append (p->first);
3670
3671 return names;
3672 }
3673
3674 octave_function *
3675 load_fcn_from_file (const std::string& file_name, const std::string& dir_name,
3676 const std::string& dispatch_type,
3677 const std::string& fcn_name, bool autoload)
3678 {
3679 octave_function *retval = 0;
3680
3681 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
3682
3683 std::string nm = file_name;
3684
3685 size_t nm_len = nm.length ();
3686
3687 std::string file;
3688
3689 unwind_protect::protect_var (fcn_file_from_relative_lookup);
3690
3691 fcn_file_from_relative_lookup = false;
3692
3693 file = nm;
3694
3695 if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
3696 || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
3697 || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
3698 {
3699 nm = octave_env::base_pathname (file);
3700 nm = nm.substr (0, nm.find_last_of ('.'));
3701 }
3702
3703 if (autoload)
3704 {
3705 unwind_protect::protect_var (autoloading);
3706 autoloading = true;
3707 }
3708
3709 fcn_file_from_relative_lookup = ! octave_env::absolute_pathname (file);
3710
3711 file = octave_env::make_absolute (file, octave_env::getcwd ());
3712
3713 int len = file.length ();
3714
3715 if (len > 4 && file.substr (len-4, len-1) == ".oct")
3716 {
3717 if (autoload && ! fcn_name.empty ())
3718 nm = fcn_name;
3719
3720 retval = octave_dynamic_loader::load_oct (nm, file, fcn_file_from_relative_lookup);
3721 }
3722 else if (len > 4 && file.substr (len-4, len-1) == ".mex")
3723 retval = octave_dynamic_loader::load_mex (nm, file, fcn_file_from_relative_lookup);
3724 else if (len > 2)
3725 {
3726 // These are needed by yyparse.
3727
3728 unwind_protect::protect_var (curr_fcn_file_name);
3729 unwind_protect::protect_var (curr_fcn_file_full_name);
3730
3731 curr_fcn_file_name = nm;
3732 curr_fcn_file_full_name = file;
3733
3734 retval = parse_fcn_file (file, dispatch_type, autoloading);
3735 }
3736
3737 if (retval)
3738 {
3739 retval->stash_dir_name (dir_name);
3740
3741 if (retval->is_user_function ())
3742 {
3743 symbol_table::scope_id id = retval->scope ();
3744
3745 symbol_table::stash_dir_name_for_subfunctions (id, dir_name);
3746 }
3747 }
3748
3749 unwind_protect::run_frame (uwp_frame);
3750
3751 return retval;
3752 }
3753
3754 DEFUN (autoload, args, ,
3755 "-*- texinfo -*-\n\
3756 @deftypefn {Built-in Function} {} autoload (@var{function}, @var{file})\n\
3757 Define @var{function} to autoload from @var{file}.\n\
3758 \n\
3759 The second argument, @var{file}, should be an absolute file name or\n\
3760 a file name in the same directory as the function or script from which\n\
3761 the autoload command was run. @var{file} should not depend on the\n\
3762 Octave load path.\n\
3763 \n\
3764 Normally, calls to @code{autoload} appear in PKG_ADD script files that\n\
3765 are evaluated when a directory is added to the Octave's load path. To\n\
3766 avoid having to hardcode directory names in @var{file}, if @var{file}\n\
3767 is in the same directory as the PKG_ADD script then\n\
3768 \n\
3769 @example\n\
3770 autoload (\"foo\", \"bar.oct\");\n\
3771 @end example\n\
3772 \n\
3773 will load the function @code{foo} from the file @code{bar.oct}. The above\n\
3774 when @code{bar.oct} is not in the same directory or uses like\n\
3775 \n\
3776 @example\n\
3777 autoload (\"foo\", file_in_loadpath (\"bar.oct\"))\n\
3778 @end example\n\
3779 \n\
3780 @noindent\n\
3781 are strongly discouraged, as their behavior might be unpredictable.\n\
3782 \n\
3783 With no arguments, return a structure containing the current autoload map.\n\
3784 @seealso{PKG_ADD}\n\
3785 @end deftypefn")
3786 {
3787 octave_value retval;
3788
3789 int nargin = args.length ();
3790
3791 if (nargin == 0)
3792 {
3793 Cell func_names (dim_vector (autoload_map.size ()), 1);
3794 Cell file_names (dim_vector (autoload_map.size ()), 1);
3795
3796 octave_idx_type i = 0;
3797 typedef std::map<std::string, std::string>::const_iterator am_iter;
3798 for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
3799 {
3800 func_names(i) = p->first;
3801 file_names(i) = p->second;
3802
3803 i++;
3804 }
3805
3806 Octave_map m;
3807
3808 m.assign ("function", func_names);
3809 m.assign ("file", file_names);
3810
3811 retval = m;
3812 }
3813 else if (nargin == 2)
3814 {
3815 string_vector argv = args.make_argv ("autoload");
3816
3817 if (! error_state)
3818 {
3819 std::string nm = argv[2];
3820
3821 if (! octave_env::absolute_pathname (nm))
3822 {
3823 octave_user_code *fcn = octave_call_stack::caller_user_code ();
3824
3825 bool found = false;
3826
3827 if (fcn)
3828 {
3829 std::string fname = fcn->fcn_file_name ();
3830
3831 if (! fname.empty ())
3832 {
3833 fname = octave_env::make_absolute (fname, octave_env::getcwd ());
3834 fname = fname.substr (0, fname.find_last_of (file_ops::dir_sep_str ()) + 1);
3835
3836 file_stat fs (fname + nm);
3837
3838 if (fs.exists ())
3839 {
3840 nm = fname + nm;
3841 found = true;
3842 }
3843 }
3844 }
3845 if (! found)
3846 warning_with_id ("Octave:autoload-relative-file-name",
3847 "autoload: `%s' is not an absolute file name",
3848 nm.c_str ());
3849 }
3850 autoload_map[argv[1]] = nm;
3851 }
3852 }
3853 else
3854 print_usage ();
3855
3856 return retval;
3857 }
3858
3859 void
3860 source_file (const std::string& file_name, const std::string& context,
3861 bool verbose, bool require_file, const std::string& warn_for)
3862 {
3863 std::string file_full_name = file_ops::tilde_expand (file_name);
3864
3865 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
3866
3867 unwind_protect::protect_var (curr_fcn_file_name);
3868 unwind_protect::protect_var (curr_fcn_file_full_name);
3869
3870 curr_fcn_file_name = file_name;
3871 curr_fcn_file_full_name = file_full_name;
3872
3873 if (! context.empty ())
3874 {
3875 if (context == "caller")
3876 octave_call_stack::goto_caller_frame ();
3877 else if (context == "base")
3878 octave_call_stack::goto_base_frame ();
3879 else
3880 error ("source: context must be \"caller\" or \"base\"");
3881
3882 if (! error_state)
3883 unwind_protect::add_fcn (octave_call_stack::pop);
3884 }
3885
3886 if (! error_state)
3887 {
3888 octave_function *fcn = parse_fcn_file (file_full_name, "", true,
3889 require_file, warn_for);
3890
3891 if (! error_state)
3892 {
3893 if (fcn && fcn->is_user_script ())
3894 {
3895 octave_value_list args;
3896
3897 if (verbose)
3898 {
3899 std::cout << "executing commands from " << file_full_name << " ... ";
3900 reading_startup_message_printed = true;
3901 std::cout.flush ();
3902 }
3903
3904 fcn->do_multi_index_op (0, args);
3905
3906 if (verbose)
3907 std::cout << "done." << std::endl;
3908
3909 delete fcn;
3910 }
3911 }
3912 else
3913 error ("source: error sourcing file `%s'",
3914 file_full_name.c_str ());
3915 }
3916
3917 unwind_protect::run_frame (uwp_frame);
3918 }
3919
3920 DEFUN (mfilename, args, ,
3921 "-*- texinfo -*-\n\
3922 @deftypefn {Built-in Function} {} mfilename ()\n\
3923 @deftypefnx {Built-in Function} {} mfilename (@code{\"fullpath\"})\n\
3924 @deftypefnx {Built-in Function} {} mfilename (@code{\"fullpathext\"})\n\
3925 Return the name of the currently executing file. At the top-level,\n\
3926 return the empty string. Given the argument @code{\"fullpath\"},\n\
3927 include the directory part of the file name, but not the extension.\n\
3928 Given the argument @code{\"fullpathext\"}, include the directory part\n\
3929 of the file name and the extension.\n\
3930 @end deftypefn")
3931 {
3932 octave_value retval;
3933
3934 int nargin = args.length ();
3935
3936 if (nargin > 1)
3937 {
3938 print_usage ();
3939 return retval;
3940 }
3941
3942 std::string arg;
3943
3944 if (nargin == 1)
3945 {
3946 arg = args(0).string_value ();
3947
3948 if (error_state)
3949 {
3950 error ("mfilename: expecting argument to be a character string");
3951 return retval;
3952 }
3953 }
3954
3955 std::string fname;
3956
3957 octave_user_code *fcn = octave_call_stack::caller_user_code ();
3958
3959 if (fcn)
3960 {
3961 fname = fcn->fcn_file_name ();
3962
3963 if (fname.empty ())
3964 fname = fcn->name ();
3965 }
3966
3967 if (arg == "fullpathext")
3968 retval = fname;
3969 else
3970 {
3971 size_t dpos = fname.rfind (file_ops::dir_sep_char ());
3972 size_t epos = fname.rfind ('.');
3973
3974 if (epos <= dpos)
3975 epos = std::string::npos;
3976
3977 fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
3978
3979 if (arg == "fullpath")
3980 retval = fname;
3981 else
3982 retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
3983 }
3984
3985 return retval;
3986 }
3987
3988
3989 DEFUN (source, args, ,
3990 "-*- texinfo -*-\n\
3991 @deftypefn {Built-in Function} {} source (@var{file})\n\
3992 Parse and execute the contents of @var{file}. This is equivalent to\n\
3993 executing commands from a script file, but without requiring the file to\n\
3994 be named @file{@var{file}.m}.\n\
3995 @end deftypefn")
3996 {
3997 octave_value_list retval;
3998
3999 int nargin = args.length ();
4000
4001 if (nargin == 1 || nargin == 2)
4002 {
4003 std::string file_name = args(0).string_value ();
4004
4005 if (! error_state)
4006 {
4007 std::string context;
4008
4009 if (nargin == 2)
4010 context = args(1).string_value ();
4011
4012 if (! error_state)
4013 source_file (file_name, context);
4014 else
4015 error ("source: expecting context to be character string");
4016 }
4017 else
4018 error ("source: expecting file name as argument");
4019 }
4020 else
4021 print_usage ();
4022
4023 return retval;
4024 }
4025
4026 // Evaluate an Octave function (built-in or interpreted) and return
4027 // the list of result values. NAME is the name of the function to
4028 // call. ARGS are the arguments to the function. NARGOUT is the
4029 // number of output arguments expected.
4030
4031 octave_value_list
4032 feval (const std::string& name, const octave_value_list& args, int nargout)
4033 {
4034 octave_value_list retval;
4035
4036 octave_value fcn = symbol_table::find_function (name, args);
4037
4038 if (fcn.is_defined ())
4039 retval = fcn.do_multi_index_op (nargout, args);
4040 else
4041 error ("feval: function `%s' not found", name.c_str ());
4042
4043 return retval;
4044 }
4045
4046 octave_value_list
4047 feval (octave_function *fcn, const octave_value_list& args, int nargout)
4048 {
4049 octave_value_list retval;
4050
4051 if (fcn)
4052 retval = fcn->do_multi_index_op (nargout, args);
4053
4054 return retval;
4055 }
4056
4057 static octave_value_list
4058 get_feval_args (const octave_value_list& args)
4059 {
4060 int tmp_nargin = args.length () - 1;
4061
4062 octave_value_list retval (tmp_nargin, octave_value ());
4063
4064 for (int i = 0; i < tmp_nargin; i++)
4065 retval(i) = args(i+1);
4066
4067 string_vector arg_names = args.name_tags ();
4068
4069 if (! arg_names.empty ())
4070 {
4071 // tmp_nargin and arg_names.length () - 1 may differ if
4072 // we are passed all_va_args.
4073
4074 int n = arg_names.length () - 1;
4075
4076 int len = n > tmp_nargin ? tmp_nargin : n;
4077
4078 string_vector tmp_arg_names (len);
4079
4080 for (int i = 0; i < len; i++)
4081 tmp_arg_names(i) = arg_names(i+1);
4082
4083 retval.stash_name_tags (tmp_arg_names);
4084 }
4085
4086 return retval;
4087 }
4088
4089
4090 // Evaluate an Octave function (built-in or interpreted) and return
4091 // the list of result values. The first element of ARGS should be a
4092 // string containing the name of the function to call, then the rest
4093 // are the actual arguments to the function. NARGOUT is the number of
4094 // output arguments expected.
4095
4096 octave_value_list
4097 feval (const octave_value_list& args, int nargout)
4098 {
4099 octave_value_list retval;
4100
4101 int nargin = args.length ();
4102
4103 if (nargin > 0)
4104 {
4105 octave_value f_arg = args(0);
4106
4107 if (f_arg.is_string ())
4108 {
4109 std::string name = f_arg.string_value ();
4110
4111 if (! error_state)
4112 {
4113 octave_value_list tmp_args = get_feval_args (args);
4114
4115 retval = feval (name, tmp_args, nargout);
4116 }
4117 }
4118 else
4119 {
4120 octave_function *fcn = f_arg.function_value ();
4121
4122 if (fcn)
4123 {
4124 octave_value_list tmp_args = get_feval_args (args);
4125
4126 retval = feval (fcn, tmp_args, nargout);
4127 }
4128 }
4129 }
4130
4131 return retval;
4132 }
4133
4134 DEFUN (feval, args, nargout,
4135 "-*- texinfo -*-\n\
4136 @deftypefn {Built-in Function} {} feval (@var{name}, @dots{})\n\
4137 Evaluate the function named @var{name}. Any arguments after the first\n\
4138 are passed on to the named function. For example,\n\
4139 \n\
4140 @example\n\
4141 feval (\"acos\", -1)\n\
4142 @result{} 3.1416\n\
4143 @end example\n\
4144 \n\
4145 @noindent\n\
4146 calls the function @code{acos} with the argument @samp{-1}.\n\
4147 \n\
4148 The function @code{feval} is necessary in order to be able to write\n\
4149 functions that call user-supplied functions, because Octave does not\n\
4150 have a way to declare a pointer to a function (like C) or to declare a\n\
4151 special kind of variable that can be used to hold the name of a function\n\
4152 (like @code{EXTERNAL} in Fortran). Instead, you must refer to functions\n\
4153 by name, and use @code{feval} to call them.\n\
4154 @end deftypefn")
4155 {
4156 octave_value_list retval;
4157
4158 int nargin = args.length ();
4159
4160 if (nargin > 0)
4161 retval = feval (args, nargout);
4162 else
4163 print_usage ();
4164
4165 return retval;
4166 }
4167
4168 octave_value_list
4169 eval_string (const std::string& s, bool silent, int& parse_status, int nargout)
4170 {
4171 octave_value_list retval;
4172
4173 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
4174
4175 unwind_protect::protect_var (input_line_number);
4176 unwind_protect::protect_var (current_input_column);
4177 unwind_protect::protect_var (get_input_from_eval_string);
4178 unwind_protect::protect_var (input_from_eval_string_pending);
4179 unwind_protect::protect_var (parser_end_of_input);
4180 unwind_protect::protect_var (line_editing);
4181 unwind_protect::protect_var (current_eval_string);
4182 unwind_protect::protect_var (current_function_depth);
4183 unwind_protect::protect_var (max_function_depth);
4184 unwind_protect::protect_var (parsing_subfunctions);
4185 unwind_protect::protect_var (endfunction_found);
4186
4187 input_line_number = 1;
4188 current_input_column = 1;
4189 get_input_from_eval_string = true;
4190 input_from_eval_string_pending = true;
4191 parser_end_of_input = false;
4192 line_editing = false;
4193 current_function_depth = 0;
4194 max_function_depth = 0;
4195 parsing_subfunctions = false;
4196 endfunction_found = false;
4197
4198 current_eval_string = s;
4199
4200 YY_BUFFER_STATE old_buf = current_buffer ();
4201 YY_BUFFER_STATE new_buf = create_buffer (0);
4202
4203 unwind_protect::add_fcn (switch_to_buffer, old_buf);
4204 unwind_protect::add_fcn (delete_buffer, new_buf);
4205
4206 switch_to_buffer (new_buf);
4207
4208 do
4209 {
4210 reset_parser ();
4211
4212 unwind_protect::protect_var (global_command);
4213
4214 // Do this with an unwind-protect cleanup function so that the
4215 // forced variables will be unmarked in the event of an
4216 // interrupt.
4217 symbol_table::scope_id scope = symbol_table::top_scope ();
4218 unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
4219
4220 parse_status = yyparse ();
4221
4222 tree_statement_list *command_list = global_command;
4223
4224 // Unmark forced variables.
4225 unwind_protect::run ();
4226
4227 // Restore previous value of global_command.
4228 unwind_protect::run ();
4229
4230 if (parse_status == 0)
4231 {
4232 if (command_list)
4233 {
4234 tree_statement *stmt = 0;
4235
4236 if (command_list->length () == 1
4237 && (stmt = command_list->front ())
4238 && stmt->is_expression ())
4239 {
4240 tree_expression *expr = stmt->expression ();
4241
4242 if (silent)
4243 expr->set_print_flag (false);
4244
4245 bool do_bind_ans = false;
4246
4247 if (expr->is_identifier ())
4248 {
4249 tree_identifier *id
4250 = dynamic_cast<tree_identifier *> (expr);
4251
4252 do_bind_ans = (! id->is_variable ());
4253 }
4254 else
4255 do_bind_ans = (! expr->is_assignment_expression ());
4256
4257 retval = expr->rvalue (nargout);
4258
4259 if (do_bind_ans && ! (error_state || retval.empty ()))
4260 bind_ans (retval(0), expr->print_result ());
4261
4262 if (nargout == 0)
4263 retval = octave_value_list ();
4264 }
4265 else if (nargout == 0)
4266 command_list->accept (*current_evaluator);
4267 else
4268 error ("eval: invalid use of statement list");
4269
4270 delete command_list;
4271
4272 command_list = 0;
4273
4274 if (error_state
4275 || tree_return_command::returning
4276 || tree_break_command::breaking
4277 || tree_continue_command::continuing)
4278 break;
4279 }
4280 else if (parser_end_of_input)
4281 break;
4282 }
4283 }
4284 while (parse_status == 0);
4285
4286 unwind_protect::run_frame (uwp_frame);
4287
4288 return retval;
4289 }
4290
4291 octave_value
4292 eval_string (const std::string& s, bool silent, int& parse_status)
4293 {
4294 octave_value retval;
4295
4296 octave_value_list tmp = eval_string (s, silent, parse_status, 1);
4297
4298 if (! tmp.empty ())
4299 retval = tmp(0);
4300
4301 return retval;
4302 }
4303
4304 static octave_value_list
4305 eval_string (const octave_value& arg, bool silent, int& parse_status,
4306 int nargout)
4307 {
4308 std::string s = arg.string_value ();
4309
4310 if (error_state)
4311 {
4312 error ("eval: expecting std::string argument");
4313 return octave_value (-1);
4314 }
4315
4316 return eval_string (s, silent, parse_status, nargout);
4317 }
4318
4319 DEFUN (eval, args, nargout,
4320 "-*- texinfo -*-\n\
4321 @deftypefn {Built-in Function} {} eval (@var{try}, @var{catch})\n\
4322 Parse the string @var{try} and evaluate it as if it were an Octave\n\
4323 program. If that fails, evaluate the optional string @var{catch}.\n\
4324 The string @var{try} is evaluated in the current context,\n\
4325 so any results remain available after @code{eval} returns.\n\
4326 \n\
4327 The following example makes the variable @var{a} with the approximate\n\
4328 value 3.1416 available.\n\
4329 \n\
4330 @example\n\
4331 eval(\"a = acos(-1);\");\n\
4332 @end example\n\
4333 \n\
4334 If an error occurs during the evaluation of @var{try} the @var{catch}\n\
4335 string is evaluated, as the following example shows:\n\
4336 \n\
4337 @example\n\
4338 eval ('error (\"This is a bad example\");',\n\
4339 'printf (\"This error occurred:\\n%s\\n\", lasterr ());');\n\
4340 @print{} This error occurred:\n\
4341 This is a bad example\n\
4342 @end example\n\
4343 @end deftypefn")
4344 {
4345 octave_value_list retval;
4346
4347 int nargin = args.length ();
4348
4349 if (nargin > 0)
4350 {
4351 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
4352
4353 if (nargin > 1)
4354 {
4355 unwind_protect::protect_var (buffer_error_messages);
4356 buffer_error_messages++;
4357 }
4358
4359 int parse_status = 0;
4360
4361 octave_value_list tmp = eval_string (args(0), nargout > 0,
4362 parse_status, nargout);
4363
4364 if (nargin > 1 && (parse_status != 0 || error_state))
4365 {
4366 error_state = 0;
4367
4368 // Set up for letting the user print any messages from
4369 // errors that occurred in the first part of this eval().
4370
4371 buffer_error_messages--;
4372
4373 tmp = eval_string (args(1), nargout > 0, parse_status, nargout);
4374
4375 if (nargout > 0)
4376 retval = tmp;
4377 }
4378 else if (nargout > 0)
4379 retval = tmp;
4380
4381 unwind_protect::run_frame (uwp_frame);
4382 }
4383 else
4384 print_usage ();
4385
4386 return retval;
4387 }
4388
4389 /*
4390
4391 %% test/octave.test/eval/eval-1.m
4392 %!#test
4393 %! x = 1;
4394 %! assert(eval ("x"),1);
4395
4396 %% test/octave.test/eval/eval-2.m
4397 %!test
4398 %! x = 1;
4399 %! assert(eval ("x;"));
4400
4401 %% test/octave.test/eval/eval-3.m
4402 %!test
4403 %! x = 1;
4404 %! assert(eval ("x;"),1);
4405
4406 %% FIXME
4407 %% Disable this test as adding the ";" is redundant with eval-1 and
4408 %% in any case is a syntax error with assert
4409 %% test/octave.test/eval/eval-4.m
4410 %!#test
4411 %! x = 1;
4412 %! assert(eval ("x");,1);
4413
4414 %% test/octave.test/eval/eval-5.m
4415 %!test
4416 %! eval ("flipud = 2;");
4417 %! assert(flipud,2);
4418
4419 %% test/octave.test/eval/eval-6.m
4420 %!function y = f ()
4421 %! eval ("flipud = 2;");
4422 %! y = flipud;
4423 %!test
4424 %! assert(f,2);
4425
4426 %% test/octave.test/eval/eval-7.m
4427 %!#test
4428 %! eval ("x = 1");
4429 %! assert(x,1);
4430
4431 %% test/octave.test/eval/eval-8.m
4432 %!test
4433 %! eval ("x = 1;")
4434 %! assert(x,1);
4435
4436 %% test/octave.test/eval/eval-9.m
4437 %!test
4438 %! eval ("x = 1;");
4439 %! assert(x,1);
4440
4441 %% test/octave.test/eval/eval-10.m
4442 %!#test
4443 %! eval ("x = 1")
4444 %! assert(x,1);
4445
4446 %% test/octave.test/eval/eval-11.m
4447 %!test
4448 %! x = 1;
4449 %! y = eval ("x");
4450 %! assert(y,1);
4451
4452 %% test/octave.test/eval/eval-12.m
4453 %!test
4454 %! x = 1;
4455 %! y = eval ("x;");
4456 %! assert(y,1);
4457
4458 %% test/octave.test/eval/eval-13.m
4459 %!test
4460 %! x = 1;
4461 %! y = eval ("x;");
4462 %! assert(y,1);
4463
4464 %% test/octave.test/eval/eval-14.m
4465 %!test
4466 %! x = 1;
4467 %! y = eval ("x");
4468 %! assert(y,1);
4469
4470 */
4471
4472 DEFUN (assignin, args, ,
4473 "-*- texinfo -*-\n\
4474 @deftypefn {Built-in Function} {} assignin (@var{context}, @var{varname}, @var{value})\n\
4475 Assign @var{value} to @var{varname} in context @var{context}, which\n\
4476 may be either @code{\"base\"} or @code{\"caller\"}.\n\
4477 @end deftypefn")
4478 {
4479 octave_value_list retval;
4480
4481 int nargin = args.length ();
4482
4483 if (nargin == 3)
4484 {
4485 std::string context = args(0).string_value ();
4486
4487 if (! error_state)
4488 {
4489 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
4490
4491 if (context == "caller")
4492 octave_call_stack::goto_caller_frame ();
4493 else if (context == "base")
4494 octave_call_stack::goto_base_frame ();
4495 else
4496 error ("assignin: context must be \"caller\" or \"base\"");
4497
4498 if (! error_state)
4499 {
4500 unwind_protect::add_fcn (octave_call_stack::pop);
4501
4502 std::string nm = args(1).string_value ();
4503
4504 if (! error_state)
4505 {
4506 if (valid_identifier (nm))
4507 symbol_table::varref (nm) = args(2);
4508 else
4509 error ("assignin: invalid variable name");
4510 }
4511 else
4512 error ("assignin: expecting variable name as second argument");
4513 }
4514
4515 unwind_protect::run_frame (uwp_frame);
4516 }
4517 else
4518 error ("assignin: expecting string as first argument");
4519 }
4520 else
4521 print_usage ();
4522
4523 return retval;
4524 }
4525
4526 DEFUN (evalin, args, nargout,
4527 "-*- texinfo -*-\n\
4528 @deftypefn {Built-in Function} {} evalin (@var{context}, @var{try}, @var{catch})\n\
4529 Like @code{eval}, except that the expressions are evaluated in the\n\
4530 context @var{context}, which may be either @code{\"caller\"} or\n\
4531 @code{\"base\"}.\n\
4532 @end deftypefn")
4533 {
4534 octave_value_list retval;
4535
4536 int nargin = args.length ();
4537
4538 if (nargin > 1)
4539 {
4540 std::string context = args(0).string_value ();
4541
4542 if (! error_state)
4543 {
4544 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
4545
4546 if (context == "caller")
4547 octave_call_stack::goto_caller_frame ();
4548 else if (context == "base")
4549 octave_call_stack::goto_base_frame ();
4550 else
4551 error ("evalin: context must be \"caller\" or \"base\"");
4552
4553 if (! error_state)
4554 {
4555 unwind_protect::add_fcn (octave_call_stack::pop);
4556
4557 if (nargin > 2)
4558 {
4559 unwind_protect::protect_var (buffer_error_messages);
4560 buffer_error_messages++;
4561 }
4562
4563 int parse_status = 0;
4564
4565 octave_value_list tmp = eval_string (args(1), nargout > 0,
4566 parse_status, nargout);
4567
4568 if (nargout > 0)
4569 retval = tmp;
4570
4571 if (nargin > 2 && (parse_status != 0 || error_state))
4572 {
4573 error_state = 0;
4574
4575 // Set up for letting the user print any messages from
4576 // errors that occurred in the first part of this eval().
4577
4578 buffer_error_messages--;
4579
4580 tmp = eval_string (args(2), nargout > 0,
4581 parse_status, nargout);
4582
4583 retval = (nargout > 0) ? tmp : octave_value_list ();
4584 }
4585 }
4586
4587 unwind_protect::run_frame (uwp_frame);
4588 }
4589 else
4590 error ("evalin: expecting string as first argument");
4591 }
4592 else
4593 print_usage ();
4594
4595 return retval;
4596 }
4597
4598 DEFUN (__parser_debug_flag__, args, nargout,
4599 "-*- texinfo -*-\n\
4600 @deftypefn {Built-in Function} {@var{old_val} =} __parser_debug_flag__ (@var{new_val}))\n\
4601 Undocumented internal function.\n\
4602 @end deftypefn")
4603 {
4604 octave_value retval;
4605
4606 bool debug_flag = octave_debug;
4607
4608 retval = set_internal_variable (debug_flag, args, nargout,
4609 "__parser_debug_flag__");
4610
4611 octave_debug = debug_flag;
4612
4613 return retval;
4614 }
4615
4616 /*
4617 ;;; Local Variables: ***
4618 ;;; mode: text ***
4619 ;;; End: ***
4620 */