Mercurial > hg > octave-nkf
changeset 16141:c6b2409672e9
Merge in Julien's changes
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Wed, 27 Feb 2013 14:51:21 -0500 |
parents | 797ac81586d1 (current diff) 2fd39ab12209 (diff) |
children | 26d65d677557 |
files | |
diffstat | 13 files changed, 1049 insertions(+), 931 deletions(-) [+] |
line wrap: on
line diff
--- a/build-aux/common.mk +++ b/build-aux/common.mk @@ -3,12 +3,15 @@ AWK = @AWK@ export AWK -SED = @SED@ -export SED +GREP = @GREP@ +export GREP FIND = @FIND@ export FIND +SED = @SED@ +export SED + PERL = @PERL@ export PERL @@ -278,9 +281,9 @@ ## Order matters, at least on some systems (Cygwin, for example). SPARSE_XLIBS = \ - $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \ - $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \ - $(CCOLAMD_LIBS) $(CXSPARSE_LIBS) + $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \ + $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \ + $(CCOLAMD_LIBS) $(CXSPARSE_LIBS) TERM_LIBS = @TERM_LIBS@ @@ -696,42 +699,13 @@ -e "s|%AWK%|${AWK}|g" \ -e "s|%FIND%|${FIND}|g" \ -e "s|%SED%|${SED}|g" \ - -e "s|%library_path_var%|${library_path_var}|g" \ - -e "s|%liboctinterp%|${SHLPRE}octinterp.${SHLEXT}|g" \ - -e "s|%liboctave%|${SHLPRE}octave.${SHLEXT}|g" \ - -e "s|%ldpreloadsep%|${ldpreloadsep}|g" \ - -e "s|%srcdir%|${srcdir}|" \ - -e "s|%top_srcdir%|${top_srcdir}|" \ -e "s|%abs_top_srcdir%|${abs_top_srcdir}|" \ -e "s|%builddir%|$(shell pwd)|" > $@-t $(simple_move_if_change_rule) endef -define do_script_install -$(top_srcdir)/build-aux/mkinstalldirs $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) -for f in $(FCN_FILES); do \ - fbase=`basename $$f`; \ - rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \ - $(INSTALL_DATA) $$f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \ -done -$(top_srcdir)/mkpkgadd $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) > $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t -if [ -n "`cat $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t`" ]; then \ - $(INSTALL_DATA) $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD ; \ -else \ - rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t ; \ -fi -endef - -define do_script_uninstall -for f in $(FCN_FILES_NO_DIR); \ - do rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$f; \ -done -rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD --rmdir $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) -endef - define test-file-commands -( echo "## DO NOT EDIT! Generated automatically from $(<F) by Make."; grep '^%!' $< ) > $@-t +( echo "## DO NOT EDIT! Generated automatically from $(<F) by Make."; $(GREP) '^%!' $< ) > $@-t mv $@-t $@ endef
--- a/build-aux/find-files-with-tests.sh +++ b/build-aux/find-files-with-tests.sh @@ -1,6 +1,7 @@ #! /bin/sh set -e +GREP=${GREP:-grep} SED=${SED:-sed} srcdir="$1" @@ -13,7 +14,7 @@ else file="$srcdir/$arg" fi - if [ "`grep -l '^%!' $file`" ]; then + if [ "`$GREP -l '^%!' $file`" ]; then echo "$file" | $SED "s,\\$srcdir/,,"; fi done
--- a/configure.ac +++ b/configure.ac @@ -97,6 +97,7 @@ ## Programs used in Makefiles. AC_PROG_AWK +AC_PROG_GREP OCTAVE_PROG_FIND OCTAVE_PROG_SED OCTAVE_PROG_PERL
--- a/doc/interpreter/octave.texi +++ b/doc/interpreter/octave.texi @@ -498,7 +498,7 @@ * Plot Annotations:: * Multiple Plots on One Page:: * Multiple Plot Windows:: -* Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions +* Use of axis@comma{} line@comma{} and patch Functions:: * Manipulation of Plot Windows:: * Use of the @code{interpreter} Property:: * Printing and Saving Plots::
--- a/doc/interpreter/plot.txi +++ b/doc/interpreter/plot.txi @@ -62,7 +62,7 @@ * Plot Annotations:: * Multiple Plots on One Page:: * Multiple Plot Windows:: -* Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions:: +* Use of axis@comma{} line@comma{} and patch Functions:: * Manipulation of Plot Windows:: * Use of the @code{interpreter} Property:: * Printing and Saving Plots:: @@ -521,8 +521,8 @@ @DOCSTRING(figure) -@node Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions -@subsection Use of @code{axis}@comma{} @code{line}@comma{} and @code{patch} Functions +@node Use of axis@comma{} line@comma{} and patch Functions +@subsection Use of axis@comma{} line@comma{} and patch Functions You can create axes, line, and patch objects directly using the @code{axes}, @code{line}, and @code{patch} functions. These objects
--- a/libinterp/interp-core/pt-jit.cc +++ b/libinterp/interp-core/pt-jit.cc @@ -36,12 +36,12 @@ #include "symtab.h" #include "variables.h" +#ifdef HAVE_LLVM + static bool Venable_jit_debugging = false; static bool Venable_jit_compiler = true; -#ifdef HAVE_LLVM - #include <llvm/Analysis/CallGraph.h> #include <llvm/Analysis/Passes.h> #include <llvm/Analysis/Verifier.h>
--- a/libinterp/interpfcn/input.cc +++ b/libinterp/interpfcn/input.cc @@ -680,24 +680,31 @@ frame.protect_var (curr_lexer); curr_lexer = new lexical_feedback (); + frame.add_fcn (lexical_feedback::cleanup, curr_lexer); + + frame.protect_var (curr_parser); + curr_parser = new octave_parser (); + frame.add_fcn (octave_parser::cleanup, curr_parser); while (Vdebugging) { + unwind_protect middle_frame; + reset_error_handler (); - reset_parser (); + curr_parser->reset (); // Save current value of global_command. - frame.protect_var (global_command); + middle_frame.protect_var (global_command); global_command = 0; // Do this with an unwind-protect cleanup function so that the // forced variables will be unmarked in the event of an interrupt. symbol_table::scope_id scope = symbol_table::top_scope (); - frame.add_fcn (symbol_table::unmark_forced_variables, scope); + middle_frame.add_fcn (symbol_table::unmark_forced_variables, scope); - int retval = octave_parse_input (); + int retval = curr_parser->run (); if (retval == 0 && global_command) { @@ -715,10 +722,6 @@ octave_completion_matches_called = false; } - // Unmark forced variables. - // Restore previous value of global_command. - frame.run (2); - octave_quit (); } }
--- a/libinterp/interpfcn/toplev.cc +++ b/libinterp/interpfcn/toplev.cc @@ -561,6 +561,11 @@ frame.protect_var (curr_lexer); curr_lexer = new lexical_feedback (); + frame.add_fcn (lexical_feedback::cleanup, curr_lexer); + + frame.protect_var (curr_parser); + curr_parser = new octave_parser (); + frame.add_fcn (octave_parser::cleanup, curr_parser); // The big loop. @@ -573,7 +578,7 @@ reset_error_handler (); - reset_parser (); + curr_parser->reset (); if (symbol_table::at_top_level ()) tree_evaluator::reset_debug_state (); @@ -588,7 +593,7 @@ global_command = 0; - retval = octave_parse_input (); + retval = curr_parser->run (); if (retval == 0) { @@ -636,7 +641,7 @@ command_editor::increment_current_command_number (); } } - else if (curr_lexer->parser_end_of_input) + else if (curr_parser->end_of_input) break; } }
--- a/libinterp/parse-tree/lex.h +++ b/libinterp/parse-tree/lex.h @@ -51,9 +51,6 @@ // Is the given string a keyword? extern bool is_keyword (const std::string& s); -extern void prep_lexer_for_script_file (void); -extern void prep_lexer_for_function_file (void); - class stream_reader { @@ -185,7 +182,7 @@ looking_for_object_index (false), looking_at_indirect_ref (false), parsing_class_method (false), maybe_classdef_get_set_method (false), parsing_classdef (false), - quote_is_transpose (false), parser_end_of_input (false), + quote_is_transpose (false), input_line_number (1), current_input_column (1), bracketflag (0), braceflag (0), looping (0), defining_func (0), looking_at_function_handle (0), @@ -205,12 +202,26 @@ looking_at_object_index.push_front (false); } + void reset (void); + + void prep_for_script_file (void); + + void prep_for_function_file (void); + + int octave_read (char *buf, unsigned int max_size); + + char *flex_yytext (void); + + int flex_yyleng (void); + void do_comma_insert_check (void); int text_yyinput (void); void xunput (char c, char *buf); + void xunput (char c); + void fixup_column_count (char *s); bool inside_any_object_index (void); @@ -276,6 +287,16 @@ void gripe_matlab_incompatible_operator (const std::string& op); + void push_token (token *); + + token *current_token (void); + + void display_token (int tok); + + void fatal_error (const char *msg); + + void lexer_debug (const char *pattern, const char *text); + // TRUE means that we should convert spaces to a comma inside a // matrix definition. bool convert_spaces_to_comma; @@ -329,9 +350,6 @@ // Return transpose or start a string? bool quote_is_transpose; - // TRUE means that we have encountered EOF on the input stream. - bool parser_end_of_input; - // The current input line number. int input_line_number; @@ -372,13 +390,16 @@ // a paren? bbp_nesting_level nesting_level; + // For unwind protect. + static void cleanup (lexical_feedback *lexer) { delete lexer; } + +private: + // Stack to hold tokens so that we can delete them when the parser is // reset and avoid growing forever just because we are stashing some // information. std::stack <token*> token_stack; -private: - // No copying! lexical_feedback (const lexical_feedback&);
--- a/libinterp/parse-tree/lex.ll +++ b/libinterp/parse-tree/lex.ll @@ -103,7 +103,7 @@ #undef YY_INPUT #endif #define YY_INPUT(buf, result, max_size) \ - result = octave_read (buf, max_size) + result = curr_lexer->octave_read (buf, max_size) // Try to avoid crashing out completely on fatal scanner errors. // The call to yy_fatal_error should never happen, but it avoids a @@ -113,24 +113,18 @@ #undef YY_FATAL_ERROR #endif #define YY_FATAL_ERROR(msg) \ - do \ - { \ - error (msg); \ - OCTAVE_QUIT; \ - yy_fatal_error (msg); \ - } \ - while (0) + curr_lexer->fatal_error (msg) #define DISPLAY_TOK_AND_RETURN(tok) \ do \ { \ int tok_val = tok; \ if (Vdisplay_tokens) \ - display_token (tok_val); \ + curr_lexer->display_token (tok_val); \ if (lexer_debug_flag) \ { \ std::cerr << "R: "; \ - display_token (tok_val); \ + curr_lexer->display_token (tok_val); \ std::cerr << std::endl; \ } \ return tok_val; \ @@ -158,9 +152,9 @@ #define TOK_PUSH_AND_RETURN(name, tok) \ do \ { \ - yylval.tok_val = new token (name, curr_lexer->input_line_number, \ - curr_lexer->current_input_column); \ - curr_lexer->token_stack.push (yylval.tok_val); \ + curr_lexer->push_token \ + (new token (name, curr_lexer->input_line_number, \ + curr_lexer->current_input_column)); \ TOK_RETURN (tok); \ } \ while (0) @@ -168,9 +162,9 @@ #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \ do \ { \ - yylval.tok_val = new token (curr_lexer->input_line_number, \ - curr_lexer->current_input_column); \ - curr_lexer->token_stack.push (yylval.tok_val); \ + curr_lexer->push_token \ + (new token (curr_lexer->input_line_number, \ + curr_lexer->current_input_column)); \ curr_lexer->current_input_column += yyleng; \ curr_lexer->quote_is_transpose = qit; \ curr_lexer->convert_spaces_to_comma = convert; \ @@ -207,7 +201,7 @@ do \ { \ if (lexer_debug_flag) \ - lexer_debug (pattern, yytext); \ + curr_lexer->lexer_debug (pattern, yytext); \ } \ while (0) @@ -225,9 +219,6 @@ // file that are needed inside the lexer actions. static std::string strip_trailing_whitespace (char *s); -static int octave_read (char *buf, unsigned int max_size); -static void display_token (int tok); -static void lexer_debug (const char *pattern, const char *text); %} @@ -259,7 +250,7 @@ LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>."); BEGIN (INITIAL); - curr_lexer->xunput (yytext[0], yytext); + curr_lexer->xunput (yytext[0]); COUNT_TOK_AND_RETURN (SCRIPT_FILE); } @@ -267,7 +258,7 @@ LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>."); BEGIN (INITIAL); - curr_lexer->xunput (yytext[0], yytext); + curr_lexer->xunput (yytext[0]); COUNT_TOK_AND_RETURN (FUNCTION_FILE); } @@ -357,7 +348,7 @@ int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']'); if (spc_gobbled) - curr_lexer->xunput (' ', yytext); + curr_lexer->xunput (' '); COUNT_TOK_AND_RETURN (tok_to_return); } @@ -383,7 +374,7 @@ int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}'); if (spc_gobbled) - curr_lexer->xunput (' ', yytext); + curr_lexer->xunput (' '); COUNT_TOK_AND_RETURN (tok_to_return); } @@ -412,7 +403,7 @@ { curr_lexer->maybe_warn_separator_insert (';'); - curr_lexer->xunput (';', yytext); + curr_lexer->xunput (';'); } } @@ -449,7 +440,7 @@ { curr_lexer->maybe_warn_separator_insert (';'); - curr_lexer->xunput (';', yytext); + curr_lexer->xunput (';'); } curr_lexer->quote_is_transpose = false; @@ -769,7 +760,7 @@ curr_lexer->looking_for_object_index = false; - curr_lexer->xunput (yytext[0], yytext); + curr_lexer->xunput (yytext[0]); bool eof = false; int tok = curr_lexer->process_comment (false, eof); @@ -959,7 +950,7 @@ . { LEXER_DEBUG ("."); - curr_lexer->xunput (yytext[0], yytext); + curr_lexer->xunput (yytext[0]); int c = curr_lexer->text_yyinput (); @@ -979,38 +970,6 @@ %% -// Fix things up for errors or interrupts. The parser is never called -// recursively, so it is always safe to reinitialize its state before -// doing any parsing. - -void -reset_parser (void) -{ - // Start off on the right foot. - BEGIN (INITIAL); - - parser_symtab_context.clear (); - - // We do want a prompt by default. - promptflag = 1; - - // Only ask for input from stdin if we are expecting interactive - // input. - - if (! quitting_gracefully - && (interactive || forced_interactive) - && ! (reading_fcn_file - || reading_classdef_file - || reading_script_file - || get_input_from_eval_string - || input_from_startup_file)) - yyrestart (stdin); - - // Clear the buffer for help text. - while (! help_buf.empty ()) - help_buf.pop (); -} - static void display_character (char c) { @@ -1212,8 +1171,6 @@ void cleanup_parser (void) { - reset_parser (); - clear_all_buffers (); } @@ -1233,26 +1190,6 @@ delete_buffer (static_cast<YY_BUFFER_STATE> (buf)); } -class -flex_stream_reader : public stream_reader -{ -public: - flex_stream_reader (char *buf_arg) : stream_reader (), buf (buf_arg) { } - - int getc (void) { return curr_lexer->text_yyinput (); } - int ungetc (int c) { curr_lexer->xunput (c, buf); return 0; } - -private: - - // No copying! - - flex_stream_reader (const flex_stream_reader&); - - flex_stream_reader& operator = (const flex_stream_reader&); - - char *buf; -}; - // Return 1 if the given character matches any character in the given // string. @@ -1354,18 +1291,6 @@ */ -void -prep_lexer_for_script_file (void) -{ - BEGIN (SCRIPT_FILE_BEGIN); -} - -void -prep_lexer_for_function_file (void) -{ - BEGIN (FUNCTION_FILE_BEGIN); -} - // Used to delete trailing white space from tokens. static std::string @@ -1381,8 +1306,117 @@ return retval; } -static int -octave_read (char *buf, unsigned max_size) +DEFUN (__display_tokens__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __display_tokens__ ()\n\ +Query or set the internal variable that determines whether Octave's\n\ +lexer displays tokens as they are read.\n\ +@end deftypefn") +{ + return SET_INTERNAL_VARIABLE (display_tokens); +} + +DEFUN (__token_count__, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __token_count__ ()\n\ +Number of language tokens processed since Octave startup.\n\ +@end deftypefn") +{ + return octave_value (Vtoken_count); +} + +DEFUN (__lexer_debug_flag__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval; + + retval = set_internal_variable (lexer_debug_flag, args, nargout, + "__lexer_debug_flag__"); + + return retval; +} + +class +flex_stream_reader : public stream_reader +{ +public: + flex_stream_reader (lexical_feedback *l, char *buf_arg) + : stream_reader (), lexer (l), buf (buf_arg) + { } + + int getc (void) { return lexer->text_yyinput (); } + int ungetc (int c) { lexer->xunput (c, buf); return 0; } + +private: + + // No copying! + + flex_stream_reader (const flex_stream_reader&); + + flex_stream_reader& operator = (const flex_stream_reader&); + + lexical_feedback *lexer; + + char *buf; +}; + +lexical_feedback::~lexical_feedback (void) +{ + // Clear out the stack of token info used to track line and + // column numbers. + + while (! token_stack.empty ()) + { + delete token_stack.top (); + token_stack.pop (); + } +} + +void +lexical_feedback::reset (void) +{ + // Start off on the right foot. + BEGIN (INITIAL); + + parser_symtab_context.clear (); + + // We do want a prompt by default. + promptflag = 1; + + // Only ask for input from stdin if we are expecting interactive + // input. + + if (! quitting_gracefully + && (interactive || forced_interactive) + && ! (reading_fcn_file + || reading_classdef_file + || reading_script_file + || get_input_from_eval_string + || input_from_startup_file)) + yyrestart (stdin); + + // Clear the buffer for help text. + while (! help_buf.empty ()) + help_buf.pop (); +} + +void +lexical_feedback::prep_for_script_file (void) +{ + BEGIN (SCRIPT_FILE_BEGIN); +} + +void +lexical_feedback::prep_for_function_file (void) +{ + BEGIN (FUNCTION_FILE_BEGIN); +} + +int +lexical_feedback::octave_read (char *buf, unsigned max_size) { static const char * const eol = "\n"; static std::string input_buf; @@ -1445,219 +1479,16 @@ return status; } -static void -display_token (int tok) +char * +lexical_feedback::flex_yytext (void) { - switch (tok) - { - case '=': std::cerr << "'='\n"; break; - case ':': std::cerr << "':'\n"; break; - case '-': std::cerr << "'-'\n"; break; - case '+': std::cerr << "'+'\n"; break; - case '*': std::cerr << "'*'\n"; break; - case '/': std::cerr << "'/'\n"; break; - case ADD_EQ: std::cerr << "ADD_EQ\n"; break; - case SUB_EQ: std::cerr << "SUB_EQ\n"; break; - case MUL_EQ: std::cerr << "MUL_EQ\n"; break; - case DIV_EQ: std::cerr << "DIV_EQ\n"; break; - case LEFTDIV_EQ: std::cerr << "LEFTDIV_EQ\n"; break; - case POW_EQ: std::cerr << "POW_EQ\n"; break; - case EMUL_EQ: std::cerr << "EMUL_EQ\n"; break; - case EDIV_EQ: std::cerr << "EDIV_EQ\n"; break; - case ELEFTDIV_EQ: std::cerr << "ELEFTDIV_EQ\n"; break; - case EPOW_EQ: std::cerr << "EPOW_EQ\n"; break; - case AND_EQ: std::cerr << "AND_EQ\n"; break; - case OR_EQ: std::cerr << "OR_EQ\n"; break; - case LSHIFT_EQ: std::cerr << "LSHIFT_EQ\n"; break; - case RSHIFT_EQ: std::cerr << "RSHIFT_EQ\n"; break; - case LSHIFT: std::cerr << "LSHIFT\n"; break; - case RSHIFT: std::cerr << "RSHIFT\n"; break; - case EXPR_AND_AND: std::cerr << "EXPR_AND_AND\n"; break; - case EXPR_OR_OR: std::cerr << "EXPR_OR_OR\n"; break; - case EXPR_AND: std::cerr << "EXPR_AND\n"; break; - case EXPR_OR: std::cerr << "EXPR_OR\n"; break; - case EXPR_NOT: std::cerr << "EXPR_NOT\n"; break; - case EXPR_LT: std::cerr << "EXPR_LT\n"; break; - case EXPR_LE: std::cerr << "EXPR_LE\n"; break; - case EXPR_EQ: std::cerr << "EXPR_EQ\n"; break; - case EXPR_NE: std::cerr << "EXPR_NE\n"; break; - case EXPR_GE: std::cerr << "EXPR_GE\n"; break; - case EXPR_GT: std::cerr << "EXPR_GT\n"; break; - case LEFTDIV: std::cerr << "LEFTDIV\n"; break; - case EMUL: std::cerr << "EMUL\n"; break; - case EDIV: std::cerr << "EDIV\n"; break; - case ELEFTDIV: std::cerr << "ELEFTDIV\n"; break; - case EPLUS: std::cerr << "EPLUS\n"; break; - case EMINUS: std::cerr << "EMINUS\n"; break; - case QUOTE: std::cerr << "QUOTE\n"; break; - case TRANSPOSE: std::cerr << "TRANSPOSE\n"; break; - case PLUS_PLUS: std::cerr << "PLUS_PLUS\n"; break; - case MINUS_MINUS: std::cerr << "MINUS_MINUS\n"; break; - case POW: std::cerr << "POW\n"; break; - case EPOW: std::cerr << "EPOW\n"; break; - - case NUM: - case IMAG_NUM: - std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM") - << " [" << yylval.tok_val->number () << "]\n"; - break; - - case STRUCT_ELT: - std::cerr << "STRUCT_ELT [" << yylval.tok_val->text () << "]\n"; break; - - case NAME: - { - symbol_table::symbol_record *sr = yylval.tok_val->sym_rec (); - std::cerr << "NAME"; - if (sr) - std::cerr << " [" << sr->name () << "]"; - std::cerr << "\n"; - } - break; - - case END: std::cerr << "END\n"; break; - - case DQ_STRING: - case SQ_STRING: - std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING") - << " [" << yylval.tok_val->text () << "]\n"; - break; - - case FOR: std::cerr << "FOR\n"; break; - case WHILE: std::cerr << "WHILE\n"; break; - case DO: std::cerr << "DO\n"; break; - case UNTIL: std::cerr << "UNTIL\n"; break; - case IF: std::cerr << "IF\n"; break; - case ELSEIF: std::cerr << "ELSEIF\n"; break; - case ELSE: std::cerr << "ELSE\n"; break; - case SWITCH: std::cerr << "SWITCH\n"; break; - case CASE: std::cerr << "CASE\n"; break; - case OTHERWISE: std::cerr << "OTHERWISE\n"; break; - case BREAK: std::cerr << "BREAK\n"; break; - case CONTINUE: std::cerr << "CONTINUE\n"; break; - case FUNC_RET: std::cerr << "FUNC_RET\n"; break; - case UNWIND: std::cerr << "UNWIND\n"; break; - case CLEANUP: std::cerr << "CLEANUP\n"; break; - case TRY: std::cerr << "TRY\n"; break; - case CATCH: std::cerr << "CATCH\n"; break; - case GLOBAL: std::cerr << "GLOBAL\n"; break; - case PERSISTENT: std::cerr << "PERSISTENT\n"; break; - case FCN_HANDLE: std::cerr << "FCN_HANDLE\n"; break; - case END_OF_INPUT: std::cerr << "END_OF_INPUT\n\n"; break; - case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break; - case FCN: std::cerr << "FCN\n"; break; - case CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break; - case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break; - case FUNCTION_FILE: std::cerr << "FUNCTION_FILE\n"; break; - case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break; - case METAQUERY: std::cerr << "METAQUERY\n"; break; - case GET: std::cerr << "GET\n"; break; - case SET: std::cerr << "SET\n"; break; - case PROPERTIES: std::cerr << "PROPERTIES\n"; break; - case METHODS: std::cerr << "METHODS\n"; break; - case EVENTS: std::cerr << "EVENTS\n"; break; - case CLASSDEF: std::cerr << "CLASSDEF\n"; break; - case '\n': std::cerr << "\\n\n"; break; - case '\r': std::cerr << "\\r\n"; break; - case '\t': std::cerr << "TAB\n"; break; - default: - { - if (tok < 256) - std::cerr << static_cast<char> (tok) << "\n"; - else - std::cerr << "UNKNOWN(" << tok << ")\n"; - } - break; - } + return yytext; } -static void -display_state (void) -{ - std::cerr << "S: "; - - switch (YY_START) - { - case INITIAL: - std::cerr << "INITIAL" << std::endl; - break; - - case COMMAND_START: - std::cerr << "COMMAND_START" << std::endl; - break; - - case MATRIX_START: - std::cerr << "MATRIX_START" << std::endl; - break; - - case SCRIPT_FILE_BEGIN: - std::cerr << "SCRIPT_FILE_BEGIN" << std::endl; - break; - - case FUNCTION_FILE_BEGIN: - std::cerr << "FUNCTION_FILE_BEGIN" << std::endl; - break; - - default: - std::cerr << "UNKNOWN START STATE!" << std::endl; - break; - } -} - -static void -lexer_debug (const char *pattern, const char *text) +int +lexical_feedback::flex_yyleng (void) { - std::cerr << std::endl; - - display_state (); - - std::cerr << "P: " << pattern << std::endl; - std::cerr << "T: " << text << std::endl; -} - -DEFUN (__display_tokens__, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __display_tokens__ ()\n\ -Query or set the internal variable that determines whether Octave's\n\ -lexer displays tokens as they are read.\n\ -@end deftypefn") -{ - return SET_INTERNAL_VARIABLE (display_tokens); -} - -DEFUN (__token_count__, , , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __token_count__ ()\n\ -Number of language tokens processed since Octave startup.\n\ -@end deftypefn") -{ - return octave_value (Vtoken_count); -} - -DEFUN (__lexer_debug_flag__, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\ -Undocumented internal function.\n\ -@end deftypefn") -{ - octave_value retval; - - retval = set_internal_variable (lexer_debug_flag, args, nargout, - "__lexer_debug_flag__"); - - return retval; -} - -lexical_feedback::~lexical_feedback (void) -{ - // Clear out the stack of token info used to track line and - // column numbers. - - while (! token_stack.empty ()) - { - delete token_stack.top (); - token_stack.pop (); - } + return yyleng; } // GAG. @@ -1672,10 +1503,10 @@ int c = text_yyinput (); - xunput (c, yytext); + xunput (c); if (spc_gobbled) - xunput (' ', yytext); + xunput (' '); do_comma_insert = (! looking_at_object_index.front () && bracketflag && c == '['); @@ -1708,7 +1539,7 @@ if (c != '\n') { - xunput (c, yytext); + xunput (c); c = '\n'; } } @@ -1735,6 +1566,13 @@ yyunput (c, buf); } +void +lexical_feedback::xunput (char c) +{ + char *yytxt = flex_yytext (); + xunput (c, yytxt); +} + // If we read some newlines, we need figure out what column we're // really looking at. @@ -1786,7 +1624,7 @@ if (kw) { - yylval.tok_val = 0; + token *tok_val = 0; switch (kw->kw_id) { @@ -1831,72 +1669,72 @@ || parsed_function_name.top ())))) return 0; - yylval.tok_val = new token (token::simple_end, l, c); + tok_val = new token (token::simple_end, l, c); at_beginning_of_statement = true; break; case end_try_catch_kw: - yylval.tok_val = new token (token::try_catch_end, l, c); + tok_val = new token (token::try_catch_end, l, c); at_beginning_of_statement = true; break; case end_unwind_protect_kw: - yylval.tok_val = new token (token::unwind_protect_end, l, c); + tok_val = new token (token::unwind_protect_end, l, c); at_beginning_of_statement = true; break; case endfor_kw: - yylval.tok_val = new token (token::for_end, l, c); + tok_val = new token (token::for_end, l, c); at_beginning_of_statement = true; break; case endfunction_kw: - yylval.tok_val = new token (token::function_end, l, c); + tok_val = new token (token::function_end, l, c); at_beginning_of_statement = true; break; case endif_kw: - yylval.tok_val = new token (token::if_end, l, c); + tok_val = new token (token::if_end, l, c); at_beginning_of_statement = true; break; case endparfor_kw: - yylval.tok_val = new token (token::parfor_end, l, c); + tok_val = new token (token::parfor_end, l, c); at_beginning_of_statement = true; break; case endswitch_kw: - yylval.tok_val = new token (token::switch_end, l, c); + tok_val = new token (token::switch_end, l, c); at_beginning_of_statement = true; break; case endwhile_kw: - yylval.tok_val = new token (token::while_end, l, c); + tok_val = new token (token::while_end, l, c); at_beginning_of_statement = true; break; case endclassdef_kw: - yylval.tok_val = new token (token::classdef_end, l, c); + tok_val = new token (token::classdef_end, l, c); at_beginning_of_statement = true; break; case endenumeration_kw: - yylval.tok_val = new token (token::enumeration_end, l, c); + tok_val = new token (token::enumeration_end, l, c); at_beginning_of_statement = true; break; case endevents_kw: - yylval.tok_val = new token (token::events_end, l, c); + tok_val = new token (token::events_end, l, c); at_beginning_of_statement = true; break; case endmethods_kw: - yylval.tok_val = new token (token::methods_end, l, c); + tok_val = new token (token::methods_end, l, c); at_beginning_of_statement = true; break; case endproperties_kw: - yylval.tok_val = new token (token::properties_end, l, c); + tok_val = new token (token::properties_end, l, c); at_beginning_of_statement = true; break; @@ -1964,24 +1802,24 @@ if ((reading_fcn_file || reading_script_file || reading_classdef_file) && ! curr_fcn_file_full_name.empty ()) - yylval.tok_val = new token (curr_fcn_file_full_name, l, c); + tok_val = new token (curr_fcn_file_full_name, l, c); else - yylval.tok_val = new token ("stdin", l, c); + tok_val = new token ("stdin", l, c); } break; case magic_line_kw: - yylval.tok_val = new token (static_cast<double> (l), "", l, c); + tok_val = new token (static_cast<double> (l), "", l, c); break; default: panic_impossible (); } - if (! yylval.tok_val) - yylval.tok_val = new token (l, c); - - token_stack.push (yylval.tok_val); + if (! tok_val) + tok_val = new token (l, c); + + curr_lexer->push_token (tok_val); return kw->tok; } @@ -2253,7 +2091,8 @@ if (! help_buf.empty ()) help_txt = help_buf.top (); - flex_stream_reader flex_reader (yytext); + char *yytxt = flex_yytext (); + flex_stream_reader flex_reader (this, yytxt); // process_comment is only supposed to be called when we are not // initially looking at a block comment. @@ -2303,7 +2142,7 @@ retval = match_any (c, ",;\n]"); - xunput (c, yytext); + xunput (c); return retval; } @@ -2326,22 +2165,22 @@ { int c1 = text_yyinput (); un_op = (c1 == '\''); - xunput (c1, yytext); + xunput (c1); } else if (c0 == '+') { int c1 = text_yyinput (); un_op = (c1 == '+'); - xunput (c1, yytext); + xunput (c1); } else if (c0 == '-') { int c1 = text_yyinput (); un_op = (c1 == '-'); - xunput (c1, yytext); + xunput (c1); } - xunput (c0, yytext); + xunput (c0); return un_op; } @@ -2390,7 +2229,7 @@ break; } - xunput (c1, yytext); + xunput (c1); } break; @@ -2414,7 +2253,7 @@ // A structure element reference is a binary op. bin_op = true; - xunput (c1, yytext); + xunput (c1); } break; @@ -2444,7 +2283,7 @@ if (c1 == '=') bin_op = true; - xunput (c1, yytext); + xunput (c1); } break; @@ -2452,7 +2291,7 @@ break; } - xunput (c0, yytext); + xunput (c0); return bin_op; } @@ -2622,7 +2461,7 @@ octave_comment_buffer::append (comment_buf); done: - xunput (c, yytext); + xunput (c); current_input_column--; return retval; } @@ -2639,17 +2478,19 @@ double value = 0.0; int nread = 0; - if (looks_like_hex (yytext, strlen (yytext))) + char *yytxt = flex_yytext (); + + if (looks_like_hex (yytxt, strlen (yytxt))) { unsigned long ival; - nread = sscanf (yytext, "%lx", &ival); + nread = sscanf (yytxt, "%lx", &ival); value = static_cast<double> (ival); } else { - char *tmp = strsave (yytext); + char *tmp = strsave (yytxt); char *idx = strpbrk (tmp, "Dd"); @@ -2670,12 +2511,10 @@ looking_for_object_index = false; at_beginning_of_statement = false; - yylval.tok_val = new token (value, yytext, input_line_number, - current_input_column); - - token_stack.push (yylval.tok_val); - - current_input_column += yyleng; + curr_lexer->push_token (new token (value, yytxt, input_line_number, + current_input_column)); + + current_input_column += flex_yyleng (); do_comma_insert_check (); } @@ -2761,7 +2600,7 @@ } } - xunput (c, yytext); + xunput (c); return false; cleanup: @@ -2770,7 +2609,7 @@ int len = s.length (); while (len--) - xunput (s[len], yytext); + xunput (s[len]); return false; } @@ -2790,12 +2629,12 @@ return true; else { - xunput (c2, yytext); - xunput (c1, yytext); + xunput (c2); + xunput (c1); } } else - xunput (c1, yytext); + xunput (c1); return false; } @@ -2814,7 +2653,7 @@ || (c == '\\' && have_continuation ())) retval = eat_whitespace (); else - xunput (c, yytext); + xunput (c); return retval; } @@ -2877,7 +2716,7 @@ else { std::string s; - xunput (c, yytext); + xunput (c); if (delim == '\'') s = buf.str (); @@ -2887,8 +2726,7 @@ quote_is_transpose = true; convert_spaces_to_comma = true; - yylval.tok_val = new token (s, bos_line, bos_col); - token_stack.push (yylval.tok_val); + curr_lexer->push_token (new token (s, bos_line, bos_col)); if (delim == '"') gripe_matlab_incompatible ("\" used as string delimiter"); @@ -2925,7 +2763,7 @@ case '=': { int c1 = text_yyinput (); - xunput (c1, yytext); + xunput (c1); if (c1 != '=') retval = true; } @@ -2940,7 +2778,7 @@ case '|': { int c1 = text_yyinput (); - xunput (c1, yytext); + xunput (c1); if (c1 == '=') retval = true; } @@ -2952,11 +2790,11 @@ if (match_any (c1, "+-*/\\")) { int c2 = text_yyinput (); - xunput (c2, yytext); + xunput (c2); if (c2 == '=') retval = true; } - xunput (c1, yytext); + xunput (c1); } break; @@ -2966,11 +2804,11 @@ if (c1 == '>') { int c2 = text_yyinput (); - xunput (c2, yytext); + xunput (c2); if (c2 == '=') retval = true; } - xunput (c1, yytext); + xunput (c1); } break; @@ -2980,11 +2818,11 @@ if (c1 == '<') { int c2 = text_yyinput (); - xunput (c2, yytext); + xunput (c2); if (c2 == '=') retval = true; } - xunput (c1, yytext); + xunput (c1); } break; @@ -2992,7 +2830,7 @@ break; } - xunput (c0, yytext); + xunput (c0); return retval; } @@ -3001,7 +2839,7 @@ lexical_feedback::next_token_is_index_op (void) { int c = text_yyinput (); - xunput (c, yytext); + xunput (c); return c == '(' || c == '{'; } @@ -3059,7 +2897,7 @@ { maybe_warn_separator_insert (','); - xunput (',', yytext); + xunput (','); return retval; } } @@ -3085,8 +2923,8 @@ int c1 = text_yyinput (); int c2 = text_yyinput (); - xunput (c2, yytext); - xunput (c1, yytext); + xunput (c2); + xunput (c1); int sep_op = next_token_is_sep_op (); @@ -3106,7 +2944,7 @@ maybe_warn_separator_insert (','); - xunput (',', yytext); + xunput (','); } } @@ -3131,7 +2969,7 @@ // Restore input. while (! buf.empty ()) { - xunput (buf.top (), yytext); + xunput (buf.top ()); buf.pop (); } @@ -3174,12 +3012,12 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } else retval = false; - xunput (c1, yytext); + xunput (c1); } break; @@ -3229,12 +3067,12 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } break; } - xunput (c1, yytext); + xunput (c1); } break; @@ -3249,7 +3087,7 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c1, yytext); + xunput (c1); } break; @@ -3270,13 +3108,13 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c3, yytext); + xunput (c3); } else if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t') && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } else if (! match_any (c1, ",;\n") && (! isdigit (c1) && c1 != ' ' && c1 != '\t' @@ -3287,7 +3125,7 @@ retval = false; } - xunput (c1, yytext); + xunput (c1); } break; @@ -3306,13 +3144,13 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') && next_token_can_follow_bin_op ()) retval = false; - xunput (c1, yytext); + xunput (c1); } break; @@ -3330,13 +3168,13 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') && next_token_can_follow_bin_op ()) retval = false; - xunput (c1, yytext); + xunput (c1); } break; @@ -3355,13 +3193,13 @@ && next_token_can_follow_bin_op ()) retval = false; - xunput (c2, yytext); + xunput (c2); } else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t') && next_token_can_follow_bin_op ()) retval = false; - xunput (c1, yytext); + xunput (c1); } break; @@ -3369,7 +3207,7 @@ break; } - xunput (c0, yytext); + xunput (c0); return retval; } @@ -3380,7 +3218,8 @@ eat_continuation (); std::string pkg; - std::string meth = strip_trailing_whitespace (yytext); + char *yytxt = flex_yytext (); + std::string meth = strip_trailing_whitespace (yytxt); size_t pos = meth.find ("@"); std::string cls = meth.substr (pos).substr (1); meth = meth.substr (0, pos - 1); @@ -3400,16 +3239,14 @@ return LEXICAL_ERROR; } - yylval.tok_val - = new token (meth.empty () ? 0 : &(symbol_table::insert (meth)), - cls.empty () ? 0 : &(symbol_table::insert (cls)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg)), - input_line_number, - current_input_column); - token_stack.push (yylval.tok_val); + curr_lexer->push_token + (new token (meth.empty () ? 0 : &(symbol_table::insert (meth)), + cls.empty () ? 0 : &(symbol_table::insert (cls)), + pkg.empty () ? 0 : &(symbol_table::insert (pkg)), + input_line_number, current_input_column)); convert_spaces_to_comma = true; - current_input_column += yyleng; + current_input_column += flex_yyleng (); return SUPERCLASSREF; } @@ -3420,7 +3257,8 @@ eat_continuation (); std::string pkg; - std::string cls = strip_trailing_whitespace (yytext).substr (1); + char *yytxt = flex_yytext (); + std::string cls = strip_trailing_whitespace (yytxt).substr (1); size_t pos = cls.find ("."); if (pos != std::string::npos) @@ -3436,16 +3274,13 @@ return LEXICAL_ERROR; } - yylval.tok_val - = new token (cls.empty () ? 0 : &(symbol_table::insert (cls)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg)), - input_line_number, - current_input_column); - - token_stack.push (yylval.tok_val); + curr_lexer->push_token + (new token (cls.empty () ? 0 : &(symbol_table::insert (cls)), + pkg.empty () ? 0 : &(symbol_table::insert (pkg)), + input_line_number, current_input_column)); convert_spaces_to_comma = true; - current_input_column += yyleng; + current_input_column += flex_yyleng (); return METAQUERY; } @@ -3459,9 +3294,11 @@ { bool at_bos = at_beginning_of_statement; - std::string tok = strip_trailing_whitespace (yytext); - - int c = yytext[yyleng-1]; + char *yytxt = flex_yytext (); + + std::string tok = strip_trailing_whitespace (yytxt); + + int c = yytxt[flex_yyleng()-1]; bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE); @@ -3478,16 +3315,14 @@ maybe_unput_comma (spc_gobbled); - yylval.tok_val = new token (tok, input_line_number, - current_input_column); - - token_stack.push (yylval.tok_val); + curr_lexer->push_token (new token (tok, input_line_number, + current_input_column)); quote_is_transpose = true; convert_spaces_to_comma = true; looking_for_object_index = true; - current_input_column += yyleng; + current_input_column += flex_yyleng (); return STRUCT_ELT; } @@ -3515,12 +3350,10 @@ } else { - yylval.tok_val = new token (tok, input_line_number, - current_input_column); - - token_stack.push (yylval.tok_val); - - current_input_column += yyleng; + curr_lexer->push_token (new token (tok, input_line_number, + current_input_column)); + + current_input_column += flex_yyleng (); quote_is_transpose = false; convert_spaces_to_comma = true; looking_for_object_index = true; @@ -3536,7 +3369,7 @@ { if (kw_token >= 0) { - current_input_column += yyleng; + current_input_column += flex_yyleng (); quote_is_transpose = false; convert_spaces_to_comma = true; looking_for_object_index = false; @@ -3553,13 +3386,13 @@ if (c1 == '=') { int c2 = text_yyinput (); - xunput (c2, yytext); + xunput (c2); if (c2 != '=') next_tok_is_eq = true; } - xunput (c1, yytext); + xunput (c1); // Kluge alert. // @@ -3598,11 +3431,8 @@ if (tok == "end") tok = "__end__"; - yylval.tok_val = new token (&(symbol_table::insert (tok)), - input_line_number, - current_input_column); - - token_stack.push (yylval.tok_val); + curr_lexer->push_token (new token (&(symbol_table::insert (tok)), + input_line_number, current_input_column)); // After seeing an identifer, it is ok to convert spaces to a comma // (if needed). @@ -3618,7 +3448,7 @@ maybe_unput_comma (spc_gobbled); } - current_input_column += yyleng; + current_input_column += flex_yyleng (); if (tok != "__end__") looking_for_object_index = true; @@ -3693,3 +3523,208 @@ t.resize (n-1); gripe_matlab_incompatible (t + " used as operator"); } + +void +lexical_feedback::push_token (token *tok) +{ + yylval.tok_val = tok; + token_stack.push (tok); +} + +token * +lexical_feedback::current_token (void) +{ + return yylval.tok_val; +} + +void +lexical_feedback::display_token (int tok) +{ + switch (tok) + { + case '=': std::cerr << "'='\n"; break; + case ':': std::cerr << "':'\n"; break; + case '-': std::cerr << "'-'\n"; break; + case '+': std::cerr << "'+'\n"; break; + case '*': std::cerr << "'*'\n"; break; + case '/': std::cerr << "'/'\n"; break; + case ADD_EQ: std::cerr << "ADD_EQ\n"; break; + case SUB_EQ: std::cerr << "SUB_EQ\n"; break; + case MUL_EQ: std::cerr << "MUL_EQ\n"; break; + case DIV_EQ: std::cerr << "DIV_EQ\n"; break; + case LEFTDIV_EQ: std::cerr << "LEFTDIV_EQ\n"; break; + case POW_EQ: std::cerr << "POW_EQ\n"; break; + case EMUL_EQ: std::cerr << "EMUL_EQ\n"; break; + case EDIV_EQ: std::cerr << "EDIV_EQ\n"; break; + case ELEFTDIV_EQ: std::cerr << "ELEFTDIV_EQ\n"; break; + case EPOW_EQ: std::cerr << "EPOW_EQ\n"; break; + case AND_EQ: std::cerr << "AND_EQ\n"; break; + case OR_EQ: std::cerr << "OR_EQ\n"; break; + case LSHIFT_EQ: std::cerr << "LSHIFT_EQ\n"; break; + case RSHIFT_EQ: std::cerr << "RSHIFT_EQ\n"; break; + case LSHIFT: std::cerr << "LSHIFT\n"; break; + case RSHIFT: std::cerr << "RSHIFT\n"; break; + case EXPR_AND_AND: std::cerr << "EXPR_AND_AND\n"; break; + case EXPR_OR_OR: std::cerr << "EXPR_OR_OR\n"; break; + case EXPR_AND: std::cerr << "EXPR_AND\n"; break; + case EXPR_OR: std::cerr << "EXPR_OR\n"; break; + case EXPR_NOT: std::cerr << "EXPR_NOT\n"; break; + case EXPR_LT: std::cerr << "EXPR_LT\n"; break; + case EXPR_LE: std::cerr << "EXPR_LE\n"; break; + case EXPR_EQ: std::cerr << "EXPR_EQ\n"; break; + case EXPR_NE: std::cerr << "EXPR_NE\n"; break; + case EXPR_GE: std::cerr << "EXPR_GE\n"; break; + case EXPR_GT: std::cerr << "EXPR_GT\n"; break; + case LEFTDIV: std::cerr << "LEFTDIV\n"; break; + case EMUL: std::cerr << "EMUL\n"; break; + case EDIV: std::cerr << "EDIV\n"; break; + case ELEFTDIV: std::cerr << "ELEFTDIV\n"; break; + case EPLUS: std::cerr << "EPLUS\n"; break; + case EMINUS: std::cerr << "EMINUS\n"; break; + case QUOTE: std::cerr << "QUOTE\n"; break; + case TRANSPOSE: std::cerr << "TRANSPOSE\n"; break; + case PLUS_PLUS: std::cerr << "PLUS_PLUS\n"; break; + case MINUS_MINUS: std::cerr << "MINUS_MINUS\n"; break; + case POW: std::cerr << "POW\n"; break; + case EPOW: std::cerr << "EPOW\n"; break; + + case NUM: + case IMAG_NUM: + { + token *tok_val = curr_lexer->current_token (); + std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM") + << " [" << tok_val->number () << "]\n"; + } + break; + + case STRUCT_ELT: + { + token *tok_val = curr_lexer->current_token (); + std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n"; + } + break; + + case NAME: + { + token *tok_val = curr_lexer->current_token (); + symbol_table::symbol_record *sr = tok_val->sym_rec (); + std::cerr << "NAME"; + if (sr) + std::cerr << " [" << sr->name () << "]"; + std::cerr << "\n"; + } + break; + + case END: std::cerr << "END\n"; break; + + case DQ_STRING: + case SQ_STRING: + { + token *tok_val = curr_lexer->current_token (); + + std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING") + << " [" << tok_val->text () << "]\n"; + } + break; + + case FOR: std::cerr << "FOR\n"; break; + case WHILE: std::cerr << "WHILE\n"; break; + case DO: std::cerr << "DO\n"; break; + case UNTIL: std::cerr << "UNTIL\n"; break; + case IF: std::cerr << "IF\n"; break; + case ELSEIF: std::cerr << "ELSEIF\n"; break; + case ELSE: std::cerr << "ELSE\n"; break; + case SWITCH: std::cerr << "SWITCH\n"; break; + case CASE: std::cerr << "CASE\n"; break; + case OTHERWISE: std::cerr << "OTHERWISE\n"; break; + case BREAK: std::cerr << "BREAK\n"; break; + case CONTINUE: std::cerr << "CONTINUE\n"; break; + case FUNC_RET: std::cerr << "FUNC_RET\n"; break; + case UNWIND: std::cerr << "UNWIND\n"; break; + case CLEANUP: std::cerr << "CLEANUP\n"; break; + case TRY: std::cerr << "TRY\n"; break; + case CATCH: std::cerr << "CATCH\n"; break; + case GLOBAL: std::cerr << "GLOBAL\n"; break; + case PERSISTENT: std::cerr << "PERSISTENT\n"; break; + case FCN_HANDLE: std::cerr << "FCN_HANDLE\n"; break; + case END_OF_INPUT: std::cerr << "END_OF_INPUT\n\n"; break; + case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break; + case FCN: std::cerr << "FCN\n"; break; + case CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break; + case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break; + case FUNCTION_FILE: std::cerr << "FUNCTION_FILE\n"; break; + case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break; + case METAQUERY: std::cerr << "METAQUERY\n"; break; + case GET: std::cerr << "GET\n"; break; + case SET: std::cerr << "SET\n"; break; + case PROPERTIES: std::cerr << "PROPERTIES\n"; break; + case METHODS: std::cerr << "METHODS\n"; break; + case EVENTS: std::cerr << "EVENTS\n"; break; + case CLASSDEF: std::cerr << "CLASSDEF\n"; break; + case '\n': std::cerr << "\\n\n"; break; + case '\r': std::cerr << "\\r\n"; break; + case '\t': std::cerr << "TAB\n"; break; + default: + { + if (tok < 256) + std::cerr << static_cast<char> (tok) << "\n"; + else + std::cerr << "UNKNOWN(" << tok << ")\n"; + } + break; + } +} + +static void +display_state (int state) +{ + std::cerr << "S: "; + + switch (state) + { + case INITIAL: + std::cerr << "INITIAL" << std::endl; + break; + + case COMMAND_START: + std::cerr << "COMMAND_START" << std::endl; + break; + + case MATRIX_START: + std::cerr << "MATRIX_START" << std::endl; + break; + + case SCRIPT_FILE_BEGIN: + std::cerr << "SCRIPT_FILE_BEGIN" << std::endl; + break; + + case FUNCTION_FILE_BEGIN: + std::cerr << "FUNCTION_FILE_BEGIN" << std::endl; + break; + + default: + std::cerr << "UNKNOWN START STATE!" << std::endl; + break; + } +} + +void +lexical_feedback::fatal_error (const char *msg) +{ + error (msg); + + OCTAVE_QUIT; + + yy_fatal_error (msg); +} + +void +lexical_feedback::lexer_debug (const char *pattern, const char *text) +{ + std::cerr << std::endl; + + display_state (YY_START); + + std::cerr << "P: " << pattern << std::endl; + std::cerr << "T: " << text << std::endl; +}
--- a/libinterp/parse-tree/oct-parse.yy +++ b/libinterp/parse-tree/oct-parse.yy @@ -86,6 +86,9 @@ #define malloc GNULIB_NAMESPACE::malloc #endif +// The state of the parser. +octave_parser *curr_parser = 0; + // Buffer for help text snagged from function files. std::stack<std::string> help_buf; @@ -156,200 +159,6 @@ 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); - // Finish building a statement. template <class T> static tree_statement * @@ -556,7 +365,7 @@ { $$ = 0; } | END_OF_INPUT { - curr_lexer->parser_end_of_input = 1; + curr_parser->end_of_input = true; $$ = 0; } | simple_list @@ -568,13 +377,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 @@ -584,13 +393,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 @@ -610,7 +419,7 @@ // WHILE, etc. word_list_cmd : identifier word_list - { $$ = make_index_expression ($1, $2, '('); } + { $$ = curr_parser->make_index_expression ($1, $2, '('); } ; word_list : string @@ -643,15 +452,15 @@ ; 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; } ; @@ -676,7 +485,7 @@ } | '[' matrix_rows ']' { - $$ = finish_matrix ($2); + $$ = curr_parser->finish_matrix ($2); curr_lexer->looking_at_matrix_or_assign_lhs = false; curr_lexer->pending_local_variables.clear (); } @@ -702,7 +511,7 @@ | '{' ';' '}' { $$ = new tree_constant (octave_value (Cell ())); } | '{' cell_rows '}' - { $$ = finish_cell ($2); } + { $$ = curr_parser->finish_cell ($2); } ; cell_rows : cell_rows1 @@ -722,14 +531,14 @@ 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); + $$ = curr_parser->make_fcn_handle ($2); curr_lexer->looking_at_function_handle--; } ; @@ -737,7 +546,7 @@ anon_fcn_handle : '@' param_list statement { curr_lexer->quote_is_transpose = false; - $$ = make_anon_fcn_handle ($2, $3); + $$ = curr_parser->make_anon_fcn_handle ($2, $3); } ; @@ -802,63 +611,63 @@ 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 @@ -873,29 +682,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 @@ -921,35 +730,35 @@ ; 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 @@ -992,12 +801,12 @@ declaration : GLOBAL parsing_decl_list decl1 { - $$ = make_decl_command (GLOBAL, $1, $3); + $$ = 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); + $$ = curr_parser->make_decl_command (PERSISTENT, $1, $3); curr_lexer->looking_at_decl_list = false; } ; @@ -1043,7 +852,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; } ; @@ -1061,7 +870,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 { @@ -1074,7 +883,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); } ; @@ -1088,7 +897,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; } ; @@ -1116,7 +925,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 @@ -1133,35 +942,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; } @@ -1173,17 +982,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; } ; @@ -1195,18 +1004,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; } ; @@ -1339,10 +1148,11 @@ script_file : SCRIPT_FILE opt_list END_OF_INPUT { tree_statement *end_of_script - = make_end ("endscript", curr_lexer->input_line_number, - curr_lexer->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; } @@ -1375,13 +1185,13 @@ 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 (); } ; @@ -1414,22 +1224,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 ()); + if (curr_parser->end_token_ok ($1, token::function_end)) + $$ = curr_parser->make_end ("endfunction", $1->line (), $1->column ()); else ABORT_PARSE; } @@ -1463,8 +1273,9 @@ YYABORT; } - $$ = make_end ("endfunction", curr_lexer->input_line_number, - curr_lexer->current_input_column); + $$ = curr_parser->make_end ("endfunction", + curr_lexer->input_line_number, + curr_lexer->current_input_column); } ; @@ -1483,8 +1294,8 @@ { curr_lexer->parsing_classdef = false; - if (end_token_ok ($1, token::classdef_end)) - $$ = make_end ("endclassdef", $1->line (), $1->column ()); + if (curr_parser->end_token_ok ($1, token::classdef_end)) + $$ = curr_parser->make_end ("endclassdef", $1->line (), $1->column ()); else ABORT_PARSE; } @@ -1729,10 +1540,17 @@ parse_error ("%s", msg.c_str ()); } +int +octave_parser::run (void) +{ + return octave_parse (); +} + // 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"; @@ -1783,8 +1601,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; @@ -1853,8 +1671,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) @@ -1873,8 +1691,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 ()) { @@ -1980,8 +1798,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; @@ -2044,8 +1862,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 (); @@ -2107,8 +1925,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 (); @@ -2120,8 +1938,9 @@ // 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 = curr_lexer->input_line_number; @@ -2153,9 +1972,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; @@ -2257,9 +2076,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; @@ -2289,8 +2108,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; @@ -2332,8 +2151,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; @@ -2371,10 +2190,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; @@ -2385,7 +2207,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); } @@ -2394,10 +2216,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; @@ -2408,7 +2232,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); } @@ -2417,10 +2241,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; @@ -2443,9 +2267,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; @@ -2465,11 +2291,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; @@ -2508,8 +2336,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; @@ -2523,8 +2351,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; @@ -2538,8 +2366,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; @@ -2553,8 +2381,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); @@ -2565,9 +2394,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; @@ -2597,9 +2426,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); @@ -2611,10 +2441,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; @@ -2644,9 +2474,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); @@ -2658,9 +2489,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; @@ -2754,8 +2585,9 @@ // 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; @@ -2788,9 +2620,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. @@ -2813,16 +2646,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; @@ -2921,9 +2755,10 @@ 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; @@ -2991,8 +2826,8 @@ return retval; } -static void -recover_from_parsing_function (void) +void +octave_parser::recover_from_parsing_function (void) { if (parser_symtab_context.empty ()) panic_impossible (); @@ -3014,9 +2849,9 @@ // 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; @@ -3047,8 +2882,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; @@ -3073,8 +2909,8 @@ // 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; @@ -3099,8 +2935,9 @@ // 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; @@ -3134,8 +2971,8 @@ 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"); @@ -3144,8 +2981,8 @@ // 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; @@ -3188,14 +3025,14 @@ // 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) { @@ -3209,9 +3046,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 (); @@ -3246,15 +3083,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); @@ -3500,10 +3338,14 @@ bool eof; frame.protect_var (curr_lexer); - curr_lexer = new lexical_feedback (); - - reset_parser (); + frame.add_fcn (lexical_feedback::cleanup, curr_lexer); + + frame.protect_var (curr_parser); + curr_parser = new octave_parser (); + frame.add_fcn (octave_parser::cleanup, curr_parser); + + curr_parser->reset (); std::string help_txt = gobble_leading_white_space (ffile, eof); @@ -3578,9 +3420,9 @@ help_buf.push (help_txt); if (reading_script_file) - prep_lexer_for_script_file (); + curr_lexer->prep_for_script_file (); else - prep_lexer_for_function_file (); + curr_lexer->prep_for_function_file (); curr_lexer->parsing_class_method = ! dispatch_type.empty (); @@ -3588,7 +3430,7 @@ global_command = 0; - int status = octave_parse_input (); + 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 @@ -3605,10 +3447,10 @@ else { tree_statement *end_of_script - = make_end ("endscript", curr_lexer->input_line_number, - curr_lexer->current_input_column); - - make_script (0, end_of_script); + = curr_parser->make_end ("endscript", curr_lexer->input_line_number, + curr_lexer->current_input_column); + + curr_parser->make_script (0, end_of_script); fcn_ptr = primary_fcn_ptr; } @@ -4306,6 +4148,12 @@ unwind_protect frame; frame.protect_var (curr_lexer); + curr_lexer = new lexical_feedback (); + frame.add_fcn (lexical_feedback::cleanup, curr_lexer); + + frame.protect_var (curr_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 (line_editing); @@ -4319,8 +4167,6 @@ frame.protect_var (reading_script_file); frame.protect_var (reading_classdef_file); - curr_lexer = new lexical_feedback (); - get_input_from_eval_string = true; line_editing = false; current_function_depth = 0; @@ -4344,7 +4190,7 @@ do { - reset_parser (); + curr_parser->reset (); frame.protect_var (global_command); @@ -4356,7 +4202,7 @@ symbol_table::scope_id scope = symbol_table::top_scope (); frame.add_fcn (symbol_table::unmark_forced_variables, scope); - parse_status = octave_parse_input (); + parse_status = curr_parser->run (); tree_statement_list *command_list = global_command; @@ -4418,7 +4264,7 @@ || tree_continue_command::continuing) break; } - else if (curr_lexer->parser_end_of_input) + else if (curr_parser->end_of_input) break; } } @@ -4465,12 +4311,6 @@ } } -int -octave_parse_input (void) -{ - return octave_parse (); -} - DEFUN (eval, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} eval (@var{try})\n\
--- a/libinterp/parse-tree/parse.h +++ b/libinterp/parse-tree/parse.h @@ -29,14 +29,40 @@ #include <stack> -extern void reset_parser (void); +#include "lex.h" +#include "token.h" + extern int octave_lex (void); +class octave_comment_list; +class octave_function; +class octave_user_function; class tree; -class tree_matrix; +class tree_anon_fcn_handle; +class tree_argument_list; +class tree_cell; +class tree_colon_expression; +class tree_command; +class tree_constant; +class tree_decl_command; +class tree_decl_init_list; +class tree_expression; +class tree_fcn_handle; +class tree_function_def; class tree_identifier; +class tree_if_clause; +class tree_if_command; +class tree_if_command_list; +class tree_index_expression; +class tree_matrix; +class tree_matrix; +class tree_parameter_list; +class tree_statement; class tree_statement_list; -class octave_function; +class tree_statement_listtree_statement; +class tree_switch_case; +class tree_switch_case_list; +class tree_switch_command; #include "oct-obj.h" @@ -106,6 +132,216 @@ extern OCTINTERP_API void cleanup_statement_list (tree_statement_list **lst); -extern OCTINTERP_API int octave_parse_input (void); +class +octave_parser +{ +public: + + octave_parser (void) : end_of_input (false) { } + + ~octave_parser (void) { } + + void reset (void) + { + curr_lexer->reset (); + } + + int run (void); + + // Error mesages for mismatched end tokens. + void end_error (const char *type, token::end_tok_type ettype, int l, int c); + + // Check to see that end tokens are properly matched. + 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. + void maybe_warn_assign_as_truth_value (tree_expression *expr); + + // Maybe print a warning about switch labels that aren't constants. + void maybe_warn_variable_switch_label (tree_expression *expr); + + // Finish building a range. + tree_expression *finish_colon_expression (tree_colon_expression *e); + + // Build a constant. + tree_constant *make_constant (int op, token *tok_val); + + // Build a function handle. + tree_fcn_handle *make_fcn_handle (token *tok_val); + + // Build an anonymous function handle. + tree_anon_fcn_handle * + make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt); + + // Build a binary expression. + tree_expression * + make_binary_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2); + + // Build a boolean expression. + tree_expression * + make_boolean_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2); + + // Build a prefix expression. + tree_expression * + make_prefix_op (int op, tree_expression *op1, token *tok_val); + + // Build a postfix expression. + tree_expression * + make_postfix_op (int op, tree_expression *op1, token *tok_val); + + // Build an unwind-protect command. + 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. + 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. + 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. + tree_command * + make_do_until_command (token *until_tok, tree_statement_list *body, + tree_expression *expr, octave_comment_list *lc); + + // Build a for command. + 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. + tree_command *make_break_command (token *break_tok); + + // Build a continue command. + tree_command *make_continue_command (token *continue_tok); + + // Build a return command. + tree_command *make_return_command (token *return_tok); + + // Start an if command. + tree_if_command_list * + start_if_command (tree_expression *expr, tree_statement_list *list); + + // Finish an if command. + 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. + tree_if_clause * + make_elseif_clause (token *elseif_tok, tree_expression *expr, + tree_statement_list *list, octave_comment_list *lc); + + // Finish a switch command. + 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. + 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. + tree_expression * + make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, + tree_expression *rhs); + + // Define a script. + void make_script (tree_statement_list *cmds, tree_statement *end_script); + + // Begin defining a function. + 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. + tree_statement *make_end (const std::string& type, int l, int c); + + // Do most of the work for defining a function. + octave_user_function * + frob_function (const std::string& fname, octave_user_function *fcn); + + // Finish defining a function. + tree_function_def * + finish_function (tree_parameter_list *ret_list, + octave_user_function *fcn, octave_comment_list *lc); + + // Reset state after parsing function. + void + recover_from_parsing_function (void); + + // Make an index expression. + tree_index_expression * + make_index_expression (tree_expression *expr, + tree_argument_list *args, char type); + + // Make an indirect reference expression. + tree_index_expression * + make_indirect_ref (tree_expression *expr, const std::string&); + + // Make an indirect reference expression with dynamic field name. + tree_index_expression * + make_indirect_ref (tree_expression *expr, tree_expression *field); + + // Make a declaration command. + 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. + tree_argument_list *validate_matrix_row (tree_argument_list *row); + + // Finish building a matrix list. + tree_expression *finish_matrix (tree_matrix *m); + + // Finish building a cell list. + tree_expression *finish_cell (tree_cell *c); + + // Maybe print a warning. Duh. + void maybe_warn_missing_semi (tree_statement_list *); + + // Set the print flag for a statement based on the separator type. + tree_statement_list * + set_stmt_print_flag (tree_statement_list *, char, bool); + + // Create a statement list. + tree_statement_list *make_statement_list (tree_statement *stmt); + + // Append a statement to an existing statement list. + tree_statement_list * + append_statement_list (tree_statement_list *list, char sep, + tree_statement *stmt, bool warn_missing_semi); + + // TRUE means that we have encountered EOF on the input stream. + bool end_of_input; + + // For unwind protect. + static void cleanup (octave_parser *parser) { delete parser; } + +private: + + // No copying! + + octave_parser (const octave_parser&); + + octave_parser& operator = (const octave_parser&); +}; + +// The current state of the parser. +extern octave_parser *curr_parser; #endif