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