parser.h

Go to the documentation of this file.
00001 /*  
00002  *      Parser.h - a compiler for the 3DS MAX MAXScript scripting language
00003  *
00004  *          Copyright (c) John Wainwright 1996
00005  *
00006  */
00007 
00008 #pragma once
00009 
00010 #include "..\kernel\value.h"
00011 #include "..\..\imacroscript.h"
00012 
00013 class MSPluginClass;
00014 class CodeBlock;
00015 class MouseTool;
00016 class RCMenu;
00017 class IVisualMSForm;
00018 class MSCustAttribDef;
00019 class HashTable;
00020 class RolloutControl;
00021 class Array;
00022 
00023 #define MAX_TOKEN_SIZE  256
00024 #define UNDEFINED_MACRO -1
00025 
00026 extern ScripterExport HashTable* globals;
00027 
00028 /* tokens ... */
00029 
00030 enum lex_token
00031 {
00032     t_local, t_global, t_fn, t_mapped,
00033     t_if, t_then, t_else, t_do, t_collect, t_while, t_case, 
00034     t_open_paren, t_close_paren, t_plus, t_times, t_minus, t_div, t_power, t_end,
00035     t_pluseq, t_minuseq, t_timeseq, t_diveq,
00036     t_and, t_or, t_not,
00037     t_number, t_string, t_assign, t_semicolon, t_bad,
00038     t_badNum, t_eol, t_comma, t_open_bracket, t_close_bracket, t_colon,
00039     t_quote, t_doubleQuote, t_ampersand, t_name, t_dot, t_name_literal,
00040     t_openCurly, t_closeCurly, t_hash, t_eq, t_ne, t_lt, t_gt,
00041     t_ge, t_le, t_for, t_in, t_from, t_to, t_by, t_of, t_where,
00042     t_as, t_parameter_keyword, t_path_name,
00043     t_query, t_slash, t_ellipsis, t_level_name, t_wild_card_name, 
00044     t_dot_dot, t_end_of_path,
00045     t_with, t_animate, t_coordsys, t_set, t_undo,
00046     t_about, t_at, t_on, t_off,t_private,t_public,
00047     t_max, t_nullary_call, t_utility, t_rollout,
00048     t_return, t_exit, t_when, t_continue,
00049     t_struct, t_try, t_catch, t_throw, t_eos,
00050     t_plugin, t_tool, t_persistent, t_parameters, t_rcmenu, 
00051     t_macroScript, t_dropScript, t_attributes,
00052     t_tilde, t_resourceID,
00053 
00054     t_missing  // always last
00055 };
00056 
00057 typedef RolloutControl* (*create_fn)(Value* name, Value* caption, Value** keyparms, int keyparm_count);
00058 struct rollout_control
00059 {
00060     Value*  name;
00061     create_fn creator;
00062 };
00063 extern ScripterExport void install_rollout_control(Value* name, create_fn creator);
00064 
00065 class Parser : public Value             
00066 {
00067     struct ParserSourceData
00068     {
00069         int         tok_start;      // store stream seek pos of token start 
00070         int         last_tok_end;   // store stream seek pos of end of last token 
00071         int         tok_start_line;     // store stream line number of token start 
00072         int         last_tok_end_line;  // store stream line number of end of last token 
00073         int         prev_last_tok_end;  // store stream seek pos of end of previous token 
00074         int         prev_last_tok_end_line; // store stream line number of end of previous token 
00075         int         next_last_tok_end;  // store stream seek pos of end of next token 
00076         int         next_last_tok_end_line; // store stream line number of end of next token 
00077         int         ungetch_count; // store num char ungets back to source stream
00078         int         eol_whitespace_start; // store position of start of whitespace at end of line
00079         int         eol_whitespace_end; // store position of end of whitespace at end of line
00080         bool        at_EOL; // store whether at end of line
00081         bool        spaced; // store whether detected space at end of last token
00082 
00083         bool        force_EOL_at_EOS; // whether to insert a EOL when reach EOS. True when doing an 'include', false when doing a resource.
00084 
00085         ParserSourceData(bool force_EOL_at_EOS) : force_EOL_at_EOS(force_EOL_at_EOS) {}
00086         void pushData(Parser& from_parser); // sets all members except force_EOL_at_EOS;
00087         void popData(Parser& to_parser);
00088     };
00089 public:
00090     ScripterExport         Parser();
00091     ScripterExport         Parser(CharStream* errout);
00092     ScripterExport         Parser(HashTable* scope);
00093     ScripterExport         Parser(CharStream* errout, HashTable* scope);
00094                     void   init();
00095     ScripterExport  Value* compile(CharStream* stream);
00096     ScripterExport  Value* compile_factor(CharStream* stream);
00097     ScripterExport  Value* compile_all(CharStream* stream);
00098     static          void   setup();
00099 
00100     static Tab<rollout_control> rollout_controls;
00101     static MCHAR *token_names[];
00102 
00103     void        collect() { delete this; }
00104     void        gc_trace();
00105 
00106     CharStream* source;         // input stream                     
00107     lex_token   token;          // parser's current lexical token   
00108     Value*      token_value;    //          and value
00109 
00110     bool        at_EOL;         // positioned at \r         
00111     bool        back_tracked;   // we back-tracked                  
00112     bool        EOL_at_back_track; // remember EOL state at back_track 
00113     bool        quoted_level_name; // if path level name was quote  
00114     bool        spaced;         // if space after token             
00115     bool        space_before;   // if '-' had a space before        
00116     bool        space_after;    // if '-' had a space after         
00117     bool        throws_ok;      // indicates if empty throws are OK (only in catches) 
00118     bool        in_macroscript; // compiling macroscript, disallow macroscript nesting 
00119     bool        no_free_refs;   // if on, disallow free refs
00120     bool        no_stack_refs;  // if on, disallow free and local refs
00121     bool        dotted_names_ok; // allows '.' as part of a name (for event handler name parsing)       
00122     bool        ignore_string_escapes; // ignores '\' escapes in string literals        
00123     bool        mzp_names;      // used by .mzp parser, allows . \ $ * in names 
00124 
00125     HashTable*  current_scope;  // current lexical scope hashtable  
00126     int         parm_count;     // current function def params      
00127     int         keyparm_count;  //    "        "     " keyword parms 
00128     int         local_count;    //    "        "     "  locals      
00129     int         frame_index;    // running fn frame index for locals,args 
00130     int         frame_level;    // running frame level              
00131     int         expr_level;     // running nested expression level  
00132     CharStream* stdout_stream;  // message & debug output stream (usually listener's window) 
00133     Value*      lookahead_factor; // store for factor lookahead    
00134     MCHAR       line_buf[256];  // current line capture for error printing 
00135     MCHAR*      line_buf_p;     //   "       "    "     pointer    
00136     CharStream* source_capture; // non-null, capture source to this stream 
00137     int         ungetch_count;  
00138     Tab<CharStream*> src_stack; // include source stack 
00139     Tab<CharStream*> src_capture_stack; // include source capture stack
00140     Tab<ParserSourceData> src_parser_data_stack;  // include source position data stack 
00141     Tab<int> src_stack_encryption_keys; // include source stack encryption keys         
00142 
00143     int         tok_start;      // store stream seek pos of token start 
00144     int         last_tok_end;   // store stream seek pos of end of last token 
00145 
00146     int         tok_start_line;     // store stream line number of token start 
00147     int         last_tok_end_line;  // store stream line number of end of last token 
00148 
00149     // following used for backtracking
00150     int         prev_last_tok_end;  // store stream seek pos of end of previous token 
00151     int         prev_last_tok_end_line; // store stream line number of end of previous token 
00152     int         next_last_tok_end;  // store stream seek pos of end of next token 
00153     int         next_last_tok_end_line; // store stream line number of end of next token 
00154 
00155     CodeBlock*  code_block;     // top-level code block if any
00156     int         code_block_level; // expr level for code block, used to provide context for 'on handler' parsing
00157     int         current_y, bottom_y, group_num; // used by VMS form editor construction code
00158     int         eol_whitespace_start; // offset to beginning of whitespace around an end-of-line
00159     int         eol_whitespace_end; // offset to ending of whitespace around an end-of-line
00160 
00161     Value*      single_expr(Value* stream);
00162     Value*      single_factor(Value* stream);
00163     Value*      compound_expr(Value* stream);
00164     Value*      compile_macro_script(Value* stream, MacroID id);
00165     bool        parse_rollout_for_edit(CharStream* source_stream, IVisualMSForm* form, Value* filename=NULL);
00166     Value*      compile_attributes(MSCustAttribDef* cad, CharStream* stream, Class_ID* attribID = NULL);
00167 
00168 /* lexical analysis methods */
00169     bool        token_must_be(lex_token wanted_token);
00170     bool        next_token_must_be(lex_token wanted_token);
00171     bool        next_token_must_be_name(Value* wanted_name);
00172     void        back_track(void);
00173     void        back_track_factor(Value* fac);
00174     bool        white_space(MCHAR& c);
00175     void        check_for_EOL(MCHAR c);
00176     void        flush_EO_expr(void);
00177     void        reset();
00178     MCHAR       get_char();
00179     void        unget_char(MCHAR c);
00180     void        flush_to_eobuf();
00181     Value*      get_string(MCHAR delim);
00182     Value*      get_path_name();
00183     Value*      get_name_thunk(Value* name, BOOL make_new);
00184     Value*      get_name_thunk(Value* name, BOOL make_new, BOOL forceGlobal);
00185     lex_token   get_punct(MCHAR c);
00186     lex_token   get_token(void);
00187     lex_token   get_path_token(void);
00188     int         get_max_command(Value*& code);
00189     Value*      add_event_handler(HashTable* handlers, BOOL item_based = TRUE, IVisualMSForm* form = NULL);
00190     Value*      add_event_handler(HashTable* handlers, Value* owner, BOOL item_based = TRUE, IVisualMSForm* form = NULL);
00191     void        add_tool_local(MCHAR* var, MouseTool* tool, int& local_count, Value**& local_inits);
00192     void        add_plugin_local(MCHAR* var, MSPluginClass* plugin, int& local_count, Value**& local_inits, BOOL constant = FALSE);
00193     Value**     add_rollout_control(Value** controls, int control_index, Rollout* rollout, IVisualMSForm* form = NULL);
00194     Value**     add_rcmenu_item(Value** items, int& item_count, RCMenu* menu, BOOL subMenu = FALSE);
00195     void        open_include_file(MCHAR c);
00196     void        check_for_const_lvalue(Value*& lval);
00197     Value*      optimize_return(Value* expr);
00198     static bool should_source_position_wrap(Value* code);
00199     Value*      source_position_wrap(Value* code);
00200     Value*      source_position_wrap(Value* code, unsigned int last_token_end,  unsigned int last_token_end_line);
00201     void        insert_resource(Value* resourceID, CharStream* resourceSource);
00202 
00203 /* recursive descent parse methods */
00204 
00205     Value*      expr_seq(lex_token delimiter);
00206     Value*      vector_literal();
00207     Value*      index_or_vector();
00208     Value*      hash_literals();
00209     Value*      array_literal();
00210     Value*      bit_array_literal();
00211     Value*      factor();
00212 //  Value*      property_access();
00213 //  Value*      array_index();
00214     Value*      property_index_array();
00215     Value*      coercion();
00216     Value*      deref_expr();
00217     Value*      function_call();
00218     Value*      power_expr();
00219     Value*      uminus_expr();
00220     Value*      term();
00221     Value*      plus_expr();
00222     Value*      compare_expr();
00223     Value*      not_expr();
00224     Value*      and_expr();
00225     Value*      simple_expr();
00226     Value*      variable_declaration();
00227     Value*      context_expr();
00228     Value*      change_handler();
00229     Value*      function(MCHAR* name, short flags = 0);
00230     Value*      function_def();
00231     Value*      mapped_fn_def();
00232     Value*      max_command();
00233     Value*      handler_def();
00234     Value*      struct_body(Value* name);
00235     Value*      struct_def();
00236     Value*      try_catch();
00237     Value*      tool_body(Value* name);
00238     Value*      tool_def();
00239     Value*      rcmenu_body(Value* name);
00240     Value*      rcmenu_def();
00241     void        plugin_paramblock(MSPluginClass* plugin, Array* pblock_defs, HashTable* handlers, int base_refno);
00242     Value*      plugin_def();
00243     Value*      attributes_body(MSCustAttribDef* cad, Array* remap_param_names);
00244     Value*      attributes_def(MSCustAttribDef* cad = NULL, Class_ID* attribID = NULL);
00245     Value*      macro_script(MacroID mid = UNDEFINED_MACRO);
00246     Value*      rollout_body(Value* name, lex_token type = t_rollout, IVisualMSForm* form = NULL);
00247     Value*      utility_def();
00248     Value*      rollout_def();
00249     Value*      exit_expr();
00250     Value*      continue_expr();
00251     Value*      return_expr();
00252     Value*      for_expr();
00253     Value*      do_expr();
00254     Value*      while_expr();
00255     Value*      case_expr();
00256     Value*      if_expr();
00257     Value*      assign_expr();
00258     Value*      expr();
00259     Value*      top_level_expr();           
00260     Value*      function(MCHAR* name, Value* owner, short flags = 0);
00261 
00262 private:
00263     bool        lastCharWasEscape; // used so multiple escapes in a row throw only a single SignalException
00264 
00265 };
00266 
00267 struct property_accessors
00268 {
00269     MCHAR*      name;
00270     getter_vf   getter;
00271     setter_vf   setter;
00272 };
00273 
00274 extern property_accessors* get_property_accessors(Value* prop);
00275 extern MCHAR* command_name_from_code(int com);
00276 
00277 #define token_name(tok) token_names[(int)tok]
00278