Mercurial > hg > octave-nkf
diff libinterp/parse-tree/oct-parse.yy @ 16155:0259254a3ccc classdef
maint: periodic merge of default to classdef
* lex.h, lex.ll, parse.h, oct-parse.yy: Resolve conflicts by adapting
classdef changes to new octave_parser and lexical_feedback classes.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 28 Feb 2013 02:04:24 -0500 |
parents | 46ca8488de92 a57c2c8c8163 |
children |
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.yy +++ b/libinterp/parse-tree/oct-parse.yy @@ -79,6 +79,15 @@ #include "utils.h" #include "variables.h" +// oct-parse.h must be included after pt-all.h +#include <oct-parse.h> + +extern int octave_lex (YYSTYPE *, void *); + +// Global access to currently active lexer. +// FIXME -- to be removed after more parser+lexer refactoring. +lexical_feedback *CURR_LEXER = 0; + #if defined (GNULIB_NAMESPACE) // Calls to the following functions appear in the generated output from // Bison without the namespace tag. Redefine them so we will use them @@ -88,18 +97,9 @@ #define malloc GNULIB_NAMESPACE::malloc #endif -// The current input line number. -int input_line_number = 1; - -// The column of the current token. -int current_input_column = 1; - // Buffer for help text snagged from function files. std::stack<std::string> help_buf; -// Buffer for comments appearing before a function statement. -static std::string fcn_comment_header; - // TRUE means we are using readline. // (--no-line-editing) bool line_editing = true; @@ -110,297 +110,16 @@ // TRUE means input is coming from startup file. bool input_from_startup_file = false; -// = 0 currently outside any function. -// = 1 inside the primary function or a subfunction. -// > 1 means we are looking at a function definition that seems to be -// inside a function. Note that the function still might not be a -// nested function. -static int current_function_depth = 0; - -// A stack holding the nested function scopes being parsed. -// We don't use std::stack, because we want the clear method. Also, we -// must access one from the top -static std::vector<symbol_table::scope_id> function_scopes; - -// Maximum function depth detected. Just here to determine whether -// we have nested functions or just implicitly ended subfunctions. -static int max_function_depth = 0; - -// FALSE if we are still at the primary function. Subfunctions can -// only be declared inside function files. -static int parsing_subfunctions = false; - -// Have we found an explicit end to a function? -static bool endfunction_found = false; - // Keep track of symbol table information when parsing functions. symtab_context parser_symtab_context; -// Name of the current class when we are parsing class methods or -// constructors. -std::string current_class_name; - -// TRUE means we are in the process of autoloading a function. -static bool autoloading = false; - -// TRUE means the current function file was found in a relative path -// element. -static bool fcn_file_from_relative_lookup = false; - -// Pointer to the primary user function or user script function. -static octave_function *primary_fcn_ptr = 0; - -// Scope where we install all subfunctions and nested functions. Only -// used while reading function files. -static symbol_table::scope_id primary_fcn_scope; - -// Pointer to the classdef object we just parsed, if any. -static tree_classdef *classdef_object = 0; - // List of autoloads (function -> file mapping). static std::map<std::string, std::string> autoload_map; // Forward declarations for some functions defined at the bottom of // the file. -// Generic error messages. -static void -yyerror (const char *s); - -// Error mesages for mismatched end tokens. -static void -end_error (const char *type, token::end_tok_type ettype, int l, int c); - -// Check to see that end tokens are properly matched. -static bool -end_token_ok (token *tok, token::end_tok_type expected); - -// Maybe print a warning if an assignment expression is used as the -// test in a logical expression. -static void -maybe_warn_assign_as_truth_value (tree_expression *expr); - -// Maybe print a warning about switch labels that aren't constants. -static void -maybe_warn_variable_switch_label (tree_expression *expr); - -// Finish building a range. -static tree_expression * -finish_colon_expression (tree_colon_expression *e); - -// Build a constant. -static tree_constant * -make_constant (int op, token *tok_val); - -// Build a function handle. -static tree_fcn_handle * -make_fcn_handle (token *tok_val); - -// Build an anonymous function handle. -static tree_anon_fcn_handle * -make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt); - -// Build a binary expression. -static tree_expression * -make_binary_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2); - -// Build a boolean expression. -static tree_expression * -make_boolean_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2); - -// Build a prefix expression. -static tree_expression * -make_prefix_op (int op, tree_expression *op1, token *tok_val); - -// Build a postfix expression. -static tree_expression * -make_postfix_op (int op, tree_expression *op1, token *tok_val); - -// Build an unwind-protect command. -static tree_command * -make_unwind_command (token *unwind_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, - octave_comment_list *lc, octave_comment_list *mc); - -// Build a try-catch command. -static tree_command * -make_try_command (token *try_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, - octave_comment_list *lc, octave_comment_list *mc); - -// Build a while command. -static tree_command * -make_while_command (token *while_tok, tree_expression *expr, - tree_statement_list *body, token *end_tok, - octave_comment_list *lc); - -// Build a do-until command. -static tree_command * -make_do_until_command (token *until_tok, tree_statement_list *body, - tree_expression *expr, octave_comment_list *lc); - -// Build a for command. -static tree_command * -make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs, - tree_expression *expr, tree_expression *maxproc, - tree_statement_list *body, token *end_tok, - octave_comment_list *lc); - -// Build a break command. -static tree_command * -make_break_command (token *break_tok); - -// Build a continue command. -static tree_command * -make_continue_command (token *continue_tok); - -// Build a return command. -static tree_command * -make_return_command (token *return_tok); - -// Start an if command. -static tree_if_command_list * -start_if_command (tree_expression *expr, tree_statement_list *list); - -// Finish an if command. -static tree_if_command * -finish_if_command (token *if_tok, tree_if_command_list *list, - token *end_tok, octave_comment_list *lc); - -// Build an elseif clause. -static tree_if_clause * -make_elseif_clause (token *elseif_tok, tree_expression *expr, - tree_statement_list *list, octave_comment_list *lc); - -// Finish a switch command. -static tree_switch_command * -finish_switch_command (token *switch_tok, tree_expression *expr, - tree_switch_case_list *list, token *end_tok, - octave_comment_list *lc); - -// Build a switch case. -static tree_switch_case * -make_switch_case (token *case_tok, tree_expression *expr, - tree_statement_list *list, octave_comment_list *lc); - -// Build an assignment to a variable. -static tree_expression * -make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, - tree_expression *rhs); - -// Define a script. -static void -make_script (tree_statement_list *cmds, tree_statement *end_script); - -// Begin defining a function. -static octave_user_function * -start_function (tree_parameter_list *param_list, tree_statement_list *body, - tree_statement *end_function); - -// Create a no-op statement for end_function. -static tree_statement * -make_end (const std::string& type, int l, int c); - -// Do most of the work for defining a function. -static octave_user_function * -frob_function (const std::string& fname, octave_user_function *fcn); - -// Finish defining a function. -static tree_function_def * -finish_function (tree_parameter_list *ret_list, - octave_user_function *fcn, octave_comment_list *lc); - -// Reset state after parsing function. -static void -recover_from_parsing_function (void); - -// Make an index expression. -static tree_index_expression * -make_index_expression (tree_expression *expr, - tree_argument_list *args, char type); - -// Make an indirect reference expression. -static tree_index_expression * -make_indirect_ref (tree_expression *expr, const std::string&); - -// Make an indirect reference expression with dynamic field name. -static tree_index_expression * -make_indirect_ref (tree_expression *expr, tree_expression *field); - -// Make a declaration command. -static tree_decl_command * -make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst); - -// Validate argument list forming a matrix or cell row. -static tree_argument_list * -validate_matrix_row (tree_argument_list *row); - -// Finish building a matrix list. -static tree_expression * -finish_matrix (tree_matrix *m); - -// Finish building a cell list. -static tree_expression * -finish_cell (tree_cell *c); - -// Maybe print a warning. Duh. -static void -maybe_warn_missing_semi (tree_statement_list *); - -// Set the print flag for a statement based on the separator type. -static tree_statement_list * -set_stmt_print_flag (tree_statement_list *, char, bool); - -// Create a statement list. -static tree_statement_list *make_statement_list (tree_statement *stmt); - -// Append a statement to an existing statement list. -static tree_statement_list * -append_statement_list (tree_statement_list *list, char sep, - tree_statement *stmt, bool warn_missing_semi); - -static tree_funcall * -make_superclass_ref (const std::string& method_nm, - const std::string& package_nm, - const std::string& class_nm, - int l, int c); - -static tree_funcall * -make_meta_class_query (const std::string& package_nm, - const std::string& class_nm, - int l, int c); - -static tree_classdef * -make_classdef (token *tok_val, tree_classdef_attribute_list *a, - tree_identifier *id, tree_classdef_superclass_list *sc, - tree_classdef_body *body, token *end_tok, - octave_comment_list *lc); - -static tree_classdef_properties_block * -make_classdef_properties_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_property_list *plist, - token *end_tok, octave_comment_list *lc); - -static tree_classdef_methods_block * -make_classdef_methods_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_methods_list *mlist, - token *end_tok, octave_comment_list *lc); - -static tree_classdef_events_block * -make_classdef_events_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_events_list *elist, - token *end_tok, octave_comment_list *lc); - -static tree_classdef_enum_block * -make_classdef_enum_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_enum_list *elist, - token *end_tok, octave_comment_list *lc); +static void yyerror (octave_parser *curr_parser, const char *s); // Finish building a statement. template <class T> @@ -427,6 +146,9 @@ } \ while (0) +#define curr_lexer curr_parser->curr_lexer +#define scanner curr_lexer->scanner + %} // Bison declarations. @@ -436,6 +158,19 @@ %name-prefix="octave_" +// We are using the pure parser interface and the reentrant lexer +// interface but the Octave parser and lexer are NOT properly +// reentrant because both still use many global variables. It should be +// safe to create a parser object and call it while anotehr parser +// object is active (to parse a callback function while the main +// interactive parser is waiting for input, for example) if you take +// care to properly save and restore (typically with an unwind_protect +// object) relevant global values before and after the nested call. + +%define api.pure +%parse-param { octave_parser *curr_parser } +%lex-param { void *scanner } + %union { // The type of the basic tokens returned by the lexer. @@ -633,7 +368,7 @@ { $$ = 0; } | END_OF_INPUT { - parser_end_of_input = 1; + curr_parser->end_of_input = true; $$ = 0; } | simple_list @@ -645,13 +380,13 @@ ; simple_list : simple_list1 opt_sep_no_nl - { $$ = set_stmt_print_flag ($1, $2, false); } + { $$ = curr_parser->set_stmt_print_flag ($1, $2, false); } ; simple_list1 : statement - { $$ = make_statement_list ($1); } + { $$ = curr_parser->make_statement_list ($1); } | simple_list1 sep_no_nl statement - { $$ = append_statement_list ($1, $2, $3, false); } + { $$ = curr_parser->append_statement_list ($1, $2, $3, false); } ; opt_list : // empty @@ -661,13 +396,13 @@ ; list : list1 opt_sep - { $$ = set_stmt_print_flag ($1, $2, true); } + { $$ = curr_parser->set_stmt_print_flag ($1, $2, true); } ; list1 : statement - { $$ = make_statement_list ($1); } + { $$ = curr_parser->make_statement_list ($1); } | list1 sep statement - { $$ = append_statement_list ($1, $2, $3, true); } + { $$ = curr_parser->append_statement_list ($1, $2, $3, true); } ; statement : expression @@ -687,7 +422,7 @@ // WHILE, etc. word_list_cmd : identifier word_list - { $$ = make_index_expression ($1, $2, '('); } + { $$ = curr_parser->make_index_expression ($1, $2, '('); } ; word_list : string @@ -717,8 +452,9 @@ std::string package_nm = $1->superclass_package_name (); std::string class_nm = $1->superclass_class_name (); - $$ = make_superclass_ref (method_nm, package_nm, class_nm, - $1->line (), $1->column ()); + $$ = curr_parser->make_superclass_ref + (method_nm, package_nm, class_nm, + $1->line (), $1->column ()); } ; @@ -727,21 +463,22 @@ std::string package_nm = $1->meta_package_name (); std::string class_nm = $1->meta_class_name (); - $$ = make_meta_class_query (package_nm, class_nm, - $1->line (), $1->column ()); + $$ = curr_parser->make_meta_class_query + (package_nm, class_nm, + $1->line (), $1->column ()); } ; string : DQ_STRING - { $$ = make_constant (DQ_STRING, $1); } + { $$ = curr_parser->make_constant (DQ_STRING, $1); } | SQ_STRING - { $$ = make_constant (SQ_STRING, $1); } + { $$ = curr_parser->make_constant (SQ_STRING, $1); } ; constant : NUM - { $$ = make_constant (NUM, $1); } + { $$ = curr_parser->make_constant (NUM, $1); } | IMAG_NUM - { $$ = make_constant (IMAG_NUM, $1); } + { $$ = curr_parser->make_constant (IMAG_NUM, $1); } | string { $$ = $1; } ; @@ -749,26 +486,26 @@ matrix : '[' ']' { $$ = new tree_constant (octave_null_matrix::instance); - lexer_flags.looking_at_matrix_or_assign_lhs = false; - lexer_flags.pending_local_variables.clear (); + curr_lexer->looking_at_matrix_or_assign_lhs = false; + curr_lexer->pending_local_variables.clear (); } | '[' ';' ']' { $$ = new tree_constant (octave_null_matrix::instance); - lexer_flags.looking_at_matrix_or_assign_lhs = false; - lexer_flags.pending_local_variables.clear (); + curr_lexer->looking_at_matrix_or_assign_lhs = false; + curr_lexer->pending_local_variables.clear (); } | '[' ',' ']' { $$ = new tree_constant (octave_null_matrix::instance); - lexer_flags.looking_at_matrix_or_assign_lhs = false; - lexer_flags.pending_local_variables.clear (); + curr_lexer->looking_at_matrix_or_assign_lhs = false; + curr_lexer->pending_local_variables.clear (); } | '[' matrix_rows ']' { - $$ = finish_matrix ($2); - lexer_flags.looking_at_matrix_or_assign_lhs = false; - lexer_flags.pending_local_variables.clear (); + $$ = curr_parser->finish_matrix ($2); + curr_lexer->looking_at_matrix_or_assign_lhs = false; + curr_lexer->pending_local_variables.clear (); } ; @@ -792,7 +529,7 @@ | '{' ';' '}' { $$ = new tree_constant (octave_value (Cell ())); } | '{' cell_rows '}' - { $$ = finish_cell ($2); } + { $$ = curr_parser->finish_cell ($2); } ; cell_rows : cell_rows1 @@ -812,22 +549,22 @@ cell_or_matrix_row : arg_list - { $$ = validate_matrix_row ($1); } + { $$ = curr_parser->validate_matrix_row ($1); } | arg_list ',' // Ignore trailing comma. - { $$ = validate_matrix_row ($1); } + { $$ = curr_parser->validate_matrix_row ($1); } ; fcn_handle : '@' FCN_HANDLE { - $$ = make_fcn_handle ($2); - lexer_flags.looking_at_function_handle--; + $$ = curr_parser->make_fcn_handle ($2); + curr_lexer->looking_at_function_handle--; } ; anon_fcn_handle : '@' param_list statement { - lexer_flags.quote_is_transpose = false; - $$ = make_anon_fcn_handle ($2, $3); + curr_lexer->quote_is_transpose = false; + $$ = curr_parser->make_anon_fcn_handle ($2, $3); } ; @@ -886,69 +623,69 @@ ; indirect_ref_op : '.' - { lexer_flags.looking_at_indirect_ref = true; } + { curr_lexer->looking_at_indirect_ref = true; } ; oper_expr : primary_expr { $$ = $1; } | oper_expr PLUS_PLUS - { $$ = make_postfix_op (PLUS_PLUS, $1, $2); } + { $$ = curr_parser->make_postfix_op (PLUS_PLUS, $1, $2); } | oper_expr MINUS_MINUS - { $$ = make_postfix_op (MINUS_MINUS, $1, $2); } + { $$ = curr_parser->make_postfix_op (MINUS_MINUS, $1, $2); } | oper_expr '(' ')' - { $$ = make_index_expression ($1, 0, '('); } + { $$ = curr_parser->make_index_expression ($1, 0, '('); } | oper_expr '(' arg_list ')' - { $$ = make_index_expression ($1, $3, '('); } + { $$ = curr_parser->make_index_expression ($1, $3, '('); } | oper_expr '{' '}' - { $$ = make_index_expression ($1, 0, '{'); } + { $$ = curr_parser->make_index_expression ($1, 0, '{'); } | oper_expr '{' arg_list '}' - { $$ = make_index_expression ($1, $3, '{'); } + { $$ = curr_parser->make_index_expression ($1, $3, '{'); } | oper_expr QUOTE - { $$ = make_postfix_op (QUOTE, $1, $2); } + { $$ = curr_parser->make_postfix_op (QUOTE, $1, $2); } | oper_expr TRANSPOSE - { $$ = make_postfix_op (TRANSPOSE, $1, $2); } + { $$ = curr_parser->make_postfix_op (TRANSPOSE, $1, $2); } | oper_expr indirect_ref_op STRUCT_ELT - { $$ = make_indirect_ref ($1, $3->text ()); } + { $$ = curr_parser->make_indirect_ref ($1, $3->text ()); } | oper_expr indirect_ref_op '(' expression ')' - { $$ = make_indirect_ref ($1, $4); } + { $$ = curr_parser->make_indirect_ref ($1, $4); } | PLUS_PLUS oper_expr %prec UNARY - { $$ = make_prefix_op (PLUS_PLUS, $2, $1); } + { $$ = curr_parser->make_prefix_op (PLUS_PLUS, $2, $1); } | MINUS_MINUS oper_expr %prec UNARY - { $$ = make_prefix_op (MINUS_MINUS, $2, $1); } + { $$ = curr_parser->make_prefix_op (MINUS_MINUS, $2, $1); } | EXPR_NOT oper_expr %prec UNARY - { $$ = make_prefix_op (EXPR_NOT, $2, $1); } + { $$ = curr_parser->make_prefix_op (EXPR_NOT, $2, $1); } | '+' oper_expr %prec UNARY - { $$ = make_prefix_op ('+', $2, $1); } + { $$ = curr_parser->make_prefix_op ('+', $2, $1); } | '-' oper_expr %prec UNARY - { $$ = make_prefix_op ('-', $2, $1); } + { $$ = curr_parser->make_prefix_op ('-', $2, $1); } | oper_expr POW oper_expr - { $$ = make_binary_op (POW, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (POW, $1, $2, $3); } | oper_expr EPOW oper_expr - { $$ = make_binary_op (EPOW, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EPOW, $1, $2, $3); } | oper_expr '+' oper_expr - { $$ = make_binary_op ('+', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); } | oper_expr '-' oper_expr - { $$ = make_binary_op ('-', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); } | oper_expr '*' oper_expr - { $$ = make_binary_op ('*', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('*', $1, $2, $3); } | oper_expr '/' oper_expr - { $$ = make_binary_op ('/', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('/', $1, $2, $3); } | oper_expr EPLUS oper_expr - { $$ = make_binary_op ('+', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); } | oper_expr EMINUS oper_expr - { $$ = make_binary_op ('-', $1, $2, $3); } + { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); } | oper_expr EMUL oper_expr - { $$ = make_binary_op (EMUL, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EMUL, $1, $2, $3); } | oper_expr EDIV oper_expr - { $$ = make_binary_op (EDIV, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EDIV, $1, $2, $3); } | oper_expr LEFTDIV oper_expr - { $$ = make_binary_op (LEFTDIV, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (LEFTDIV, $1, $2, $3); } | oper_expr ELEFTDIV oper_expr - { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (ELEFTDIV, $1, $2, $3); } ; colon_expr : colon_expr1 - { $$ = finish_colon_expression ($1); } + { $$ = curr_parser->finish_colon_expression ($1); } ; colon_expr1 : oper_expr @@ -963,29 +700,29 @@ simple_expr : colon_expr { $$ = $1; } | simple_expr LSHIFT simple_expr - { $$ = make_binary_op (LSHIFT, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (LSHIFT, $1, $2, $3); } | simple_expr RSHIFT simple_expr - { $$ = make_binary_op (RSHIFT, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (RSHIFT, $1, $2, $3); } | simple_expr EXPR_LT simple_expr - { $$ = make_binary_op (EXPR_LT, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_LT, $1, $2, $3); } | simple_expr EXPR_LE simple_expr - { $$ = make_binary_op (EXPR_LE, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_LE, $1, $2, $3); } | simple_expr EXPR_EQ simple_expr - { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_EQ, $1, $2, $3); } | simple_expr EXPR_GE simple_expr - { $$ = make_binary_op (EXPR_GE, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_GE, $1, $2, $3); } | simple_expr EXPR_GT simple_expr - { $$ = make_binary_op (EXPR_GT, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_GT, $1, $2, $3); } | simple_expr EXPR_NE simple_expr - { $$ = make_binary_op (EXPR_NE, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_NE, $1, $2, $3); } | simple_expr EXPR_AND simple_expr - { $$ = make_binary_op (EXPR_AND, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_AND, $1, $2, $3); } | simple_expr EXPR_OR simple_expr - { $$ = make_binary_op (EXPR_OR, $1, $2, $3); } + { $$ = curr_parser->make_binary_op (EXPR_OR, $1, $2, $3); } | simple_expr EXPR_AND_AND simple_expr - { $$ = make_boolean_op (EXPR_AND_AND, $1, $2, $3); } + { $$ = curr_parser->make_boolean_op (EXPR_AND_AND, $1, $2, $3); } | simple_expr EXPR_OR_OR simple_expr - { $$ = make_boolean_op (EXPR_OR_OR, $1, $2, $3); } + { $$ = curr_parser->make_boolean_op (EXPR_OR_OR, $1, $2, $3); } ; // Arrange for the lexer to return CLOSE_BRACE for ']' by looking ahead @@ -999,47 +736,47 @@ | '[' arg_list opt_comma CLOSE_BRACE { $$ = $2; - lexer_flags.looking_at_matrix_or_assign_lhs = false; - for (std::set<std::string>::const_iterator p = lexer_flags.pending_local_variables.begin (); - p != lexer_flags.pending_local_variables.end (); + curr_lexer->looking_at_matrix_or_assign_lhs = false; + for (std::set<std::string>::const_iterator p = curr_lexer->pending_local_variables.begin (); + p != curr_lexer->pending_local_variables.end (); p++) { symbol_table::force_variable (*p); } - lexer_flags.pending_local_variables.clear (); + curr_lexer->pending_local_variables.clear (); } ; assign_expr : assign_lhs '=' expression - { $$ = make_assign_op ('=', $1, $2, $3); } + { $$ = curr_parser->make_assign_op ('=', $1, $2, $3); } | assign_lhs ADD_EQ expression - { $$ = make_assign_op (ADD_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (ADD_EQ, $1, $2, $3); } | assign_lhs SUB_EQ expression - { $$ = make_assign_op (SUB_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (SUB_EQ, $1, $2, $3); } | assign_lhs MUL_EQ expression - { $$ = make_assign_op (MUL_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (MUL_EQ, $1, $2, $3); } | assign_lhs DIV_EQ expression - { $$ = make_assign_op (DIV_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (DIV_EQ, $1, $2, $3); } | assign_lhs LEFTDIV_EQ expression - { $$ = make_assign_op (LEFTDIV_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (LEFTDIV_EQ, $1, $2, $3); } | assign_lhs POW_EQ expression - { $$ = make_assign_op (POW_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (POW_EQ, $1, $2, $3); } | assign_lhs LSHIFT_EQ expression - { $$ = make_assign_op (LSHIFT_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (LSHIFT_EQ, $1, $2, $3); } | assign_lhs RSHIFT_EQ expression - { $$ = make_assign_op (RSHIFT_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (RSHIFT_EQ, $1, $2, $3); } | assign_lhs EMUL_EQ expression - { $$ = make_assign_op (EMUL_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (EMUL_EQ, $1, $2, $3); } | assign_lhs EDIV_EQ expression - { $$ = make_assign_op (EDIV_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (EDIV_EQ, $1, $2, $3); } | assign_lhs ELEFTDIV_EQ expression - { $$ = make_assign_op (ELEFTDIV_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (ELEFTDIV_EQ, $1, $2, $3); } | assign_lhs EPOW_EQ expression - { $$ = make_assign_op (EPOW_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (EPOW_EQ, $1, $2, $3); } | assign_lhs AND_EQ expression - { $$ = make_assign_op (AND_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (AND_EQ, $1, $2, $3); } | assign_lhs OR_EQ expression - { $$ = make_assign_op (OR_EQ, $1, $2, $3); } + { $$ = curr_parser->make_assign_op (OR_EQ, $1, $2, $3); } ; expression : simple_expr @@ -1076,17 +813,17 @@ parsing_decl_list : // empty - { lexer_flags.looking_at_decl_list = true; } + { curr_lexer->looking_at_decl_list = true; } declaration : GLOBAL parsing_decl_list decl1 { - $$ = make_decl_command (GLOBAL, $1, $3); - lexer_flags.looking_at_decl_list = false; + $$ = curr_parser->make_decl_command (GLOBAL, $1, $3); + curr_lexer->looking_at_decl_list = false; } | PERSISTENT parsing_decl_list decl1 { - $$ = make_decl_command (PERSISTENT, $1, $3); - lexer_flags.looking_at_decl_list = false; + $$ = curr_parser->make_decl_command (PERSISTENT, $1, $3); + curr_lexer->looking_at_decl_list = false; } ; @@ -1100,13 +837,13 @@ ; decl_param_init : // empty - { lexer_flags.looking_at_initializer_expression = true; } + { curr_lexer->looking_at_initializer_expression = true; } decl2 : identifier { $$ = new tree_decl_elt ($1); } | identifier '=' decl_param_init expression { - lexer_flags.looking_at_initializer_expression = false; + curr_lexer->looking_at_initializer_expression = false; $$ = new tree_decl_elt ($1, $4); } | magic_tilde @@ -1131,7 +868,7 @@ if_command : IF stash_comment if_cmd_list END { - if (! ($$ = finish_if_command ($1, $3, $4, $2))) + if (! ($$ = curr_parser->finish_if_command ($1, $3, $4, $2))) ABORT_PARSE; } ; @@ -1149,7 +886,7 @@ { $1->mark_braindead_shortcircuit (curr_fcn_file_full_name); - $$ = start_if_command ($1, $3); + $$ = curr_parser->start_if_command ($1, $3); } | if_cmd_list1 elseif_clause { @@ -1162,7 +899,7 @@ { $4->mark_braindead_shortcircuit (curr_fcn_file_full_name); - $$ = make_elseif_clause ($1, $4, $6, $2); + $$ = curr_parser->make_elseif_clause ($1, $4, $6, $2); } ; @@ -1176,7 +913,7 @@ switch_command : SWITCH stash_comment expression opt_sep case_list END { - if (! ($$ = finish_switch_command ($1, $3, $5, $6, $2))) + if (! ($$ = curr_parser->finish_switch_command ($1, $3, $5, $6, $2))) ABORT_PARSE; } ; @@ -1204,7 +941,7 @@ ; switch_case : CASE stash_comment opt_sep expression opt_sep opt_list - { $$ = make_switch_case ($1, $4, $6, $2); } + { $$ = curr_parser->make_switch_case ($1, $4, $6, $2); } ; default_case : OTHERWISE stash_comment opt_sep opt_list @@ -1221,35 +958,35 @@ { $3->mark_braindead_shortcircuit (curr_fcn_file_full_name); - if (! ($$ = make_while_command ($1, $3, $5, $6, $2))) + if (! ($$ = curr_parser->make_while_command ($1, $3, $5, $6, $2))) ABORT_PARSE; } | DO stash_comment opt_sep opt_list UNTIL expression { - if (! ($$ = make_do_until_command ($5, $4, $6, $2))) + if (! ($$ = curr_parser->make_do_until_command ($5, $4, $6, $2))) ABORT_PARSE; } | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END { - if (! ($$ = make_for_command (FOR, $1, $3, $5, 0, + if (! ($$ = curr_parser->make_for_command (FOR, $1, $3, $5, 0, $7, $8, $2))) ABORT_PARSE; } | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END { - if (! ($$ = make_for_command (FOR, $1, $4, $6, 0, + if (! ($$ = curr_parser->make_for_command (FOR, $1, $4, $6, 0, $9, $10, $2))) ABORT_PARSE; } | PARFOR stash_comment assign_lhs '=' expression opt_sep opt_list END { - if (! ($$ = make_for_command (PARFOR, $1, $3, $5, + if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $3, $5, 0, $7, $8, $2))) ABORT_PARSE; } | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END { - if (! ($$ = make_for_command (PARFOR, $1, $4, $6, + if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $4, $6, $8, $11, $12, $2))) ABORT_PARSE; } @@ -1261,17 +998,17 @@ jump_command : BREAK { - if (! ($$ = make_break_command ($1))) + if (! ($$ = curr_parser->make_break_command ($1))) ABORT_PARSE; } | CONTINUE { - if (! ($$ = make_continue_command ($1))) + if (! ($$ = curr_parser->make_continue_command ($1))) ABORT_PARSE; } | FUNC_RET { - if (! ($$ = make_return_command ($1))) + if (! ($$ = curr_parser->make_return_command ($1))) ABORT_PARSE; } ; @@ -1283,18 +1020,18 @@ except_command : UNWIND stash_comment opt_sep opt_list CLEANUP stash_comment opt_sep opt_list END { - if (! ($$ = make_unwind_command ($1, $4, $8, $9, $2, $6))) + if (! ($$ = curr_parser->make_unwind_command ($1, $4, $8, $9, $2, $6))) ABORT_PARSE; } | TRY stash_comment opt_sep opt_list CATCH stash_comment opt_sep opt_list END { - if (! ($$ = make_try_command ($1, $4, $8, $9, $2, $6))) + if (! ($$ = curr_parser->make_try_command ($1, $4, $8, $9, $2, $6))) ABORT_PARSE; } | TRY stash_comment opt_sep opt_list END { - if (! ($$ = make_try_command ($1, $4, 0, $5, $2, 0))) + if (! ($$ = curr_parser->make_try_command ($1, $4, 0, $5, $2, 0))) ABORT_PARSE; } ; @@ -1305,23 +1042,23 @@ push_fcn_symtab : // empty { - current_function_depth++; - - if (max_function_depth < current_function_depth) - max_function_depth = current_function_depth; + curr_parser->curr_fcn_depth++; + + if (curr_parser->max_fcn_depth < curr_parser->curr_fcn_depth) + curr_parser->max_fcn_depth = curr_parser->curr_fcn_depth; parser_symtab_context.push (); symbol_table::set_scope (symbol_table::alloc_scope ()); - function_scopes.push_back (symbol_table::current_scope ()); - - if (! reading_script_file && current_function_depth == 1 - && ! parsing_subfunctions) - primary_fcn_scope = symbol_table::current_scope (); - - if (reading_script_file && current_function_depth > 1) - yyerror ("nested functions not implemented in this context"); + curr_parser->function_scopes.push_back (symbol_table::current_scope ()); + + if (! reading_script_file && curr_parser->curr_fcn_depth == 1 + && ! curr_parser->parsing_subfunctions) + curr_parser->primary_fcn_scope = symbol_table::current_scope (); + + if (reading_script_file && curr_parser->curr_fcn_depth > 1) + curr_parser->bison_error ("nested functions not implemented in this context"); } ; @@ -1331,33 +1068,33 @@ param_list_beg : '(' { - lexer_flags.looking_at_parameter_list = true; - - if (lexer_flags.looking_at_function_handle) + curr_lexer->looking_at_parameter_list = true; + + if (curr_lexer->looking_at_function_handle) { parser_symtab_context.push (); symbol_table::set_scope (symbol_table::alloc_scope ()); - lexer_flags.looking_at_function_handle--; - lexer_flags.looking_at_anon_fcn_args = true; + curr_lexer->looking_at_function_handle--; + curr_lexer->looking_at_anon_fcn_args = true; } } ; param_list_end : ')' { - lexer_flags.looking_at_parameter_list = false; - lexer_flags.looking_for_object_index = false; + curr_lexer->looking_at_parameter_list = false; + curr_lexer->looking_for_object_index = false; } ; param_list : param_list_beg param_list1 param_list_end { - lexer_flags.quote_is_transpose = false; + curr_lexer->quote_is_transpose = false; $$ = $2; } | param_list_beg error { - yyerror ("invalid parameter list"); + curr_parser->bison_error ("invalid parameter list"); $$ = 0; ABORT_PARSE; } @@ -1390,12 +1127,12 @@ return_list : '[' ']' { - lexer_flags.looking_at_return_list = false; + curr_lexer->looking_at_return_list = false; $$ = new tree_parameter_list (); } | return_list1 { - lexer_flags.looking_at_return_list = false; + curr_lexer->looking_at_return_list = false; if ($1->validate (tree_parameter_list::out)) $$ = $1; else @@ -1403,7 +1140,7 @@ } | '[' return_list1 ']' { - lexer_flags.looking_at_return_list = false; + curr_lexer->looking_at_return_list = false; if ($2->validate (tree_parameter_list::out)) $$ = $2; else @@ -1427,10 +1164,11 @@ script_file : SCRIPT_FILE opt_list END_OF_INPUT { tree_statement *end_of_script - = make_end ("endscript", input_line_number, - current_input_column); - - make_script ($2, end_of_script); + = curr_parser->make_end ("endscript", + curr_lexer->input_line_number, + curr_lexer->current_input_column); + + curr_parser->make_script ($2, end_of_script); $$ = 0; } @@ -1456,20 +1194,20 @@ { $$ = $3; - if (reading_classdef_file || lexer_flags.parsing_classdef) - lexer_flags.maybe_classdef_get_set_method = true; + if (reading_classdef_file || curr_lexer->parsing_classdef) + curr_lexer->maybe_classdef_get_set_method = true; } ; function : function_beg function1 { - $$ = finish_function (0, $2, $1); - recover_from_parsing_function (); + $$ = curr_parser->finish_function (0, $2, $1); + curr_parser->recover_from_parsing_function (); } | function_beg return_list '=' function1 { - $$ = finish_function ($2, $4, $1); - recover_from_parsing_function (); + $$ = curr_parser->finish_function ($2, $4, $1); + curr_parser->recover_from_parsing_function (); } ; @@ -1477,23 +1215,23 @@ { std::string id_name = $1->name (); - lexer_flags.parsed_function_name.top () = true; - lexer_flags.maybe_classdef_get_set_method = false; + curr_lexer->parsed_function_name.top () = true; + curr_lexer->maybe_classdef_get_set_method = false; $$ = $1; } | GET '.' identifier { - lexer_flags.parsed_function_name.top () = true; - lexer_flags.maybe_classdef_get_set_method = false; - lexer_flags.parsing_classdef_get_method = true; + curr_lexer->parsed_function_name.top () = true; + curr_lexer->maybe_classdef_get_set_method = false; + curr_lexer->parsing_classdef_get_method = true; $$ = $3; } | SET '.' identifier { - lexer_flags.parsed_function_name.top () = true; - lexer_flags.maybe_classdef_get_set_method = false; - lexer_flags.parsing_classdef_set_method = true; + curr_lexer->parsed_function_name.top () = true; + curr_lexer->maybe_classdef_get_set_method = false; + curr_lexer->parsing_classdef_set_method = true; $$ = $3; } ; @@ -1504,22 +1242,22 @@ delete $1; - if (! ($$ = frob_function (fname, $2))) + if (! ($$ = curr_parser->frob_function (fname, $2))) ABORT_PARSE; } ; function2 : param_list opt_sep opt_list function_end - { $$ = start_function ($1, $3, $4); } + { $$ = curr_parser->start_function ($1, $3, $4); } | opt_sep opt_list function_end - { $$ = start_function (0, $2, $3); } + { $$ = curr_parser->start_function (0, $2, $3); } ; function_end : END { - endfunction_found = true; - if (end_token_ok ($1, token::function_end)) - $$ = make_end ("endfunction", $1->line (), $1->column ()); + curr_parser->endfunction_found = true; + if (curr_parser->end_token_ok ($1, token::function_end)) + $$ = curr_parser->make_end ("endfunction", $1->line (), $1->column ()); else ABORT_PARSE; } @@ -1528,13 +1266,13 @@ // A lot of tests are based on the assumption that this is OK // if (reading_script_file) // { -// yyerror ("function body open at end of script"); +// curr_parser->bison_error ("function body open at end of script"); // YYABORT; // } - if (endfunction_found) + if (curr_parser->endfunction_found) { - yyerror ("inconsistent function endings -- " + curr_parser->bison_error ("inconsistent function endings -- " "if one function is explicitly ended, " "so must all the others"); YYABORT; @@ -1543,18 +1281,19 @@ if (! (reading_fcn_file || reading_script_file || get_input_from_eval_string)) { - yyerror ("function body open at end of input"); + curr_parser->bison_error ("function body open at end of input"); YYABORT; } if (reading_classdef_file) { - yyerror ("classdef body open at end of input"); + curr_parser->bison_error ("classdef body open at end of input"); YYABORT; } - $$ = make_end ("endfunction", input_line_number, - current_input_column); + $$ = curr_parser->make_end ("endfunction", + curr_lexer->input_line_number, + curr_lexer->current_input_column); } ; @@ -1564,7 +1303,7 @@ classdef_file : CLASSDEF_FILE classdef opt_sep END_OF_INPUT { - classdef_object = $2; + curr_parser->classdef_object = $2; $$ = 0; } ; @@ -1577,19 +1316,19 @@ { if (! reading_classdef_file) { - yyerror ("classdef must appear inside a file containing only a class definition"); + curr_parser->bison_error ("classdef must appear inside a file containing only a class definition"); YYABORT; } - lexer_flags.parsing_classdef = true; + curr_lexer->parsing_classdef = true; $$ = $1; } ; classdef : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END { - lexer_flags.parsing_classdef = false; - if (! ($$ = make_classdef ($1, $3, $4, $5, $7, $9, $2))) + curr_lexer->parsing_classdef = false; + if (! ($$ = curr_parser->make_classdef ($1, $3, $4, $5, $7, $9, $2))) ABORT_PARSE; } ; @@ -1613,7 +1352,7 @@ { $$ = new tree_classdef_attribute ($1); } | identifier '=' decl_param_init expression { - lexer_flags.looking_at_initializer_expression = false; + curr_lexer->looking_at_initializer_expression = false; $$ = new tree_classdef_attribute ($1, $4); } | EXPR_NOT identifier @@ -1675,7 +1414,8 @@ properties_block : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END { - if (! ($$ = make_classdef_properties_block ($1, $3, $5, $7, $2))) + if (! ($$ = curr_parser->make_classdef_properties_block + ($1, $3, $5, $7, $2))) ABORT_PARSE; } ; @@ -1694,14 +1434,15 @@ { $$ = new tree_classdef_property ($1); } | identifier '=' decl_param_init expression ';' { - lexer_flags.looking_at_initializer_expression = false; + curr_lexer->looking_at_initializer_expression = false; $$ = new tree_classdef_property ($1, $4); } ; methods_block : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END { - if (! ($$ = make_classdef_methods_block ($1, $3, $5, $7, $2))) + if (! ($$ = curr_parser->make_classdef_methods_block + ($1, $3, $5, $7, $2))) ABORT_PARSE; } ; @@ -1728,7 +1469,8 @@ events_block : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END { - if (! ($$ = make_classdef_events_block ($1, $3, $5, $7, $2))) + if (! ($$ = curr_parser->make_classdef_events_block + ($1, $3, $5, $7, $2))) ABORT_PARSE; } ; @@ -1748,7 +1490,8 @@ enum_block : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END { - if (! ($$ = make_classdef_enum_block ($1, $3, $5, $7, $2))) + if (! ($$ = curr_parser->make_classdef_enum_block + ($1, $3, $5, $7, $2))) ABORT_PARSE; } ; @@ -1775,7 +1518,7 @@ ; parse_error : LEXICAL_ERROR - { yyerror ("parse error"); } + { curr_parser->bison_error ("parse error"); } | error ; @@ -1825,55 +1568,25 @@ // Generic error messages. +#undef curr_lexer + static void -yyerror (const char *s) +yyerror (octave_parser *curr_parser, const char *s) { - int err_col = current_input_column - 1; - - std::ostringstream output_buf; - - if (reading_fcn_file || reading_script_file || reading_classdef_file) - output_buf << "parse error near line " << input_line_number - << " of file " << curr_fcn_file_full_name; - else - output_buf << "parse error:"; - - if (s && strcmp (s, "parse error") != 0) - output_buf << "\n\n " << s; - - output_buf << "\n\n"; - - if (! current_input_line.empty ()) - { - size_t len = current_input_line.length (); - - if (current_input_line[len-1] == '\n') - current_input_line.resize (len-1); - - // Print the line, maybe with a pointer near the error token. - - output_buf << ">>> " << current_input_line << "\n"; - - if (err_col == 0) - err_col = len; - - for (int i = 0; i < err_col + 3; i++) - output_buf << " "; - - output_buf << "^"; - } - - output_buf << "\n"; - - std::string msg = output_buf.str (); - - parse_error ("%s", msg.c_str ()); + curr_parser->bison_error (s); +} + +int +octave_parser::run (void) +{ + return octave_parse (this); } // Error mesages for mismatched end tokens. -static void -end_error (const char *type, token::end_tok_type ettype, int l, int c) +void +octave_parser::end_error (const char *type, token::end_tok_type ettype, + int l, int c) { static const char *fmt = "'%s' command matched by '%s' near line %d column %d"; @@ -1924,8 +1637,8 @@ // Check to see that end tokens are properly matched. -static bool -end_token_ok (token *tok, token::end_tok_type expected) +bool +octave_parser::end_token_ok (token *tok, token::end_tok_type expected) { bool retval = true; @@ -1935,7 +1648,7 @@ { retval = false; - yyerror ("parse error"); + bison_error ("parse error"); int l = tok->line (); int c = tok->column (); @@ -1994,8 +1707,8 @@ // Maybe print a warning if an assignment expression is used as the // test in a logical expression. -static void -maybe_warn_assign_as_truth_value (tree_expression *expr) +void +octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr) { if (expr->is_assignment_expression () && expr->paren_count () < 2) @@ -2014,8 +1727,8 @@ // Maybe print a warning about switch labels that aren't constants. -static void -maybe_warn_variable_switch_label (tree_expression *expr) +void +octave_parser::maybe_warn_variable_switch_label (tree_expression *expr) { if (! expr->is_constant ()) { @@ -2121,8 +1834,8 @@ // Finish building a range. -static tree_expression * -finish_colon_expression (tree_colon_expression *e) +tree_expression * +octave_parser::finish_colon_expression (tree_colon_expression *e) { tree_expression *retval = e; @@ -2185,8 +1898,8 @@ // Make a constant. -static tree_constant * -make_constant (int op, token *tok_val) +tree_constant * +octave_parser::make_constant (int op, token *tok_val) { int l = tok_val->line (); int c = tok_val->column (); @@ -2248,8 +1961,8 @@ // Make a function handle. -static tree_fcn_handle * -make_fcn_handle (token *tok_val) +tree_fcn_handle * +octave_parser::make_fcn_handle (token *tok_val) { int l = tok_val->line (); int c = tok_val->column (); @@ -2261,12 +1974,13 @@ // Make an anonymous function handle. -static tree_anon_fcn_handle * -make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt) +tree_anon_fcn_handle * +octave_parser::make_anon_fcn_handle (tree_parameter_list *param_list, + tree_statement *stmt) { // FIXME -- need to get these from the location of the @ symbol. - int l = input_line_number; - int c = current_input_column; + int l = curr_lexer->input_line_number; + int c = curr_lexer->current_input_column; tree_parameter_list *ret_list = 0; @@ -2294,9 +2008,9 @@ // Build a binary expression. -static tree_expression * -make_binary_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2) +tree_expression * +octave_parser::make_binary_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2) { octave_value::binary_op t = octave_value::unknown_binary_op; @@ -2398,9 +2112,9 @@ // Build a boolean expression. -static tree_expression * -make_boolean_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2) +tree_expression * +octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2) { tree_boolean_expression::type t; @@ -2430,8 +2144,8 @@ // Build a prefix expression. -static tree_expression * -make_prefix_op (int op, tree_expression *op1, token *tok_val) +tree_expression * +octave_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val) { octave_value::unary_op t = octave_value::unknown_unary_op; @@ -2473,8 +2187,8 @@ // Build a postfix expression. -static tree_expression * -make_postfix_op (int op, tree_expression *op1, token *tok_val) +tree_expression * +octave_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val) { octave_value::unary_op t = octave_value::unknown_unary_op; @@ -2512,10 +2226,13 @@ // Build an unwind-protect command. -static tree_command * -make_unwind_command (token *unwind_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, - octave_comment_list *lc, octave_comment_list *mc) +tree_command * +octave_parser::make_unwind_command (token *unwind_tok, + tree_statement_list *body, + tree_statement_list *cleanup_stmts, + token *end_tok, + octave_comment_list *lc, + octave_comment_list *mc) { tree_command *retval = 0; @@ -2526,7 +2243,7 @@ int l = unwind_tok->line (); int c = unwind_tok->column (); - retval = new tree_unwind_protect_command (body, cleanup, + retval = new tree_unwind_protect_command (body, cleanup_stmts, lc, mc, tc, l, c); } @@ -2535,10 +2252,12 @@ // Build a try-catch command. -static tree_command * -make_try_command (token *try_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, - octave_comment_list *lc, octave_comment_list *mc) +tree_command * +octave_parser::make_try_command (token *try_tok, tree_statement_list *body, + tree_statement_list *cleanup_stmts, + token *end_tok, + octave_comment_list *lc, + octave_comment_list *mc) { tree_command *retval = 0; @@ -2549,7 +2268,7 @@ int l = try_tok->line (); int c = try_tok->column (); - retval = new tree_try_catch_command (body, cleanup, + retval = new tree_try_catch_command (body, cleanup_stmts, lc, mc, tc, l, c); } @@ -2558,10 +2277,10 @@ // Build a while command. -static tree_command * -make_while_command (token *while_tok, tree_expression *expr, - tree_statement_list *body, token *end_tok, - octave_comment_list *lc) +tree_command * +octave_parser::make_while_command (token *while_tok, tree_expression *expr, + tree_statement_list *body, token *end_tok, + octave_comment_list *lc) { tree_command *retval = 0; @@ -2571,7 +2290,7 @@ { octave_comment_list *tc = octave_comment_buffer::get_comment (); - lexer_flags.looping--; + curr_lexer->looping--; int l = while_tok->line (); int c = while_tok->column (); @@ -2584,9 +2303,11 @@ // Build a do-until command. -static tree_command * -make_do_until_command (token *until_tok, tree_statement_list *body, - tree_expression *expr, octave_comment_list *lc) +tree_command * +octave_parser::make_do_until_command (token *until_tok, + tree_statement_list *body, + tree_expression *expr, + octave_comment_list *lc) { tree_command *retval = 0; @@ -2594,7 +2315,7 @@ octave_comment_list *tc = octave_comment_buffer::get_comment (); - lexer_flags.looping--; + curr_lexer->looping--; int l = until_tok->line (); int c = until_tok->column (); @@ -2606,11 +2327,13 @@ // Build a for command. -static tree_command * -make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs, - tree_expression *expr, tree_expression *maxproc, - tree_statement_list *body, token *end_tok, - octave_comment_list *lc) +tree_command * +octave_parser::make_for_command (int tok_id, token *for_tok, + tree_argument_list *lhs, + tree_expression *expr, + tree_expression *maxproc, + tree_statement_list *body, token *end_tok, + octave_comment_list *lc) { tree_command *retval = 0; @@ -2620,7 +2343,7 @@ { octave_comment_list *tc = octave_comment_buffer::get_comment (); - lexer_flags.looping--; + curr_lexer->looping--; int l = for_tok->line (); int c = for_tok->column (); @@ -2637,7 +2360,7 @@ else { if (parfor) - yyerror ("invalid syntax for parfor statement"); + bison_error ("invalid syntax for parfor statement"); else retval = new tree_complex_for_command (lhs, expr, body, lc, tc, l, c); @@ -2649,8 +2372,8 @@ // Build a break command. -static tree_command * -make_break_command (token *break_tok) +tree_command * +octave_parser::make_break_command (token *break_tok) { tree_command *retval = 0; @@ -2664,8 +2387,8 @@ // Build a continue command. -static tree_command * -make_continue_command (token *continue_tok) +tree_command * +octave_parser::make_continue_command (token *continue_tok) { tree_command *retval = 0; @@ -2679,8 +2402,8 @@ // Build a return command. -static tree_command * -make_return_command (token *return_tok) +tree_command * +octave_parser::make_return_command (token *return_tok) { tree_command *retval = 0; @@ -2694,8 +2417,9 @@ // Start an if command. -static tree_if_command_list * -start_if_command (tree_expression *expr, tree_statement_list *list) +tree_if_command_list * +octave_parser::start_if_command (tree_expression *expr, + tree_statement_list *list) { maybe_warn_assign_as_truth_value (expr); @@ -2706,9 +2430,9 @@ // Finish an if command. -static tree_if_command * -finish_if_command (token *if_tok, tree_if_command_list *list, - token *end_tok, octave_comment_list *lc) +tree_if_command * +octave_parser::finish_if_command (token *if_tok, tree_if_command_list *list, + token *end_tok, octave_comment_list *lc) { tree_if_command *retval = 0; @@ -2738,9 +2462,10 @@ // Build an elseif clause. -static tree_if_clause * -make_elseif_clause (token *elseif_tok, tree_expression *expr, - tree_statement_list *list, octave_comment_list *lc) +tree_if_clause * +octave_parser::make_elseif_clause (token *elseif_tok, tree_expression *expr, + tree_statement_list *list, + octave_comment_list *lc) { maybe_warn_assign_as_truth_value (expr); @@ -2752,10 +2477,10 @@ // Finish a switch command. -static tree_switch_command * -finish_switch_command (token *switch_tok, tree_expression *expr, - tree_switch_case_list *list, token *end_tok, - octave_comment_list *lc) +tree_switch_command * +octave_parser::finish_switch_command (token *switch_tok, tree_expression *expr, + tree_switch_case_list *list, + token *end_tok, octave_comment_list *lc) { tree_switch_command *retval = 0; @@ -2785,9 +2510,10 @@ // Build a switch case. -static tree_switch_case * -make_switch_case (token *case_tok, tree_expression *expr, - tree_statement_list *list, octave_comment_list *lc) +tree_switch_case * +octave_parser::make_switch_case (token *case_tok, tree_expression *expr, + tree_statement_list *list, + octave_comment_list *lc) { maybe_warn_variable_switch_label (expr); @@ -2799,9 +2525,9 @@ // Build an assignment to a variable. -static tree_expression * -make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, - tree_expression *rhs) +tree_expression * +octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, + tree_expression *rhs) { tree_expression *retval = 0; @@ -2888,15 +2614,16 @@ else if (t == octave_value::op_asn_eq) return new tree_multi_assignment (lhs, rhs, false, l, c); else - yyerror ("computed multiple assignment not allowed"); + bison_error ("computed multiple assignment not allowed"); return retval; } // Define a script. -static void -make_script (tree_statement_list *cmds, tree_statement *end_script) +void +octave_parser::make_script (tree_statement_list *cmds, + tree_statement *end_script) { std::string doc_string; @@ -2929,9 +2656,10 @@ // Begin defining a function. -static octave_user_function * -start_function (tree_parameter_list *param_list, tree_statement_list *body, - tree_statement *end_fcn_stmt) +octave_user_function * +octave_parser::start_function (tree_parameter_list *param_list, + tree_statement_list *body, + tree_statement *end_fcn_stmt) { // We'll fill in the return list later. @@ -2954,16 +2682,17 @@ return fcn; } -static tree_statement * -make_end (const std::string& type, int l, int c) +tree_statement * +octave_parser::make_end (const std::string& type, int l, int c) { return make_statement (new tree_no_op_command (type, l, c)); } // Do most of the work for defining a function. -static octave_user_function * -frob_function (const std::string& fname, octave_user_function *fcn) +octave_user_function * +octave_parser::frob_function (const std::string& fname, + octave_user_function *fcn) { std::string id_name = fname; @@ -2972,7 +2701,7 @@ // file. Matlab doesn't provide a diagnostic (it ignores the stated // name). if (! autoloading && reading_fcn_file - && current_function_depth == 1 && ! parsing_subfunctions) + && curr_fcn_depth == 1 && ! parsing_subfunctions) { // FIXME -- should curr_fcn_file_name already be // preprocessed when we get here? It seems to only be a @@ -3007,24 +2736,24 @@ if (fcn_file_from_relative_lookup) fcn->mark_relative (); - if (current_function_depth > 1 || parsing_subfunctions) + if (curr_fcn_depth > 1 || parsing_subfunctions) { fcn->stash_parent_fcn_name (curr_fcn_file_name); - if (current_function_depth > 1) + if (curr_fcn_depth > 1) fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]); else fcn->stash_parent_fcn_scope (primary_fcn_scope); } - if (lexer_flags.parsing_class_method) + if (curr_lexer->parsing_class_method) { - if (current_class_name == id_name) + if (curr_class_name == id_name) fcn->mark_as_class_constructor (); else fcn->mark_as_class_method (); - fcn->stash_dispatch_class (current_class_name); + fcn->stash_dispatch_class (curr_class_name); } std::string nm = fcn->fcn_file_name (); @@ -3044,9 +2773,10 @@ } fcn->stash_function_name (id_name); - fcn->stash_fcn_location (input_line_number, current_input_column); - - if (! help_buf.empty () && current_function_depth == 1 + fcn->stash_fcn_location (curr_lexer->input_line_number, + curr_lexer->current_input_column); + + if (! help_buf.empty () && curr_fcn_depth == 1 && ! parsing_subfunctions) { fcn->document (help_buf.top ()); @@ -3054,16 +2784,17 @@ help_buf.pop (); } - if (reading_fcn_file && current_function_depth == 1 + if (reading_fcn_file && curr_fcn_depth == 1 && ! parsing_subfunctions) primary_fcn_ptr = fcn; return fcn; } -static tree_function_def * -finish_function (tree_parameter_list *ret_list, - octave_user_function *fcn, octave_comment_list *lc) +tree_function_def * +octave_parser::finish_function (tree_parameter_list *ret_list, + octave_user_function *fcn, + octave_comment_list *lc) { tree_function_def *retval = 0; @@ -3086,7 +2817,7 @@ fcn->define_ret_list (ret_list); - if (current_function_depth > 1 || parsing_subfunctions) + if (curr_fcn_depth > 1 || parsing_subfunctions) { fcn->mark_as_subfunction (); @@ -3103,10 +2834,10 @@ primary_fcn_scope); } - if (current_function_depth == 1 && fcn) + if (curr_fcn_depth == 1 && fcn) symbol_table::update_nest (fcn->scope ()); - if (! reading_fcn_file && current_function_depth == 1) + if (! reading_fcn_file && curr_fcn_depth == 1) { // We are either reading a script file or defining a function // at the command line, so this definition creates a @@ -3131,38 +2862,204 @@ return retval; } -static void -recover_from_parsing_function (void) +void +octave_parser::recover_from_parsing_function (void) { if (parser_symtab_context.empty ()) panic_impossible (); parser_symtab_context.pop (); - if (reading_fcn_file && current_function_depth == 1 + if (reading_fcn_file && curr_fcn_depth == 1 && ! parsing_subfunctions) parsing_subfunctions = true; - current_function_depth--; + curr_fcn_depth--; function_scopes.pop_back (); - lexer_flags.defining_func--; - lexer_flags.parsed_function_name.pop (); - lexer_flags.looking_at_return_list = false; - lexer_flags.looking_at_parameter_list = false; + curr_lexer->defining_func--; + curr_lexer->parsed_function_name.pop (); + curr_lexer->looking_at_return_list = false; + curr_lexer->looking_at_parameter_list = false; +} + +tree_funcall * +octave_parser::make_superclass_ref (const std::string& method_nm, + const std::string& package_nm, + const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(2) = class_nm; + args(1) = package_nm; + args(0) = method_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__superclass_reference__"); + + return new tree_funcall (fcn, args); +} + +tree_funcall * +octave_parser::make_meta_class_query (const std::string& package_nm, + const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(1) = class_nm; + args(0) = package_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__meta_class_query__"); + + return new tree_funcall (fcn, args); +} + +// A CLASSDEF block defines a class that has a constructor and other +// methods, but it is not an executable command. Parsing the block +// makes some changes in the symbol table (inserting the constructor +// and methods, and adding to the list of known objects) and creates +// a parse tree containing meta information about the class. + +tree_classdef * +octave_parser::make_classdef (token *tok_val, + tree_classdef_attribute_list *a, + tree_identifier *id, + tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + octave_comment_list *lc) +{ + tree_classdef *retval = 0; + + std::string cls_name = id->name (); + + std::string nm = curr_fcn_file_name; + + size_t pos = nm.find_last_of (file_ops::dir_sep_chars ()); + + if (pos != std::string::npos) + nm = curr_fcn_file_name.substr (pos+1); + + if (nm != cls_name) + { + bison_error ("invalid classdef definition, the class name must match the file name"); + return retval; + } + + if (end_token_ok (end_tok, token::classdef_end)) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef (a, id, sc, body, lc, tc, l, c); + } + + return retval; +} + +tree_classdef_properties_block * +octave_parser::make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_properties_block *retval = 0; + + if (end_token_ok (end_tok, token::properties_end)) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); + } + + return retval; +} + +tree_classdef_methods_block * +octave_parser::make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_methods_block *retval = 0; + + if (end_token_ok (end_tok, token::methods_end)) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c); + } + + return retval; +} + +tree_classdef_events_block * +octave_parser::make_classdef_events_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_events_block *retval = 0; + + if (end_token_ok (end_tok, token::events_end)) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_events_block (a, elist, lc, tc, l, c); + } + + return retval; +} + +tree_classdef_enum_block * +octave_parser::make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_enum_block *retval = 0; + + if (end_token_ok (end_tok, token::enumeration_end)) + { + octave_comment_list *tc = octave_comment_buffer::get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c); + } + + return retval; } // Make an index expression. -static tree_index_expression * -make_index_expression (tree_expression *expr, tree_argument_list *args, - char type) +tree_index_expression * +octave_parser::make_index_expression (tree_expression *expr, + tree_argument_list *args, char type) { tree_index_expression *retval = 0; if (args && args->has_magic_tilde ()) { - yyerror ("invalid use of empty argument (~) in index expression"); + bison_error ("invalid use of empty argument (~) in index expression"); return retval; } @@ -3188,8 +3085,9 @@ // Make an indirect reference expression. -static tree_index_expression * -make_indirect_ref (tree_expression *expr, const std::string& elt) +tree_index_expression * +octave_parser::make_indirect_ref (tree_expression *expr, + const std::string& elt) { tree_index_expression *retval = 0; @@ -3210,15 +3108,15 @@ else retval = new tree_index_expression (expr, elt, l, c); - lexer_flags.looking_at_indirect_ref = false; + curr_lexer->looking_at_indirect_ref = false; return retval; } // Make an indirect reference expression with dynamic field name. -static tree_index_expression * -make_indirect_ref (tree_expression *expr, tree_expression *elt) +tree_index_expression * +octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt) { tree_index_expression *retval = 0; @@ -3239,15 +3137,16 @@ else retval = new tree_index_expression (expr, elt, l, c); - lexer_flags.looking_at_indirect_ref = false; + curr_lexer->looking_at_indirect_ref = false; return retval; } // Make a declaration command. -static tree_decl_command * -make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst) +tree_decl_command * +octave_parser::make_decl_command (int tok, token *tok_val, + tree_decl_init_list *lst) { tree_decl_command *retval = 0; @@ -3261,7 +3160,7 @@ break; case PERSISTENT: - if (current_function_depth > 0) + if (curr_fcn_depth > 0) retval = new tree_persistent_command (lst, l, c); else { @@ -3281,18 +3180,18 @@ return retval; } -static tree_argument_list * -validate_matrix_row (tree_argument_list *row) +tree_argument_list * +octave_parser::validate_matrix_row (tree_argument_list *row) { if (row && row->has_magic_tilde ()) - yyerror ("invalid use of tilde (~) in matrix expression"); + bison_error ("invalid use of tilde (~) in matrix expression"); return row; } // Finish building a matrix list. -static tree_expression * -finish_matrix (tree_matrix *m) +tree_expression * +octave_parser::finish_matrix (tree_matrix *m) { tree_expression *retval = m; @@ -3335,16 +3234,16 @@ // Finish building a cell list. -static tree_expression * -finish_cell (tree_cell *c) +tree_expression * +octave_parser::finish_cell (tree_cell *c) { return finish_matrix (c); } -static void -maybe_warn_missing_semi (tree_statement_list *t) +void +octave_parser::maybe_warn_missing_semi (tree_statement_list *t) { - if (current_function_depth > 0) + if (curr_fcn_depth > 0) { tree_statement *tmp = t->back (); @@ -3356,9 +3255,9 @@ } } -static tree_statement_list * -set_stmt_print_flag (tree_statement_list *list, char sep, - bool warn_missing_semi) +tree_statement_list * +octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep, + bool warn_missing_semi) { tree_statement *tmp = list->back (); @@ -3393,15 +3292,16 @@ return list; } -static tree_statement_list * -make_statement_list (tree_statement *stmt) +tree_statement_list * +octave_parser::make_statement_list (tree_statement *stmt) { return new tree_statement_list (stmt); } -static tree_statement_list * -append_statement_list (tree_statement_list *list, char sep, - tree_statement *stmt, bool warn_missing_semi) +tree_statement_list * +octave_parser::append_statement_list (tree_statement_list *list, char sep, + tree_statement *stmt, + bool warn_missing_semi) { set_stmt_print_flag (list, sep, warn_missing_semi); @@ -3410,164 +3310,50 @@ return list; } -static tree_funcall * -make_superclass_ref (const std::string& method_nm, - const std::string& package_nm, - const std::string& class_nm, - int l, int c) -{ - octave_value_list args; - - args(2) = class_nm; - args(1) = package_nm; - args(0) = method_nm; - - octave_value fcn - = symbol_table::find_built_in_function ("__superclass_reference__"); - - return new tree_funcall (fcn, args); -} - -static tree_funcall * -make_meta_class_query (const std::string& package_nm, - const std::string& class_nm, - int l, int c) +void +octave_parser::bison_error (const char *s) + { - octave_value_list args; - - args(1) = class_nm; - args(0) = package_nm; - - octave_value fcn - = symbol_table::find_built_in_function ("__meta_class_query__"); - - return new tree_funcall (fcn, args); -} - -// A CLASSDEF block defines a class that has a constructor and other -// methods, but it is not an executable command. Parsing the block -// makes some changes in the symbol table (inserting the constructor -// and methods, and adding to the list of known objects) and creates -// a parse tree containing meta information about the class. - -static tree_classdef * -make_classdef (token *tok_val, tree_classdef_attribute_list *a, - tree_identifier *id, tree_classdef_superclass_list *sc, - tree_classdef_body *body, token *end_tok, - octave_comment_list *lc) -{ - tree_classdef *retval = 0; - - std::string cls_name = id->name (); - - std::string nm = curr_fcn_file_name; - - size_t pos = nm.find_last_of (file_ops::dir_sep_chars ()); - - if (pos != std::string::npos) - nm = curr_fcn_file_name.substr (pos+1); - - if (nm != cls_name) + int err_col = curr_lexer->current_input_column - 1; + + std::ostringstream output_buf; + + if (reading_fcn_file || reading_script_file || reading_classdef_file) + output_buf << "parse error near line " << curr_lexer->input_line_number + << " of file " << curr_fcn_file_full_name; + else + output_buf << "parse error:"; + + if (s && strcmp (s, "parse error") != 0) + output_buf << "\n\n " << s; + + output_buf << "\n\n"; + + if (! current_input_line.empty ()) { - yyerror ("invalid classdef definition, the class name must match the file name"); - return retval; - } - - if (end_token_ok (end_tok, token::classdef_end)) - { - octave_comment_list *tc = octave_comment_buffer::get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - retval = new tree_classdef (a, id, sc, body, lc, tc, l, c); + size_t len = current_input_line.length (); + + if (current_input_line[len-1] == '\n') + current_input_line.resize (len-1); + + // Print the line, maybe with a pointer near the error token. + + output_buf << ">>> " << current_input_line << "\n"; + + if (err_col == 0) + err_col = len; + + for (int i = 0; i < err_col + 3; i++) + output_buf << " "; + + output_buf << "^"; } - return retval; -} - -static tree_classdef_properties_block * -make_classdef_properties_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_property_list *plist, - token *end_tok, octave_comment_list *lc) -{ - tree_classdef_properties_block *retval = 0; - - if (end_token_ok (end_tok, token::properties_end)) - { - octave_comment_list *tc = octave_comment_buffer::get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); - } - - return retval; -} - -static tree_classdef_methods_block * -make_classdef_methods_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_methods_list *mlist, - token *end_tok, octave_comment_list *lc) -{ - tree_classdef_methods_block *retval = 0; - - if (end_token_ok (end_tok, token::methods_end)) - { - octave_comment_list *tc = octave_comment_buffer::get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c); - } - - return retval; -} - -static tree_classdef_events_block * -make_classdef_events_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_events_list *elist, - token *end_tok, octave_comment_list *lc) -{ - tree_classdef_events_block *retval = 0; - - if (end_token_ok (end_tok, token::events_end)) - { - octave_comment_list *tc = octave_comment_buffer::get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - retval = new tree_classdef_events_block (a, elist, lc, tc, l, c); - } - - return retval; -} - -static tree_classdef_enum_block * -make_classdef_enum_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_enum_list *elist, - token *end_tok, octave_comment_list *lc) -{ - tree_classdef_enum_block *retval = 0; - - if (end_token_ok (end_tok, token::enumeration_end)) - { - octave_comment_list *tc = octave_comment_buffer::get_comment (); - - int l = tok_val->line (); - int c = tok_val->column (); - - retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c); - } - - return retval; + output_buf << "\n"; + + std::string msg = output_buf.str (); + + parse_error ("%s", msg.c_str ()); } static void @@ -3619,9 +3405,6 @@ } } - if (c == '\n') - input_line_number++; - return c; } @@ -3629,20 +3412,53 @@ stdio_stream_reader : public stream_reader { public: - stdio_stream_reader (FILE *f_arg) : stream_reader (), f (f_arg) { } - - int getc (void) { return ::text_getc (f); } + + stdio_stream_reader (FILE *f_arg, int& l, int& c) + : stream_reader (), f (f_arg), line_num (l), column_num (c) + { } + + int getc (void) + { + char c = ::text_getc (f); + + if (c == '\n') + { + line_num++; + column_num = 0; + } + else + { + // FIXME -- try to be smarter about tabs? + column_num++; + } + + return c; + } + int ungetc (int c) { if (c == '\n') - input_line_number--; + { + line_num--; + column_num = 0; + } + else + { + // FIXME -- try to be smarter about tabs? + column_num--; + } return ::ungetc (c, f); } private: + FILE *f; + int& line_num; + + int& column_num; + // No copying! stdio_stream_reader (const stdio_stream_reader&); @@ -3661,11 +3477,7 @@ { case ' ': case '\t': - current_input_column++; - break; - case '\n': - current_input_column = 1; break; default: @@ -3699,7 +3511,8 @@ } static std::string -gobble_leading_white_space (FILE *ffile, bool& eof) +gobble_leading_white_space (FILE *ffile, bool& eof, int& line_num, + int& column_num) { std::string help_txt; @@ -3710,7 +3523,7 @@ std::string txt; - stdio_stream_reader stdio_reader (ffile); + stdio_stream_reader stdio_reader (ffile, line_num, column_num); while (true) { @@ -3719,7 +3532,7 @@ if (eof) break; - txt = grab_comment_block (stdio_reader, true, eof); + txt = CURR_LEXER->grab_comment_block (stdio_reader, true, eof); if (txt.empty ()) break; @@ -3739,6 +3552,15 @@ return help_txt; } +static std::string +gobble_leading_white_space (FILE *ffile, bool& eof) +{ + int line_num = 1; + int column_num = 1; + + return gobble_leading_white_space (ffile, eof, line_num, column_num); +} + static bool looking_at_function_keyword (FILE *ffile) { @@ -3760,8 +3582,8 @@ static octave_function * parse_fcn_file (const std::string& ff, const std::string& dispatch_type, - bool force_script = false, bool require_file = true, - const std::string& warn_for = std::string ()) + bool require_file, bool force_script, bool autoload, + bool relative_lookup, const std::string& warn_for) { unwind_protect frame; @@ -3775,27 +3597,11 @@ frame.protect_var (ff_instream); - frame.protect_var (input_line_number); - frame.protect_var (current_input_column); frame.protect_var (reading_fcn_file); frame.protect_var (line_editing); - frame.protect_var (current_class_name); - frame.protect_var (current_function_depth); - frame.protect_var (function_scopes); - frame.protect_var (max_function_depth); - frame.protect_var (parsing_subfunctions); - frame.protect_var (endfunction_found); - - input_line_number = 1; - current_input_column = 1; + reading_fcn_file = true; line_editing = false; - current_class_name = dispatch_type; - current_function_depth = 0; - function_scopes.clear (); - max_function_depth = 0; - parsing_subfunctions = false; - endfunction_found = false; frame.add_fcn (command_history::ignore_entries, command_history::ignoring_entries ()); @@ -3810,7 +3616,21 @@ { bool eof; - std::string help_txt = gobble_leading_white_space (ffile, eof); + // octave_parser constructor sets this for us. + frame.protect_var (CURR_LEXER); + + octave_parser *curr_parser = new octave_parser (); + frame.add_fcn (octave_parser::cleanup, curr_parser); + + curr_parser->curr_class_name = dispatch_type; + curr_parser->autoloading = autoload; + curr_parser->fcn_file_from_relative_lookup = relative_lookup; + + std::string help_txt + = gobble_leading_white_space + (ffile, eof, + curr_parser->curr_lexer->input_line_number, + curr_parser->curr_lexer->current_input_column); if (! help_txt.empty ()) help_buf.push (help_txt); @@ -3820,15 +3640,12 @@ std::string file_type; frame.protect_var (get_input_from_eval_string); - frame.protect_var (parser_end_of_input); frame.protect_var (reading_fcn_file); frame.protect_var (reading_script_file); frame.protect_var (reading_classdef_file); frame.protect_var (Vecho_executing_commands); - get_input_from_eval_string = false; - parser_end_of_input = false; if (! force_script && looking_at_function_keyword (ffile)) { @@ -3861,22 +3678,6 @@ reading_script_file = true; } - YY_BUFFER_STATE old_buf = current_buffer (); - YY_BUFFER_STATE new_buf = create_buffer (ffile); - - frame.add_fcn (switch_to_buffer, old_buf); - frame.add_fcn (delete_buffer, new_buf); - - switch_to_buffer (new_buf); - - frame.protect_var (primary_fcn_ptr); - primary_fcn_ptr = 0; - - frame.protect_var (classdef_object); - classdef_object = 0; - - reset_parser (); - // Do this with an unwind-protect cleanup function so that // the forced variables will be unmarked in the event of an // interrupt. @@ -3887,19 +3688,19 @@ help_buf.push (help_txt); if (reading_script_file) - prep_lexer_for_script_file (); + curr_parser->curr_lexer->prep_for_script_file (); else if (reading_classdef_file) - prep_lexer_for_classdef_file (); + curr_parser->curr_lexer->prep_for_classdef_file (); else - prep_lexer_for_function_file (); - - lexer_flags.parsing_class_method = ! dispatch_type.empty (); + curr_parser->curr_lexer->prep_for_function_file (); + + curr_parser->curr_lexer->parsing_class_method = ! dispatch_type.empty (); frame.protect_var (global_command); global_command = 0; - int status = yyparse (); + int status = curr_parser->run (); // Use an unwind-protect cleanup function so that the // global_command list will be deleted in the event of an @@ -3907,11 +3708,11 @@ frame.add_fcn (cleanup_statement_list, &global_command); - fcn_ptr = primary_fcn_ptr; + fcn_ptr = curr_parser->primary_fcn_ptr; if (status == 0) { - if (reading_classdef_file && classdef_object) + if (reading_classdef_file && curr_parser->classdef_object) { // Convert parse tree for classdef object to // meta.class info (and stash it in the symbol @@ -3920,7 +3721,7 @@ if (fcn_ptr) panic_impossible (); - fcn_ptr = classdef_object->make_meta_class (); + fcn_ptr = curr_parser->classdef_object->make_meta_class (); } } else @@ -3931,12 +3732,15 @@ } else { + int l = curr_parser->curr_lexer->input_line_number; + int c = curr_parser->curr_lexer->current_input_column; + tree_statement *end_of_script - = make_end ("endscript", input_line_number, current_input_column); - - make_script (0, end_of_script); - - fcn_ptr = primary_fcn_ptr; + = curr_parser->make_end ("endscript", l, c); + + curr_parser->make_script (0, end_of_script); + + fcn_ptr = curr_parser->primary_fcn_ptr; } } else if (require_file) @@ -3971,7 +3775,9 @@ if (retval.empty ()) { - octave_function *fcn = parse_fcn_file (file, ""); + octave_function *fcn = parse_fcn_file (file, "", true, + false, false, + false, ""); if (fcn) { @@ -4049,9 +3855,7 @@ std::string file; - frame.protect_var (fcn_file_from_relative_lookup); - - fcn_file_from_relative_lookup = false; + bool relative_lookup = false; file = nm; @@ -4067,13 +3871,7 @@ nm = nm.substr (pos+1); } - if (autoload) - { - frame.protect_var (autoloading); - autoloading = true; - } - - fcn_file_from_relative_lookup = ! octave_env::absolute_pathname (file); + relative_lookup = ! octave_env::absolute_pathname (file); file = octave_env::make_absolute (file); @@ -4084,7 +3882,7 @@ if (autoload && ! fcn_name.empty ()) nm = fcn_name; - retval = octave_dynamic_loader::load_oct (nm, file, fcn_file_from_relative_lookup); + retval = octave_dynamic_loader::load_oct (nm, file, relative_lookup); } else if (len > 4 && file.substr (len-4, len-1) == ".mex") { @@ -4097,10 +3895,11 @@ curr_fcn_file_full_name = file.substr (0, len - 2); octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2), - dispatch_type, autoloading, - false); - - retval = octave_dynamic_loader::load_mex (nm, file, fcn_file_from_relative_lookup); + dispatch_type, false, + autoload, autoload, + relative_lookup, ""); + + retval = octave_dynamic_loader::load_mex (nm, file, relative_lookup); if (tmpfcn) retval->document (tmpfcn->doc_string ()); @@ -4116,7 +3915,8 @@ curr_fcn_file_name = nm; curr_fcn_file_full_name = file; - retval = parse_fcn_file (file, dispatch_type, autoloading); + retval = parse_fcn_file (file, dispatch_type, true, autoload, + autoload, relative_lookup, ""); } if (retval) @@ -4319,8 +4119,9 @@ if (! error_state) { - octave_function *fcn = parse_fcn_file (file_full_name, "", true, - require_file, warn_for); + octave_function *fcn = parse_fcn_file (file_full_name, "", + require_file, true, false, + false, warn_for); if (! error_state) { @@ -4631,50 +4432,30 @@ unwind_protect frame; - frame.protect_var (input_line_number); - frame.protect_var (current_input_column); + // octave_parser constructor sets this for us. + frame.protect_var (CURR_LEXER); + + octave_parser *curr_parser = new octave_parser (); + frame.add_fcn (octave_parser::cleanup, curr_parser); + frame.protect_var (get_input_from_eval_string); - frame.protect_var (input_from_eval_string_pending); - frame.protect_var (parser_end_of_input); frame.protect_var (line_editing); frame.protect_var (current_eval_string); - frame.protect_var (current_function_depth); - frame.protect_var (function_scopes); - frame.protect_var (max_function_depth); - frame.protect_var (parsing_subfunctions); - frame.protect_var (endfunction_found); frame.protect_var (reading_fcn_file); frame.protect_var (reading_script_file); frame.protect_var (reading_classdef_file); - input_line_number = 1; - current_input_column = 1; get_input_from_eval_string = true; - input_from_eval_string_pending = true; - parser_end_of_input = false; line_editing = false; - current_function_depth = 0; - function_scopes.clear (); - max_function_depth = 0; - parsing_subfunctions = false; - endfunction_found = false; reading_fcn_file = false; reading_script_file = false; reading_classdef_file = false; current_eval_string = s; - YY_BUFFER_STATE old_buf = current_buffer (); - YY_BUFFER_STATE new_buf = create_buffer (0); - - frame.add_fcn (switch_to_buffer, old_buf); - frame.add_fcn (delete_buffer, new_buf); - - switch_to_buffer (new_buf); - do { - reset_parser (); + curr_parser->reset (); frame.protect_var (global_command); @@ -4686,7 +4467,7 @@ symbol_table::scope_id scope = symbol_table::top_scope (); frame.add_fcn (symbol_table::unmark_forced_variables, scope); - parse_status = yyparse (); + parse_status = curr_parser->run (); tree_statement_list *command_list = global_command; @@ -4748,7 +4529,7 @@ || tree_continue_command::continuing) break; } - else if (parser_end_of_input) + else if (curr_parser->end_of_input) break; } }