# HG changeset patch # User ryanru # Date 1239082180 21600 diff --git a/src/input.cc b/src/input.cc --- a/src/input.cc +++ b/src/input.cc @@ -115,6 +115,9 @@ // TRUE means we're parsing a function file. bool reading_fcn_file = false; +// TRUE means we're parsing a classdef file. +bool reading_classdef_file = false; + // Simple name of function file we are reading. std::string curr_fcn_file_name; @@ -216,7 +219,7 @@ FILE *curr_stream = command_editor::get_input_stream (); - if (reading_fcn_file || reading_script_file) + if (reading_fcn_file || reading_script_file || reading_classdef_file) curr_stream = ff_instream; retval = octave_fgets (curr_stream); @@ -259,6 +262,7 @@ if ((interactive || forced_interactive) && (! (reading_fcn_file + || reading_classdef_file || reading_script_file || input_from_startup_file || input_from_command_line_file))) @@ -304,7 +308,7 @@ || history_skip_auto_repeated_debugging_command)) command_history::add (current_input_line); - if (! (reading_fcn_file || reading_script_file)) + if (! (reading_fcn_file || reading_script_file || reading_classdef_file)) { octave_diary << current_input_line; @@ -314,9 +318,9 @@ do_input_echo (current_input_line); } - else if (! (reading_fcn_file || reading_script_file)) + else if (! (reading_fcn_file || reading_script_file || reading_classdef_file)) octave_diary << "\n"; - + return retval; } @@ -386,7 +390,7 @@ // Make sure input ends with a new line character. if (chars_left == 0 && buf[len-1] != '\n') { - if (len < max_size) + if (len < max_size) { // There is enough room to plug the newline character in // the buffer. @@ -409,7 +413,7 @@ { status = 0; } - else + else status = -1; return status; @@ -429,7 +433,7 @@ if (! instream && warn) warning ("%s: no such file or directory", name.c_str ()); - if (reading_fcn_file || reading_script_file) + if (reading_fcn_file || reading_script_file || reading_classdef_file) ff_instream = instream; else command_editor::set_input_stream (instream); @@ -684,7 +688,7 @@ // global_command = 0; if (octave_completion_matches_called) - octave_completion_matches_called = false; + octave_completion_matches_called = false; } // Restore previous value of global_command. diff --git a/src/input.h b/src/input.h --- a/src/input.h +++ b/src/input.h @@ -66,6 +66,9 @@ // TRUE means we're parsing a script file. extern bool reading_script_file; +// TRUE means we're parsing a classdef file. +extern bool reading_classdef_file; + // If we are reading from an M-file, this is it. extern FILE *ff_instream; diff --git a/src/lex.h b/src/lex.h --- a/src/lex.h +++ b/src/lex.h @@ -132,8 +132,15 @@ // -1 ==> Yes, but it is the last one because we have seen EOF. int parsing_nested_function; - // TRUE means we are parsing a class method. + // TRUE means we are parsing a class method in function or classdef file. bool parsing_class_method; + + // TRUE means we are parsing a class method declaration line in a classdef file and can + // accept a property get or set method name ie. "get.PropertyName" as a function name. + bool maybe_classdef_get_set_method; + + // TRUE means we are parsing a classdef file + bool parsing_classdef; // Return transpose or start a string? bool quote_is_transpose; diff --git a/src/lex.l b/src/lex.l --- a/src/lex.l +++ b/src/lex.l @@ -293,6 +293,8 @@ static void handle_number (void); static int handle_string (char delim); static int handle_close_bracket (bool spc_gobbled, int bracket_type); +static int handle_superclass_identifier (void); +static int handle_meta_identifier (void); static int handle_identifier (void); static bool have_continuation (bool trailing_comments_ok = true); static bool have_ellipsis_continuation (bool trailing_comments_ok = true); @@ -703,7 +705,7 @@ { warning ("block comment open at end of input"); - if ((reading_fcn_file || reading_script_file) + if ((reading_fcn_file || reading_script_file || reading_classdef_file) && ! curr_fcn_file_name.empty ()) warning ("near line %d of file `%s.m'", input_line_number, curr_fcn_file_name.c_str ()); @@ -731,7 +733,43 @@ } %{ -// Function handles. +// Superclass method identifiers. +%} + address@hidden | address@hidden { + LEXER_DEBUG ("address@hidden|address@hidden"); + + int id_tok = handle_superclass_identifier (); + + if (id_tok >= 0) + { + lexer_flags.looking_for_object_index = true; + + COUNT_TOK_AND_RETURN (SUPERCLASSREF); + } + } + +%{ +// Metaclass query +%} + +\?{IDENT}{S}* | +\?{IDENT}.{IDENT}{S}* { + LEXER_DEBUG ("\?{IDENT}{S}* | \?{IDENT}.{IDENT}{S}*"); + + int id_tok = handle_meta_identifier (); + + if (id_tok >= 0) + { + lexer_flags.looking_for_object_index = true; + + COUNT_TOK_AND_RETURN (METAQUERY); + } + } + +%{ +// Function handles and superclass references %} "@" { @@ -746,6 +784,7 @@ lexer_flags.at_beginning_of_statement = false; COUNT_TOK_AND_RETURN ('@'); + } %{ @@ -890,7 +929,6 @@ "||" { LEXER_DEBUG ("||"); BIN_OP_RETURN (EXPR_OR_OR, false, false); } "<<" { LEXER_DEBUG ("<<"); XBIN_OP_RETURN (LSHIFT, false, false); } ">>" { LEXER_DEBUG (">>"); XBIN_OP_RETURN (RSHIFT, false, false); } - {NOT} { LEXER_DEBUG ("{NOT}"); @@ -1087,7 +1125,7 @@ } // Can be reset by defining a function. - if (! (reading_script_file || reading_fcn_file)) + if (! (reading_script_file || reading_fcn_file || reading_classdef_file)) { current_input_column = 1; input_line_number = command_editor::current_command_number (); @@ -1097,6 +1135,7 @@ // input. if ((interactive || forced_interactive) && ! (reading_fcn_file + || reading_classdef_file || reading_script_file || get_input_from_eval_string || input_from_startup_file)) @@ -1395,7 +1434,7 @@ lexer_flags.defining_func = true; lexer_flags.parsed_function_name = false; - if (! (reading_fcn_file || reading_script_file)) + if (! (reading_fcn_file || reading_script_file || reading_classdef_file)) input_line_number = 1; } @@ -1465,14 +1504,15 @@ break; case end_kw: - if (inside_any_object_index () + if (!reading_classdef_file + && (inside_any_object_index () || (lexer_flags.defining_func && ! (lexer_flags.looking_at_return_list - || lexer_flags.parsed_function_name))) + || lexer_flags.parsed_function_name)))) return 0; else { - if (reading_fcn_file && end_tokens_expected == 1) + if (reading_fcn_file && end_tokens_expected == 1) return -1; else { @@ -1531,6 +1571,30 @@ lexer_flags.at_beginning_of_statement = true; end_tokens_expected--; break; + + case endclassdef_kw: + yylval.tok_val = new token (token::classdef_end, l, c); + lexer_flags.at_beginning_of_statement = true; + end_tokens_expected--; + break; + + case endevents_kw: + yylval.tok_val = new token (token::events_end, l, c); + lexer_flags.at_beginning_of_statement = true; + end_tokens_expected--; + break; + + case endmethods_kw: + yylval.tok_val = new token (token::methods_end, l, c); + lexer_flags.at_beginning_of_statement = true; + end_tokens_expected--; + break; + + case endproperties_kw: + yylval.tok_val = new token (token::properties_end, l, c); + lexer_flags.at_beginning_of_statement = true; + end_tokens_expected--; + break; case for_kw: case while_kw: @@ -1557,13 +1621,33 @@ end_tokens_expected++; promptflag--; break; + + case get_kw: + case set_kw: + /* 'get' and 'set' are keywords in classdef method declarations */ + if (!lexer_flags.maybe_classdef_get_set_method) + return 0; + break; + + case properties_kw: + case methods_kw: + case events_kw: + /* 'properties', 'methods' and 'events' are keywords for classdef blocks */ + if (!lexer_flags.parsing_classdef) + return 0; + /* Fall through ... */ + case classdef_kw: + /* 'classdef' is a keyword always */ + end_tokens_expected++; + promptflag--; + break; case function_kw: { if (lexer_flags.defining_func) { if (reading_fcn_file) - { + { if (lexer_flags.parsing_nested_function) { BEGIN (NESTED_FUNCTION_END); @@ -1582,11 +1666,16 @@ return FCN; } } + else if (reading_classdef_file) + { + prep_for_function (); + return FCN; + } else { error ("nested functions not implemented in this context"); - if ((reading_fcn_file || reading_script_file) + if ((reading_fcn_file || reading_script_file || reading_classdef_file) && ! curr_fcn_file_name.empty ()) error ("near line %d of file `%s.m'", input_line_number, curr_fcn_file_name.c_str ()); @@ -1596,14 +1685,15 @@ return LEXICAL_ERROR; } } - else + else prep_for_function (); + } break; case magic_file_kw: { - if ((reading_fcn_file || reading_script_file) + 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); else @@ -3069,6 +3159,84 @@ return retval; } +static int +handle_superclass_identifier (void) +{ + + int c = yytext[yyleng-1]; + int cont_is_spc = eat_continuation (); + int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); + + std::string pkg; + std::string meth = strip_trailing_whitespace (yytext); + size_t pos = meth.find ("@"); + std::string cls = meth.substr (pos).substr (1); + meth = meth.substr (0, pos - 1); + + pos = cls.find ("."); + if (pos != std::string::npos) + { + pkg = cls.substr (pos).substr (1); + cls = cls.substr (0, pos - 1); + } + + int kw_token = is_keyword_token (meth) || is_keyword_token(cls) || is_keyword_token(pkg); + if (kw_token) + { + error ("method, class and package names may not be keywords"); + return LEXICAL_ERROR; + } + + yylval.tok_val = new token ( + meth.empty () ? NULL : &(symbol_table::insert (meth)), + cls.empty () ? NULL : &(symbol_table::insert (cls)), + pkg.empty () ? NULL : &(symbol_table::insert (pkg)), + input_line_number, current_input_column); + token_stack.push (yylval.tok_val); + + lexer_flags.convert_spaces_to_comma = true; + current_input_column += yyleng; + + return SUPERCLASSREF; +} + +static int +handle_meta_identifier (void) +{ + + int c = yytext[yyleng-1]; + int cont_is_spc = eat_continuation (); + int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t'); + + std::string pkg; + std::string cls = strip_trailing_whitespace (yytext).substr (1); + size_t pos = cls.find ("."); + + if (pos != std::string::npos) + { + pkg = cls.substr (pos).substr (1); + cls = cls.substr (0, pos - 1); + } + + int kw_token = is_keyword_token (cls) || is_keyword_token(pkg); + if (kw_token) + { + error ("class and package names may not be keywords"); + return LEXICAL_ERROR; + } + + yylval.tok_val = new token ( + cls.empty () ? NULL : &(symbol_table::insert (cls)), + pkg.empty () ? NULL : &(symbol_table::insert (pkg)), + input_line_number, current_input_column); + token_stack.push (yylval.tok_val); + + lexer_flags.convert_spaces_to_comma = true; + current_input_column += yyleng; + + return METAQUERY; +} + // Figure out exactly what kind of token to return when we have seen // an identifier. Handles keywords. Return -1 if the identifier // should be ignored. @@ -3214,7 +3382,7 @@ tok = "__end__"; yylval.tok_val = new token (&(symbol_table::insert (tok)), - input_line_number, current_input_column); + input_line_number, current_input_column); token_stack.push (yylval.tok_val); @@ -3254,6 +3422,10 @@ parsed_function_name = false; parsing_nested_function = 0; parsing_class_method = false; + + // + maybe_classdef_get_set_method = false; + parsing_classdef = false; // Not initiallly looking at a function handle. looking_at_function_handle = 0; @@ -3493,6 +3665,14 @@ 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 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; diff --git a/src/octave.gperf b/src/octave.gperf --- a/src/octave.gperf +++ b/src/octave.gperf @@ -30,6 +30,7 @@ break_kw, case_kw, catch_kw, + classdef_kw, continue_kw, do_kw, else_kw, @@ -37,19 +38,28 @@ end_kw, end_try_catch_kw, end_unwind_protect_kw, + endclassdef_kw, + endevents_kw, endfor_kw, endfunction_kw, endif_kw, + endmethods_kw, + endproperties_kw, endswitch_kw, endwhile_kw, + events_kw, for_kw, function_kw, + get_kw, global_kw, if_kw, + properties_kw, magic_file_kw, magic_line_kw, + methods_kw, otherwise_kw, return_kw, + set_kw, static_kw, switch_kw, try_kw, @@ -65,24 +75,34 @@ case, CASE, case_kw catch, CATCH, catch_kw continue, CONTINUE, continue_kw +classdef, CLASSDEF, classdef_kw do, DO, do_kw else, ELSE, else_kw elseif, ELSEIF, elseif_kw end, END, end_kw end_try_catch, END, end_try_catch_kw end_unwind_protect, END, end_unwind_protect_kw +endclassdef, END, endclassdef_kw +endevents, END, endevents_kw endfor, END, endfor_kw endfunction, END, endfunction_kw endif, END, endif_kw +endmethods, END, endmethods_kw +endproperties, END, endproperties_kw endswitch, END, endswitch_kw endwhile, END, endwhile_kw +events, EVENTS, events_kw for, FOR, for_kw function, FCN, function_kw +get, GET, get_kw global, GLOBAL, global_kw if, IF, if_kw otherwise, OTHERWISE, otherwise_kw persistent, STATIC, static_kw +properties, PROPERTIES, properties_kw +methods, METHODS, methods_kw return, FUNC_RET, return_kw +set, SET, set_kw static, STATIC, static_kw switch, SWITCH, switch_kw try, TRY, try_kw diff --git a/src/parse.y b/src/parse.y --- a/src/parse.y +++ b/src/parse.y @@ -395,6 +395,7 @@ tree_statement *tree_statement_type; tree_statement_list *tree_statement_list_type; octave_user_function *octave_user_function_type; + void *void_type; } // Tokens with line and column information. @@ -421,15 +422,22 @@ %token TRY CATCH %token GLOBAL STATIC %token FCN_HANDLE +%token PROPERTIES +%token METHODS +%token EVENTS +%token METAQUERY +%token SUPERCLASSREF +%token GET SET // Other tokens. %token END_OF_INPUT LEXICAL_ERROR -%token FCN SCRIPT +%token FCN SCRIPT CLASSDEF // %token VARARGIN VARARGOUT %token CLOSE_BRACE // Nonterminals we construct. -%type stash_comment function_beg +%type stash_comment function_beg classdef_beg +%type class_properties_beg class_methods_beg class_events_beg %type sep_no_nl opt_sep_no_nl sep opt_sep %type input %type string constant magic_colon @@ -440,16 +448,16 @@ %type matrix cell %type primary_expr postfix_expr prefix_expr binary_expr %type simple_expr colon_expr assign_expr expression -%type identifier fcn_name -%type function1 function2 +%type identifier fcn_name superclass_identifier meta_identifier +%type function1 function2 classdef1 %type word_list_cmd %type colon_expr1 %type arg_list word_list assign_lhs %type cell_or_matrix_row %type param_list param_list1 param_list2 -%type return_list return_list1 +%type return_list return_list1 superclasses opt_superclasses %type command select_command loop_command -%type jump_command except_command function script +%type jump_command except_command function script classdef %type if_command %type elseif_clause else_clause %type if_cmd_list1 if_cmd_list @@ -459,9 +467,20 @@ %type decl2 %type decl1 %type declaration -%type statement function_end +%type statement function_end classdef_end %type simple_list simple_list1 list list1 %type opt_list input1 +// These types need to be specified. +%type attr class_event class_property +%type class_properties_list +%type class_properties_block +%type class_methods_list +%type class_methods_block +%type opt_attr_list +%type attr_list +%type class_events_list +%type class_events_block +%type class_body // Precedence and associativity. %left ';' ',' '\n' @@ -581,6 +600,18 @@ } ; +superclass_identifier : SUPERCLASSREF + { + $$ = new tree_identifier ($1->line (), $1->column ()); + } + ; + +meta_identifier : METAQUERY + { + $$ = new tree_identifier ($1->line (), $1->column ()); + } + ; + string : DQ_STRING { $$ = make_constant (DQ_STRING, $1); } | SQ_STRING @@ -676,8 +707,8 @@ anon_fcn_handle : '@' param_list statement { $$ = make_anon_fcn_handle ($2, $3); } ; - -primary_expr : identifier + +primary_expr : identifier { $$ = $1; } | constant { $$ = $1; } @@ -686,6 +717,10 @@ | matrix { $$ = $1; } | cell + { $$ = $1; } + | meta_identifier + { $$ = $1; } + | superclass_identifier { $$ = $1; } | '(' expression ')' { $$ = $2->mark_in_parens (); } @@ -905,6 +940,8 @@ { $$ = $1; } | script { $$ = $1; } + | classdef + { $$ = $1; } ; // ===================== @@ -1225,24 +1262,38 @@ $$ = 0; } - ; + ; // =================== // Function definition // =================== +maybe_property_get_set : // empty + { + if (reading_classdef_file || lexer_flags.parsing_classdef) + { + lexer_flags.maybe_classdef_get_set_method = true; + } + } + ; + function_beg : push_fcn_symtab FCN stash_comment - { $$ = $3; } - ; - -function : function_beg function1 + { $$ = $3; + if (reading_classdef_file || lexer_flags.parsing_classdef) + { + lexer_flags.parsing_class_method = true; + } + } + ; + +function : function_beg function1 { $$ = finish_function (0, $2, $1); recover_from_parsing_function (); } - | function_beg return_list '=' function1 - { - $$ = finish_function ($2, $4, $1); + | function_beg return_list maybe_property_get_set '=' function1 + { + $$ = finish_function ($2, $5, $1); recover_from_parsing_function (); } ; @@ -1257,8 +1308,19 @@ ? id_name : curr_fcn_file_name; lexer_flags.parsed_function_name = true; - - $$ = $1; + lexer_flags.maybe_classdef_get_set_method = false; + + $$ = $1; + } + | GET '.' identifier + { + lexer_flags.maybe_classdef_get_set_method = false; + $$ = $3; + } + | SET '.' identifier + { + lexer_flags.maybe_classdef_get_set_method = false; + $$ = $3; } ; @@ -1291,14 +1353,215 @@ if (lexer_flags.parsing_nested_function) lexer_flags.parsing_nested_function = -1; - if (reading_fcn_file || reading_script_file - || get_input_from_eval_string) + if ((reading_fcn_file || reading_script_file + || get_input_from_eval_string) && !reading_classdef_file) $$ = make_end ("endfunction", input_line_number, current_input_column); else YYABORT; } ; + + +// ============= +// Classdef +// ============= + +classdef_beg : CLASSDEF stash_comment + { + lexer_flags.parsing_classdef = true; + $$ = NULL; + } + ; + +classdef_end : END + { + lexer_flags.parsing_classdef = false; + $$ = NULL; + } + ; + +classdef1 : classdef_beg opt_attr_list identifier opt_superclasses + { + $$ = NULL; + } + ; + +classdef : classdef1 '\n' class_body '\n' stash_comment classdef_end + { + $$ = NULL; + } + ; + +opt_attr_list : // empty + { + $$ = NULL; + } + | '(' attr_list ')' + { + $$ = NULL; + } + ; + +attr_list : attr + { + $$ = NULL; + } + | attr_list ',' attr + { + $$ = NULL; + } + ; + +attr : identifier + { + $$ = NULL; + } + | identifier '=' decl_param_init expression + { + $$ = NULL; + } + | EXPR_NOT identifier + { + $$ = NULL; + } + ; + +opt_superclasses : // empty + { + $$ = NULL; + } + | superclasses + { + $$ = NULL; + } + ; + +superclasses : EXPR_LT identifier '.' identifier + { + $$ = NULL; + } + | EXPR_LT identifier + { + $$ = NULL; + } + | superclasses EXPR_AND identifier '.' identifier + { + $$ = NULL; + } + | superclasses EXPR_AND identifier + { + $$ = NULL; + } + ; + +class_body : class_properties_block + { + $$ = NULL; + } + | class_methods_block + { + $$ = NULL; + } + | class_events_block + { + $$ = NULL; + } + | class_body '\n' class_properties_block + { + $$ = NULL; + } + | class_body '\n' class_methods_block + { + $$ = NULL; + } + | class_body '\n' class_events_block + { + $$ = NULL; + } + ; + +class_properties_beg : PROPERTIES stash_comment + { + $$ = NULL; + } + ; + +class_properties_block : class_properties_beg opt_attr_list '\n' class_properties_list '\n' END + { + $$ = NULL; + } + ; + +class_properties_list : class_property + { + $$ = NULL; + } + | class_properties_list '\n' class_property + { + $$ = NULL; + } + ; + +class_property : identifier + { + $$ = NULL; + } + | identifier '=' decl_param_init expression ';' + { + $$ = NULL; + } + ; + +class_methods_beg : METHODS stash_comment + { + $$ = NULL; + } + ; + +class_methods_block : class_methods_beg opt_attr_list '\n' class_methods_list '\n' END + { + $$ = NULL; + } + ; + +class_methods_list : function + { + $$ = NULL; + } + | class_methods_list '\n' function + { + $$ = NULL; + } + ; + +class_events_beg : EVENTS stash_comment + { + $$ = NULL; + } + ; + +class_events_block : class_events_beg opt_attr_list '\n' class_events_list '\n' END + { + $$ = NULL; + } + ; + +class_events_list : class_event + { + $$ = NULL; + } + | class_events_list '\n' class_event + { + $$ = NULL; + } + ; + +class_event : identifier + { + $$ = NULL; + } + ; // ============= // Miscellaneous @@ -1360,7 +1623,7 @@ std::ostringstream output_buf; - if (reading_fcn_file || reading_script_file) + if (reading_fcn_file || reading_script_file || reading_classdef_file) output_buf << "parse error near line " << input_line_number << " of file " << curr_fcn_file_full_name; else @@ -2579,7 +2842,7 @@ // file. Matlab doesn't provide a diagnostic (it ignores the stated // name). - if (reading_fcn_file || autoloading) + if (reading_fcn_file || reading_classdef_file || autoloading) { if (! (autoloading || lexer_flags.parsing_nested_function @@ -3138,6 +3401,25 @@ return status; } + +static bool +looking_at_classdef_keyword (FILE *ffile) +{ + bool status = false; + + long pos = ftell (ffile); + + char buf [10]; + fgets (buf, 10, ffile); + size_t len = strlen (buf); + if (len > 8 && strncmp (buf, "classdef", 8) == 0 + && ! (isalnum (buf[8]) || buf[8] == '_')) + status = true; + + fseek (ffile, pos, SEEK_SET); + + return status; + } static void restore_command_history (void *) @@ -3229,6 +3511,20 @@ Vecho_executing_commands = ECHO_OFF; reading_fcn_file = true; + } + else if (! force_script && looking_at_classdef_keyword (ffile)) + { + file_type = "classdef"; + + // The value of `reading_fcn_file' will be restored to the + // proper value when we unwind from this frame. + reading_fcn_file = old_reading_fcn_file_state; + + unwind_protect_int (Vecho_executing_commands); + unwind_protect_bool (reading_classdef_file); + + Vecho_executing_commands = ECHO_OFF; + reading_classdef_file = true; } else { diff --git a/src/token.cc b/src/token.cc --- a/src/token.cc +++ b/src/token.cc @@ -81,6 +81,28 @@ sr = s; } +token::token (symbol_table::symbol_record *cls, + symbol_table::symbol_record *pkg, int l, int c) +{ + line_num = l; + column_num = c; + type_tag = meta_rec_token; + mc.cr = cls; + mc.pr = pkg; +} + +token::token (symbol_table::symbol_record *mth, + symbol_table::symbol_record *cls, + symbol_table::symbol_record *pkg, int l, int c) +{ + line_num = l; + column_num = c; + type_tag = scls_rec_token; + sc.mr = mth; + sc.cr = cls; + sc.pr = pkg; +} + token::~token (void) { if (type_tag == string_token) @@ -122,6 +144,41 @@ return sr; } +symbol_table::symbol_record * +token::method_rec (void) +{ + assert (type_tag == scls_rec_token); + return sc.mr; +} + +symbol_table::symbol_record * +token::class_rec (void) +{ + assert (type_tag == scls_rec_token); + return sc.cr; +} + +symbol_table::symbol_record * +token::package_rec (void) +{ + assert (type_tag == scls_rec_token); + return sc.pr; +} + +symbol_table::symbol_record * +token::meta_class_rec (void) +{ + assert (type_tag == meta_rec_token); + return mc.cr; +} + +symbol_table::symbol_record * +token::meta_package_rec (void) +{ + assert (type_tag == meta_rec_token); + return mc.pr; +} + std::string token::text_rep (void) { diff --git a/src/token.h b/src/token.h --- a/src/token.h +++ b/src/token.h @@ -38,15 +38,21 @@ double_token, ettype_token, pttype_token, - sym_rec_token + sym_rec_token, + scls_rec_token, + meta_rec_token }; enum end_tok_type { simple_end, + classdef_end, + events_end, for_end, function_end, if_end, + methods_end, + properties_end, switch_end, while_end, try_catch_end, @@ -67,6 +73,11 @@ token (end_tok_type t, int l = -1, int c = -1); token (plot_tok_type t, int l = -1, int c = -1); token (symbol_table::symbol_record *s, int l = -1, int c = -1); + token (symbol_table::symbol_record *cls, + symbol_table::symbol_record *pkg, int l = -1, int c = -1); + token (symbol_table::symbol_record *mth, + symbol_table::symbol_record *cls, + symbol_table::symbol_record *pkg, int l = -1, int c = -1); ~token (void); @@ -78,6 +89,13 @@ end_tok_type ettype (void); plot_tok_type pttype (void); symbol_table::symbol_record *sym_rec (void); + + symbol_table::symbol_record *method_rec (void); + symbol_table::symbol_record *class_rec (void); + symbol_table::symbol_record *package_rec (void); + + symbol_table::symbol_record *meta_class_rec (void); + symbol_table::symbol_record *meta_package_rec (void); std::string text_rep (void); @@ -99,6 +117,17 @@ end_tok_type et; plot_tok_type pt; symbol_table::symbol_record *sr; + struct + { + symbol_table::symbol_record *mr; + symbol_table::symbol_record *cr; + symbol_table::symbol_record *pr; + } sc; + struct + { + symbol_table::symbol_record *cr; + symbol_table::symbol_record *pr; + } mc; }; std::string orig_text; };