# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1362069691 18000 # Node ID f279fd604c7e0d309af3efe691514d3f9bd542c8 # Parent 6a6fef2103eb94f381fb442e590244551f98efae# Parent 7eb614760ddb99d2569736c93a84a38ba3fae118 maint: merge in Julien's changes diff -r 6a6fef2103eb -r f279fd604c7e configure.ac --- a/configure.ac Thu Feb 28 08:57:27 2013 +0100 +++ b/configure.ac Thu Feb 28 11:41:31 2013 -0500 @@ -190,6 +190,17 @@ AC_DEFINE(BOUNDS_CHECKING, 1, [Define to 1 to use internal bounds checking.]) fi +### Enable experimental push parser. + +OCTAVE_USE_PUSH_PARSER=no +AC_ARG_ENABLE([push-parser], + [AS_HELP_STRING([--enable-push-parser], + [enable experimental push parser])], + [if test "$enableval" = yes; then OCTAVE_USE_PUSH_PARSER=yes; fi], []) +if test $OCTAVE_USE_PUSH_PARSER = yes; then + AC_DEFINE(OCTAVE_USE_PUSH_PARSER, 1, [Define to 1 to use experimental push parser.]) +fi + ### Use Octave's built-in memory allocator rather than straightforward malloc. ### Disabled by default. @@ -2974,6 +2985,7 @@ Build Java interface: $build_java Do internal array bounds checking: $BOUNDS_CHECKING Use octave_allocator: $USE_OCTAVE_ALLOCATOR + Use push parser: $OCTAVE_USE_PUSH_PARSER Build static libraries: $STATIC_LIBS Build shared libraries: $SHARED_LIBS Dynamic Linking: $ENABLE_DYNAMIC_LINKING $DL_API_MSG diff -r 6a6fef2103eb -r f279fd604c7e libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Thu Feb 28 08:57:27 2013 +0100 +++ b/libinterp/parse-tree/lex.h Thu Feb 28 11:41:31 2013 -0500 @@ -50,13 +50,13 @@ stream_reader& operator = (const stream_reader&); }; -// Forward decl for lexical_feedback::token_stack. +// Forward decl for octave_lexer::token_stack. class token; // For communication between the lexer and parser. class -lexical_feedback +octave_lexer { public: @@ -153,7 +153,7 @@ std::stack context; }; - lexical_feedback (void) + octave_lexer (void) : scanner (0), convert_spaces_to_comma (true), do_comma_insert (false), at_beginning_of_statement (true), looking_at_anon_fcn_args (false), looking_at_return_list (false), @@ -174,7 +174,7 @@ init (); } - ~lexical_feedback (void); + ~octave_lexer (void); void init (void); @@ -370,7 +370,7 @@ bbp_nesting_level nesting_level; // For unwind protect. - static void cleanup (lexical_feedback *lexer) { delete lexer; } + static void cleanup (octave_lexer *lexer) { delete lexer; } private: @@ -381,9 +381,9 @@ // No copying! - lexical_feedback (const lexical_feedback&); + octave_lexer (const octave_lexer&); - lexical_feedback& operator = (const lexical_feedback&); + octave_lexer& operator = (const octave_lexer&); }; #endif diff -r 6a6fef2103eb -r f279fd604c7e libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Thu Feb 28 08:57:27 2013 +0100 +++ b/libinterp/parse-tree/lex.ll Thu Feb 28 11:41:31 2013 -0500 @@ -109,7 +109,7 @@ #error lex.l requires flex version 2.5.4 or later #endif -#define YY_EXTRA_TYPE lexical_feedback * +#define YY_EXTRA_TYPE octave_lexer * #define curr_lexer yyextra // Arrange to get input via readline. @@ -353,7 +353,7 @@ curr_lexer->at_beginning_of_statement = false; int c = yytext[yyleng-1]; - bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE); + bool cont_is_spc = (curr_lexer->eat_continuation () != octave_lexer::NO_WHITESPACE); bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']'); @@ -379,7 +379,7 @@ curr_lexer->at_beginning_of_statement = false; int c = yytext[yyleng-1]; - bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE); + bool cont_is_spc = (curr_lexer->eat_continuation () != octave_lexer::NO_WHITESPACE); bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}'); @@ -409,7 +409,7 @@ if (! curr_lexer->looking_at_object_index.front ()) { - if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE) + if ((tmp & octave_lexer::NEWLINE) == octave_lexer::NEWLINE) { curr_lexer->maybe_warn_separator_insert (';'); @@ -446,7 +446,7 @@ && curr_lexer->nesting_level.is_bracket_or_brace () && curr_lexer->convert_spaces_to_comma) { - if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE) + if ((tmp & octave_lexer::NEWLINE) == octave_lexer::NEWLINE) { curr_lexer->maybe_warn_separator_insert (';'); @@ -1284,7 +1284,7 @@ flex_stream_reader : public stream_reader { public: - flex_stream_reader (lexical_feedback *l, char *buf_arg) + flex_stream_reader (octave_lexer *l, char *buf_arg) : stream_reader (), lexer (l), buf (buf_arg) { } @@ -1299,12 +1299,12 @@ flex_stream_reader& operator = (const flex_stream_reader&); - lexical_feedback *lexer; + octave_lexer *lexer; char *buf; }; -lexical_feedback::~lexical_feedback (void) +octave_lexer::~octave_lexer (void) { // Clear out the stack of token info used to track line and // column numbers. @@ -1319,7 +1319,7 @@ } void -lexical_feedback::init (void) +octave_lexer::init (void) { // The closest paren, brace, or bracket nesting is not an object // index. @@ -1327,14 +1327,14 @@ yylex_init (&scanner); - // Make lexical_feedback object available through yyextra in + // Make octave_lexer object available through yyextra in // flex-generated lexer. yyset_extra (this, scanner); } // Inside Flex-generated functions, yyg is the scanner cast to its real // type. The BEGIN macro uses yyg and we want to use that in -// lexical_feedback member functions. If we could set the start state +// octave_lexer member functions. If we could set the start state // by calling a function instead of using the BEGIN macro, we could // eliminate the OCTAVE_YYG macro. @@ -1342,7 +1342,7 @@ struct yyguts_t *yyg = static_cast (scanner) void -lexical_feedback::reset (void) +octave_lexer::reset (void) { OCTAVE_YYG; @@ -1372,7 +1372,7 @@ } void -lexical_feedback::prep_for_script_file (void) +octave_lexer::prep_for_script_file (void) { OCTAVE_YYG; @@ -1380,7 +1380,7 @@ } void -lexical_feedback::prep_for_function_file (void) +octave_lexer::prep_for_function_file (void) { OCTAVE_YYG; @@ -1388,7 +1388,7 @@ } int -lexical_feedback::octave_read (char *buf, unsigned max_size) +octave_lexer::octave_read (char *buf, unsigned max_size) { static const char * const eol = "\n"; static std::string input_buf; @@ -1452,13 +1452,13 @@ } char * -lexical_feedback::flex_yytext (void) +octave_lexer::flex_yytext (void) { return yyget_text (scanner); } int -lexical_feedback::flex_yyleng (void) +octave_lexer::flex_yyleng (void) { return yyget_leng (scanner); } @@ -1469,9 +1469,9 @@ // that we insert a comma ahead of it. void -lexical_feedback::do_comma_insert_check (void) +octave_lexer::do_comma_insert_check (void) { - bool spc_gobbled = (eat_continuation () != lexical_feedback::NO_WHITESPACE); + bool spc_gobbled = (eat_continuation () != octave_lexer::NO_WHITESPACE); int c = text_yyinput (); @@ -1485,7 +1485,7 @@ } int -lexical_feedback::text_yyinput (void) +octave_lexer::text_yyinput (void) { int c = yyinput (scanner); @@ -1523,7 +1523,7 @@ } void -lexical_feedback::xunput (char c, char *buf) +octave_lexer::xunput (char c, char *buf) { if (lexer_debug_flag) { @@ -1539,7 +1539,7 @@ } void -lexical_feedback::xunput (char c) +octave_lexer::xunput (char c) { char *yytxt = flex_yytext (); @@ -1550,7 +1550,7 @@ // really looking at. void -lexical_feedback::fixup_column_count (char *s) +octave_lexer::fixup_column_count (char *s) { char c; while ((c = *s++) != '\0') @@ -1566,7 +1566,7 @@ } bool -lexical_feedback::inside_any_object_index (void) +octave_lexer::inside_any_object_index (void) { bool retval = false; @@ -1586,7 +1586,7 @@ // Handle keywords. Return -1 if the keyword should be ignored. int -lexical_feedback::is_keyword_token (const std::string& s) +octave_lexer::is_keyword_token (const std::string& s) { int l = input_line_number; int c = current_input_column; @@ -1801,7 +1801,7 @@ } bool -lexical_feedback::is_variable (const std::string& name) +octave_lexer::is_variable (const std::string& name) { return (symbol_table::is_variable (name) || (pending_local_variables.find (name) @@ -1809,7 +1809,7 @@ } std::string -lexical_feedback::grab_block_comment (stream_reader& reader, bool& eof) +octave_lexer::grab_block_comment (stream_reader& reader, bool& eof) { std::string buf; @@ -1915,8 +1915,8 @@ } std::string -lexical_feedback::grab_comment_block (stream_reader& reader, bool at_bol, - bool& eof) +octave_lexer::grab_comment_block (stream_reader& reader, bool at_bol, + bool& eof) { std::string buf; @@ -2055,7 +2055,7 @@ } int -lexical_feedback::process_comment (bool start_in_block, bool& eof) +octave_lexer::process_comment (bool start_in_block, bool& eof) { OCTAVE_YYG; @@ -2109,7 +2109,7 @@ // replaced by a single LF. bool -lexical_feedback::next_token_is_sep_op (void) +octave_lexer::next_token_is_sep_op (void) { bool retval = false; @@ -2126,7 +2126,7 @@ // unary operator. This is ugly, but it seems to do the right thing. bool -lexical_feedback::next_token_is_postfix_unary_op (bool spc_prev) +octave_lexer::next_token_is_postfix_unary_op (bool spc_prev) { bool un_op = false; @@ -2173,7 +2173,7 @@ // parsed as a binary operator. bool -lexical_feedback::next_token_is_bin_op (bool spc_prev) +octave_lexer::next_token_is_bin_op (bool spc_prev) { bool bin_op = false; @@ -2274,7 +2274,7 @@ // FIXME -- we need to handle block comments here. void -lexical_feedback::scan_for_comments (const char *text) +octave_lexer::scan_for_comments (const char *text) { std::string comment_buf; @@ -2335,9 +2335,9 @@ // FIXME -- we need to handle block comments here. int -lexical_feedback::eat_whitespace (void) +octave_lexer::eat_whitespace (void) { - int retval = lexical_feedback::NO_WHITESPACE; + int retval = octave_lexer::NO_WHITESPACE; std::string comment_buf; @@ -2359,11 +2359,11 @@ comment_buf += static_cast (c); beginning_of_comment = false; } - retval |= lexical_feedback::SPACE_OR_TAB; + retval |= octave_lexer::SPACE_OR_TAB; break; case '\n': - retval |= lexical_feedback::NEWLINE; + retval |= octave_lexer::NEWLINE; if (in_comment) { comment_buf += static_cast (c); @@ -2448,7 +2448,7 @@ } void -lexical_feedback::handle_number (void) +octave_lexer::handle_number (void) { double value = 0.0; int nread = 0; @@ -2506,7 +2506,7 @@ // FIXME -- we need to handle block comments here. bool -lexical_feedback::have_continuation (bool trailing_comments_ok) +octave_lexer::have_continuation (bool trailing_comments_ok) { std::ostringstream buf; @@ -2594,7 +2594,7 @@ // line character. bool -lexical_feedback::have_ellipsis_continuation (bool trailing_comments_ok) +octave_lexer::have_ellipsis_continuation (bool trailing_comments_ok) { char c1 = text_yyinput (); if (c1 == '.') @@ -2618,9 +2618,9 @@ // whitespace on the next line. int -lexical_feedback::eat_continuation (void) +octave_lexer::eat_continuation (void) { - int retval = lexical_feedback::NO_WHITESPACE; + int retval = octave_lexer::NO_WHITESPACE; int c = text_yyinput (); @@ -2634,7 +2634,7 @@ } int -lexical_feedback::handle_string (char delim) +octave_lexer::handle_string (char delim) { std::ostringstream buf; @@ -2727,7 +2727,7 @@ } bool -lexical_feedback::next_token_is_assign_op (void) +octave_lexer::next_token_is_assign_op (void) { bool retval = false; @@ -2811,7 +2811,7 @@ } bool -lexical_feedback::next_token_is_index_op (void) +octave_lexer::next_token_is_index_op (void) { int c = text_yyinput (); xunput (c); @@ -2819,7 +2819,7 @@ } int -lexical_feedback::handle_close_bracket (bool spc_gobbled, int bracket_type) +octave_lexer::handle_close_bracket (bool spc_gobbled, int bracket_type) { OCTAVE_YYG; @@ -2887,7 +2887,7 @@ } void -lexical_feedback::maybe_unput_comma (int spc_gobbled) +octave_lexer::maybe_unput_comma (int spc_gobbled) { if (nesting_level.is_bracket () || (nesting_level.is_brace () @@ -2926,7 +2926,7 @@ } bool -lexical_feedback::next_token_can_follow_bin_op (void) +octave_lexer::next_token_can_follow_bin_op (void) { std::stack buf; @@ -2968,7 +2968,7 @@ } bool -lexical_feedback::looks_like_command_arg (void) +octave_lexer::looks_like_command_arg (void) { bool retval = true; @@ -3190,7 +3190,7 @@ } int -lexical_feedback::handle_superclass_identifier (void) +octave_lexer::handle_superclass_identifier (void) { eat_continuation (); @@ -3228,7 +3228,7 @@ } int -lexical_feedback::handle_meta_identifier (void) +octave_lexer::handle_meta_identifier (void) { eat_continuation (); @@ -3265,7 +3265,7 @@ // should be ignored. int -lexical_feedback::handle_identifier (void) +octave_lexer::handle_identifier (void) { OCTAVE_YYG; @@ -3277,7 +3277,7 @@ int c = yytxt[flex_yyleng()-1]; - bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE); + bool cont_is_spc = (eat_continuation () != octave_lexer::NO_WHITESPACE); int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); @@ -3434,7 +3434,7 @@ } void -lexical_feedback::maybe_warn_separator_insert (char sep) +octave_lexer::maybe_warn_separator_insert (char sep) { std::string nm = curr_fcn_file_full_name; @@ -3449,7 +3449,7 @@ } void -lexical_feedback::gripe_single_quote_string (void) +octave_lexer::gripe_single_quote_string (void) { std::string nm = curr_fcn_file_full_name; @@ -3464,7 +3464,7 @@ } void -lexical_feedback::gripe_matlab_incompatible (const std::string& msg) +octave_lexer::gripe_matlab_incompatible (const std::string& msg) { std::string nm = curr_fcn_file_full_name; @@ -3479,20 +3479,20 @@ } void -lexical_feedback::maybe_gripe_matlab_incompatible_comment (char c) +octave_lexer::maybe_gripe_matlab_incompatible_comment (char c) { if (c == '#') gripe_matlab_incompatible ("# used as comment character"); } void -lexical_feedback::gripe_matlab_incompatible_continuation (void) +octave_lexer::gripe_matlab_incompatible_continuation (void) { gripe_matlab_incompatible ("\\ used as line continuation marker"); } void -lexical_feedback::gripe_matlab_incompatible_operator (const std::string& op) +octave_lexer::gripe_matlab_incompatible_operator (const std::string& op) { std::string t = op; int n = t.length (); @@ -3502,7 +3502,7 @@ } void -lexical_feedback::push_token (token *tok) +octave_lexer::push_token (token *tok) { YYSTYPE *lval = yyget_lval (scanner); lval->tok_val = tok; @@ -3510,14 +3510,14 @@ } token * -lexical_feedback::current_token (void) +octave_lexer::current_token (void) { YYSTYPE *lval = yyget_lval (scanner); return lval->tok_val; } void -lexical_feedback::display_token (int tok) +octave_lexer::display_token (int tok) { switch (tok) { @@ -3688,7 +3688,7 @@ } void -lexical_feedback::fatal_error (const char *msg) +octave_lexer::fatal_error (const char *msg) { error (msg); @@ -3698,7 +3698,7 @@ } void -lexical_feedback::lexer_debug (const char *pattern, const char *text) +octave_lexer::lexer_debug (const char *pattern, const char *text) { OCTAVE_YYG; diff -r 6a6fef2103eb -r f279fd604c7e libinterp/parse-tree/oct-parse.yy --- a/libinterp/parse-tree/oct-parse.yy Thu Feb 28 08:57:27 2013 +0100 +++ b/libinterp/parse-tree/oct-parse.yy Thu Feb 28 11:41:31 2013 -0500 @@ -84,7 +84,7 @@ // Global access to currently active lexer. // FIXME -- to be removed after more parser+lexer refactoring. -lexical_feedback *CURR_LEXER = 0; +octave_lexer *CURR_LEXER = 0; #if defined (GNULIB_NAMESPACE) // Calls to the following functions appear in the generated output from @@ -166,6 +166,7 @@ // object) relevant global values before and after the nested call. %define api.pure +%define api.push-pull both %parse-param { octave_parser *curr_parser } %lex-param { void *scanner } @@ -1479,10 +1480,66 @@ curr_parser->bison_error (s); } +octave_parser::~octave_parser (void) +{ +#if defined (USE_PUSH_PARSER) + yypstate_delete (parser_state); +#endif + +delete curr_lexer; +} +void octave_parser::init (void) +{ +#if defined (USE_PUSH_PARSER) + parser_state = yypstate_new (); +#endif + + CURR_LEXER = curr_lexer; +} + int octave_parser::run (void) { - return octave_parse (this); + int status = 0; + +#if defined (USE_PUSH_PARSER) + + for (;;) + { + unwind_protect frame; + + frame.protect_var (current_input_line); + + bool eof = false; + + get_user_input (eof); + + do + { + octave_char = eof ? END_OF_INPUT : octave_lex (); + + if (octave_char == 0) + { + // Attempt to get more input. + status = -1; + break; + } + + status = octave_push_parse (pstate); + } + while (status == YYPUSH_MORE); + + if (status >= 0) + break; + } + +#else + + status = octave_parse (this); + +#endif + + return status; } // Error mesages for mismatched end tokens. diff -r 6a6fef2103eb -r f279fd604c7e libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Thu Feb 28 08:57:27 2013 +0100 +++ b/libinterp/parse-tree/parse.h Thu Feb 28 11:41:31 2013 -0500 @@ -131,7 +131,7 @@ // Global access to currently active lexer. // FIXME -- to be removed after more parser+lexer refactoring. -extern lexical_feedback *CURR_LEXER; +extern octave_lexer *CURR_LEXER; class octave_parser @@ -144,15 +144,14 @@ parsing_subfunctions (false), max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1), curr_class_name (), function_scopes (), primary_fcn_ptr (0), - curr_lexer (new lexical_feedback ()) + curr_lexer (new octave_lexer ()), parser_state (0) { - CURR_LEXER = curr_lexer; + init (); } - ~octave_parser (void) - { - delete curr_lexer; - } + ~octave_parser (void); + + void init (void); void reset (void) { @@ -387,7 +386,11 @@ octave_function *primary_fcn_ptr; // State of the lexer. - lexical_feedback *curr_lexer; + octave_lexer *curr_lexer; + + // Internal state of the parser. Only used if USE_PUSH_PARSER is + // defined. + void *parser_state; // For unwind protect. static void cleanup (octave_parser *parser) { delete parser; }