cfad47cfa3/t3compiler/tads3/tcprs.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/tcprs.h,v 1.5 1999/07/11 00:46:58 MJRoberts Exp $ */
2
3
/* 
4
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
5
 *   
6
 *   Please see the accompanying license file, LICENSE.TXT, for information
7
 *   on using and copying this software.  
8
 */
9
/*
10
Name
11
  tcprs.h - TADS 3 Compiler - parser
12
Function
13
  
14
Notes
15
  
16
Modified
17
  04/29/99 MJRoberts  - Creation
18
*/
19
20
#ifndef TCPRS_H
21
#define TCPRS_H
22
23
#include <assert.h>
24
25
#include "vmtype.h"
26
#include "t3std.h"
27
#include "tcglob.h"
28
#include "tctok.h"
29
#include "tctargty.h"
30
#include "tcprstyp.h"
31
32
33
/* ------------------------------------------------------------------------ */
34
/*
35
 *   Object ID type 
36
 */
37
typedef ulong tc_obj_id;
38
39
/*
40
 *   Property ID type 
41
 */
42
typedef uint tc_prop_id;
43
44
45
/* ------------------------------------------------------------------------ */
46
/*
47
 *   scope data structure 
48
 */
49
struct tcprs_scope_t
50
{
51
    /* local symbol table */
52
    class CTcPrsSymtab *local_symtab;
53
54
    /* enclosing scope's local symbol table */
55
    class CTcPrsSymtab *enclosing_symtab;
56
57
    /* number of locals allocated in scope */
58
    int local_cnt;
59
};
60
61
/* ------------------------------------------------------------------------ */
62
/*
63
 *   Code body parsing types.  Each type of code body is essentially the
64
 *   same with minor variations, so we use a common code body parser that
65
 *   checks the parsing type to apply the variations.  
66
 */
67
enum tcprs_codebodytype
68
{
69
    /* a standard function or method code body */
70
    TCPRS_CB_NORMAL,
71
72
    /* anonymous function */
73
    TCPRS_CB_ANON_FN,
74
75
    /* short-form anonymous function */
76
    TCPRS_CB_SHORT_ANON_FN
77
};
78
79
80
/* ------------------------------------------------------------------------ */
81
/*
82
 *   the saved method context is always at index 1 in local variable context
83
 *   arrays, when we're using local variable context arrays 
84
 */
85
#define TCPRS_LOCAL_CTX_METHODCTX  1
86
87
88
/* ------------------------------------------------------------------------ */
89
/*
90
 *   Parser 
91
 */
92
class CTcParser
93
{
94
public:
95
    CTcParser();
96
    ~CTcParser();
97
98
    /* initialize - call this after the code generator is set up */
99
    void init();
100
101
    /*
102
     *   Set the module information.  This tells us the module's name (as
103
     *   it's given in the makefile (.t3m) or library (.tl) file) and its
104
     *   sequence number (an ordinal giving its position in the list of
105
     *   modules making up the overall program build).  We use this
106
     *   information in generating the sourceTextGroup object.  
107
     */
108
    void set_module_info(const char *name, int seqno);
109
110
    /*
111
     *   Write an exported symbol file.  An exported symbol file
112
     *   facilitates separate compilation by providing a listing of the
113
     *   symbols defined in another module.  If module A depends on the
114
     *   symbols from module B, the user can first create an exported
115
     *   symbol file for module B, then can compile module A in the
116
     *   presence of B's symbol file, without actually loading B, and
117
     *   without manually entering a set of external definitions in module
118
     *   A's source code. 
119
     */
120
    void write_symbol_file(class CVmFile *fp, class CTcMake *make_obj);
121
122
    /*
123
     *   Seek to the start of the build configuration information in a symbol
124
     *   file.  The return value is the number of bytes stored in the build
125
     *   configuration block; on return, the file object will have its seek
126
     *   offset set to the first byte of the build configuration data.
127
     *   Returns zero if the symbol file is invalid or does not contain any
128
     *   configuration data.  
129
     */
130
    static ulong seek_sym_file_build_config_info(class CVmFile *fp);
131
132
    /* 
133
     *   Write the global table to an object file. 
134
     */
135
    void write_to_object_file(class CVmFile *fp);
136
137
    /*
138
     *   Read an object file and load it into the global symbol table.  We
139
     *   will fill in the object and property ID translation tables
140
     *   provided with the translated values for the object and property
141
     *   symbols that we find in the object file.
142
     *   
143
     *   Returns zero on success; logs error messages and returns non-zero
144
     *   on error.  Note that a non-zero value should be returned only
145
     *   when the file appears to be corrupted or an I/O error occurs;
146
     *   errors involving conflicting symbols, or other problems that do
147
     *   not prevent us from continuing to read the file in an orderly
148
     *   fashion, should not return failure but should simply log the
149
     *   error and continue; this way, we can detect any additional symbol
150
     *   conflicts or other errors.  This routine should return failure
151
     *   only when it is not possible to continue reading the file.  
152
     */
153
    int load_object_file(class CVmFile *fp,
154
                         const textchar_t *fname,
155
                         tctarg_obj_id_t *obj_xlat,
156
                         tctarg_prop_id_t *prop_xlat,
157
                         ulong *enum_xlat);
158
159
    /*
160
     *   Apply internal object/property ID fixups.  This traverses the
161
     *   symbol table and calls each symbol's apply_internal_fixups()
162
     *   method.  This can be called once after loading all object files.  
163
     */
164
    void apply_internal_fixups();
165
    
166
    /*
167
     *   Read an exported symbol file.  Reads the file and loads the
168
     *   global symbol table with the symbols in the file, with each
169
     *   symbol marked as external.
170
     *   
171
     *   This can be used for separate compilation.  If module A depends
172
     *   on symbols in module B, first create a symbol file for module B,
173
     *   then module A can be compiled simply be pre-loading B's symbol
174
     *   file.  Any symbol files that a module depends upon must be loaded
175
     *   before the module is compiled - symbol file loading must precede
176
     *   parsing.
177
     *   
178
     *   If any errors occur, we'll log the errors and return non-zero.
179
     *   We'll return zero on success.  
180
     */
181
    int read_symbol_file(class CVmFile *fp);
182
183
    /* get the global symbol table */
184
    class CTcPrsSymtab *get_global_symtab() const { return global_symtab_; }
185
186
    /* get the current local symbol table */
187
    class CTcPrsSymtab *get_local_symtab() const { return local_symtab_; }
188
189
    /* get the 'goto' symbol table */
190
    class CTcPrsSymtab *get_goto_symtab() const { return goto_symtab_; }
191
192
    /* set the current pragma C mode */
193
    void set_pragma_c(int mode);
194
195
    /* turn preprocess expression mode on or off */
196
    void set_pp_expr_mode(int f) { pp_expr_mode_ = f; }
197
198
    /* get the current preprocess expression mode flag */
199
    int get_pp_expr_mode() const { return pp_expr_mode_; }
200
201
    /* set/get the sourceTextGroup mode */
202
    void set_source_text_group_mode(int f);
203
    int get_source_text_group_mode() const { return src_group_mode_; }
204
205
    /* get/set the syntax-only mode flag */
206
    int get_syntax_only() const { return syntax_only_; }
207
    void set_syntax_only(int f) { syntax_only_ = f; }
208
209
    /* 
210
     *   Get the constructor and finalize property ID's - all constructors
211
     *   and finalizers have these property ID's respectively 
212
     */
213
    tc_prop_id get_constructor_prop() const { return constructor_prop_; }
214
    tc_prop_id get_finalize_prop() const { return finalize_prop_; }
215
216
    /* get the constructor property symbol */
217
    class CTcSymProp *get_constructor_sym() const { return constructor_sym_; }
218
219
    /* get the object-call property */
220
    tc_prop_id get_objcall_prop() const { return objcall_prop_; }
221
222
    /*
223
     *   Check for unresolved external symbols.  Scans the global symbol
224
     *   table and logs an error for each unresolved external.  Returns
225
     *   true if any unresolved externals exist, false if not.  
226
     */
227
    int check_unresolved_externs();
228
229
    /* 
230
     *   build the dictionaries - scans the global symbol table, and
231
     *   inserts each object symbol's dictionary words into its
232
     *   corresponding dictionary 
233
     */
234
    void build_dictionaries();
235
236
    /* build the grammar productions */
237
    void build_grammar_productions();
238
239
    /*
240
     *   Top-level parser.  Parse functions, objects, and other top-level
241
     *   definitions and declarations. 
242
     */
243
    class CTPNStmProg *parse_top();
244
245
    /* 
246
     *   Parse a required semicolon.  If the semicolon is present, we'll
247
     *   simply skip it.  If it's missing, we'll log an error and try to
248
     *   resynchronize.  If we find something that looks like it should go
249
     *   at the end of an expression, we'll try to skip up to the next
250
     *   semicolon; otherwise, we'll simply stay put.
251
     *   
252
     *   Returns zero if the caller should proceed, non-zero if we're at
253
     *   end of file, in which case there's nothing more for the caller to
254
     *   parse.  
255
     */
256
    static int parse_req_sem();
257
258
    /* 
259
     *   Skip to the next semicolon, ignoring any tokens up to that point.
260
     *   This can be used when the caller encounters an error that makes
261
     *   it impossible to process the current statement further, and wants
262
     *   to find the next semicolon in the hope that it will be a good
263
     *   place to start again with the next statement.
264
     *   
265
     *   Returns zero if the caller should proceed, non-zero if we reach
266
     *   the end of the file.  
267
     */
268
    static int skip_to_sem();
269
270
    /* 
271
     *   Parse an expression.  This parses a top-level "comma" expression. 
272
     */
273
    class CTcPrsNode *parse_expr();
274
275
    /*
276
     *   Parse a condition expression.  This parses a top-level "comma"
277
     *   expression, but displays a warning if the outermost operator in
278
     *   the expression is an assignment, because such expressions are
279
     *   very frequently meant as comparisons, but the '=' operator was
280
     *   inadvertantly used instead of '=='. 
281
     */
282
    class CTcPrsNode *parse_cond_expr();
283
284
    /* 
285
     *   Parse a value expression or a double-quoted string expression
286
     *   (including a double-quoted string with embedded expressions).  If
287
     *   allow_comma_expr is true, we'll parse a comma expression;
288
     *   otherwise, we'll parse an assignment expression.  (A comma
289
     *   expression is broader than an assignment expression, since the
290
     *   comma separates assignment expressions.)  
291
     */
292
    class CTcPrsNode *parse_expr_or_dstr(int allow_comma_expr);
293
294
    /* 
295
     *   Parse an assignment expression - this is the next precedence
296
     *   level down from comma expressions.  In certain contexts, a
297
     *   top-level comma expression is not allowed because a comma has a
298
     *   separate meaning (in the initializer clause of a 'for' statement,
299
     *   for example, or in a list element). 
300
     */
301
    class CTcPrsNode *parse_asi_expr();
302
303
    /* parse an 'enum' top-level statement */
304
    void parse_enum(int *err);
305
306
    /* parse a 'dictionary' top-level statement */
307
    class CTPNStmTop *parse_dict(int *err);
308
309
    /* parse a 'grammar' top-level statement */
310
    class CTPNStmTop *parse_grammar(int *err, int replace, int modify);
311
312
    /* parse and flatten a set of grammar rules */
313
    class CTcPrsGramNode *flatten_gram_rule(int *err);
314
315
    /* parse a 'grammar' OR node */
316
    class CTcPrsGramNode *parse_gram_or(int *err, int level);
317
318
    /* parse a 'grammar' CAT node */
319
    class CTcPrsGramNode *parse_gram_cat(int *err, int level);
320
321
    /* parse a 'grammar' qualifier int value */
322
    int parse_gram_qual_int(int *err, const char *qual_name, int *stm_end);
323
324
    /* skip to the end of a mal-formed grammar qualifier */
325
    void parse_gram_qual_skip(int *err, int *stm_end);
326
327
    /* 
328
     *   Parse a 'function' top-level statement.  If 'is_extern' is true,
329
     *   the function is being defined externally, so it should have no
330
     *   code body defined here (just the prototype).  If 'replace' is
331
     *   true, we're replacing an existing function.
332
     *   
333
     *   If 'func_kw_present' is true, the 'function' keyword is present
334
     *   and must be skipped; otherwise, the function definition elides
335
     *   the 'function' keyword and starts directly with the function name
336
     *   symbol.  
337
     */
338
    class CTPNStmTop *parse_function(int *err, int is_extern,
339
                                     int replace, int modify,
340
                                     int func_kw_present);
341
342
    /* parse an 'intrinsic' top-level statement */
343
    class CTPNStmTop *parse_intrinsic(int *err);
344
345
    /* parse an 'intrinsic class' top-level statement */
346
    class CTPNStmTop *parse_intrinsic_class(int *err);
347
348
    /* parse an 'extern' top-level statement */
349
    void parse_extern(int *err);
350
351
    /* 
352
     *   parse an object or function defintion (this is called when the
353
     *   first thing in a statement is a symbol; we must check what
354
     *   follows to determine what type of definition it is) 
355
     */
356
    class CTPNStmTop *parse_object_or_func(int *err, int replace,
357
                                           int suppress_error,
358
                                           int *suppress_next_error);
359
360
    /* parse a template definition statement */
361
    class CTPNStmTop *parse_template_def(int *err,
362
                                         const class CTcToken *class_tok);
363
364
    /* add a template definition */
365
    void add_template_def(class CTcSymObj *class_sym,
366
                          class CTcObjTemplateItem *item_head,
367
                          size_t item_cnt);
368
369
    /* add inherited template definitions */
370
    void add_inherited_templates(class CTcSymObj *sc_sym,
371
                                 class CTcObjTemplateItem *item_head,
372
                                 size_t item_cnt);
373
374
    /* 
375
     *   expand the 'inherited' keyword in a template for the given
376
     *   superclass template and add the result to the template list for the
377
     *   class 
378
     */
379
    void expand_and_add_inherited_template(class CTcSymObj *sc_sym,
380
                                           class CTcObjTemplateItem *items,
381
                                           class CTcObjTemplate *sc_tpl);
382
383
    /* 
384
     *   build a list of superclass templates, for expanding an 'inherited'
385
     *   token in a template definition 
386
     */
387
    void build_super_template_list(struct inh_tpl_entry **list_head,
388
                                   struct inh_tpl_entry **list_tail,
389
                                   class CTcSymObj *sc_sym);
390
391
    /* parse an 'object' statement */
392
    class CTPNStmTop *parse_object_stm(int *err, int is_transient);
393
394
    /* 
395
     *   parse an object definition that starts with a '+' string; this
396
     *   also parses '+ property' statements 
397
     */
398
    class CTPNStmTop *parse_plus_object(int *err);
399
400
    /* 
401
     *   Parse an object definition.  If 'replace' is true, this
402
     *   definition is to replace a previous definition of the same
403
     *   object; if 'modify' is true, this definition is to modify a
404
     *   previous definition.  If 'is_class' is true, the definition is
405
     *   for a class, otherwise it's for a static instance.
406
     *   
407
     *   If the definition uses the '+' notation to set the location,
408
     *   plus_cnt gives the number of '+' signs preceding the object
409
     *   definition.  
410
     */
411
    class CTPNStmTop *parse_object(int *err, int replace, int modify,
412
                                   int is_class, int plus_cnt,
413
                                   int is_transient);
414
415
    /* find or define an object symbol */
416
    CTcSymObj *find_or_def_obj(const char *tok_txt, size_t tok_len,
417
                               int replace, int modify, int *is_class,
418
                               class CTcSymObj **mod_orig_sym,
419
                               class CTcSymMetaclass **meta_sym,
420
                               int *is_transient);
421
422
    /* parse an anonymous object */
423
    class CTPNStmObject *parse_anon_object(int *err, int plus_cnt,
424
                                           int is_nested,
425
                                           struct tcprs_term_info *term_info,
426
                                           int is_transient);
427
428
    /* 
429
     *   Parse an object body.  We start parsing from the colon that
430
     *   introduces the class list, and parse the class list and the
431
     *   property list for the object.
432
     *   
433
     *   If 'is_anon' is true, this is an anonymous object.  'obj_sym'
434
     *   should be null in this case.
435
     *   
436
     *   If 'is_nested' is true, this is a nested object defined in-line in
437
     *   an object's property list.  Note that is_nested implies is_anon,
438
     *   since nested objects are always anonymous.
439
     *   
440
     *   If this is a 'modify' definition, 'mod_orig_tok' should be set up
441
     *   with the synthesized symbol for the modified base object;
442
     *   otherwise, 'mod_orig_tok' should be null.
443
     *   
444
     *   If 'meta_sym' is non-null, we're modifying an intrinsic class.
445
     *   This imposes certain restrictions; in particular, we cannot modify
446
     *   a method defined in the native interface to the class.  
447
     */
448
    class CTPNStmObject *parse_object_body(int *err, class CTcSymObj *obj_sym,
449
                                           int is_class, int is_anon,
450
                                           int is_grammar,
451
                                           int is_nested, int modify,
452
                                           class CTcSymObj *mod_orig_sym,
453
                                           int plus_cnt,
454
                                           class CTcSymMetaclass *meta_sym,
455
                                           struct tcprs_term_info *term_info,
456
                                           int is_transient);
457
458
    /* parse an object template instance in an object body */
459
    void parse_obj_template(int *err, class CTPNStmObject *obj_stm);
460
461
    /* search a superclass list for a template match */
462
    const class CTcObjTemplate
463
        *find_class_template(const class CTPNSuperclass *first_sc,
464
                             class CTcObjTemplateInst *src,
465
                             size_t src_cnt, const CTPNSuperclass **def_sc,
466
                             int *undescribed_class);
467
468
    /* find a match for a given template in the given list */
469
    const class CTcObjTemplate
470
        *find_template_match(const class CTcObjTemplate *first_tpl,
471
                             class CTcObjTemplateInst *src,
472
                             size_t src_cnt);
473
474
    /*
475
     *   Match a template to a given actual template parameter list.  Returns
476
     *   true if we match, false if not.  We'll fill in the actual list with
477
     *   the property symbols that we matched; these values are only
478
     *   meaningful if we return true to indicate a match.  
479
     */
480
    int match_template(const class CTcObjTemplateItem *tpl_head,
481
                       class CTcObjTemplateInst *src, size_t src_cnt);
482
483
    /* parse property definition within an object */
484
    void parse_obj_prop(int *err, class CTPNStmObject *obj_stm, int replace,
485
                        class CTcSymMetaclass *meta_sym,
486
                        struct tcprs_term_info *term_info,
487
                        struct propset_def *propset_stack, int propset_depth,
488
                        int enclosing_obj_is_nested);
489
490
    /* parse a class definition */
491
    class CTPNStmTop *parse_class(int *err);
492
493
    /* parse a 'modify' definition */
494
    class CTPNStmTop *parse_modify(int *err);
495
496
    /* parse a 'replace' definition */
497
    class CTPNStmTop *parse_replace(int *err);
498
499
    /* parse a 'property' statement */
500
    void parse_property(int *err);
501
502
    /* parse an 'export' statement */
503
    void parse_export(int *err);
504
505
    /* add an export for the given symbol; returns the new export record */
506
    class CTcPrsExport *add_export(const char *sym, size_t sym_len);
507
508
    /* add an export record to our list */
509
    void add_export_to_list(class CTcPrsExport *exp);
510
511
    /* get the head of the export list */
512
    class CTcPrsExport *get_exp_head() const { return exp_head_; }
513
514
    /*
515
     *   Parse a function or method body, starting with the formal parameter
516
     *   list.  If 'eq_before_brace' is set, we expect an '=' before the
517
     *   opening brace of the code body, and we allow the expression syntax,
518
     *   where an expression enclosed in parentheses can be used.
519
     *   'self_valid' indicates whether or not 'self' is valid in the context
520
     *   of the code being compiled; for an object method, 'self' is usually
521
     *   valid, while for a stand-alone function it isn't.  
522
     */
523
    class CTPNCodeBody *parse_code_body(int eq_before_brace, int is_obj_prop,
524
                                        int self_valid,
525
                                        int *p_argc, int *p_varargs,
526
                                        int *p_varargs_list,
527
                                        class CTcSymLocal **
528
                                            p_varargs_list_local,
529
                                        int *has_retval, int *err,
530
                                        class CTcPrsSymtab *local_symtab,
531
                                        tcprs_codebodytype cb_type,
532
                                        struct propset_def *propset_stack,
533
                                        int propset_depth,
534
                                        struct CTcCodeBodyRef *enclosing,
535
                                        class CTcFormalTypeList **type_list);
536
537
    /* parse a nested code body (such as an anonymous function) */
538
    class CTPNCodeBody *parse_nested_code_body(
539
        int eq_before_brace,
540
        int self_valid,
541
        int *p_argc, int *p_varargs,
542
        int *p_varargs_list,
543
        class CTcSymLocal **p_varargs_list_local,
544
        int *has_retval, int *err,
545
        class CTcPrsSymtab *local_symtab,
546
        tcprs_codebodytype cb_type);
547
548
    /* parse a formal parameter list */
549
    void parse_formal_list(int count_only, int opt_allowed,
550
                           int *argc, int *opt_argc, int *varargs,
551
                           int *varargs_list,
552
                           class CTcSymLocal **varargs_list_local,
553
                           int *err, int base_formal_num,
554
                           int for_short_anon_func,
555
                           class CTcFormalTypeList **type_list);
556
557
    /*
558
     *   Parse a compound statement.  The caller must skip the opening
559
     *   '{'; on return, we'll have skipped the closing '}'.
560
     *   enclosing_symtab is the enclosing scope's symbol table, and
561
     *   local_symtab is the symbol table for the new scope within the
562
     *   compound statement; if the caller has not already allocated a new
563
     *   symbol table for the inner scope, it should simply pass the same
564
     *   value for both symbol tables.
565
     *   
566
     *   'enclosing_switch' is the immediately enclosing switch statement,
567
     *   if any.  This is only set when we're parsing the immediate body
568
     *   of a switch statement.  
569
     */
570
    class CTPNStmComp *parse_compound(int *err, int skip_lbrace,
571
                                      class CTPNStmSwitch *enclosing_switch,
572
                                      int use_enclosing_scope);
573
574
    /* parse a local variable definition */
575
    class CTPNStm *parse_local(int *err);
576
577
    /* parse a local initializer */
578
    class CTcPrsNode *parse_local_initializer(class CTcSymLocal *lcl,
579
                                              int *err);
580
581
    /*
582
     *   Parse an individual statement.
583
     *   
584
     *   If 'compound_use_enclosing_scope' is true, then if the statement
585
     *   is a compound statement (i.e., the current token is a left
586
     *   brace), the compound statement will use the current scope rather
587
     *   than creating its own scope.  Normally, a compound statement
588
     *   establishes its own scope, so that local variables can hide
589
     *   locals and parameters defined outside the braces.  In certain
590
     *   cases, however, locals defined within the braces should share the
591
     *   enclosing scope: at the top level of a function or method, for
592
     *   example, the formal parameters and the locals within the function
593
     *   body go in the same scope, so the function body's compound
594
     *   statement doesn't create its own scope.  
595
     */
596
    class CTPNStm *parse_stm(int *err, class CTPNStmSwitch *enclosing_switch,
597
                             int compound_use_enclosing_scope);
598
599
    /* parse a 'case' label */
600
    class CTPNStm *parse_case(int *err,
601
                              class CTPNStmSwitch *enclosing_switch);
602
603
    /* parse a 'default' label */
604
    class CTPNStm *parse_default(int *err,
605
                                 class CTPNStmSwitch *enclosing_switch);
606
607
    /* parse an 'if' statement */
608
    class CTPNStm *parse_if(int *err);
609
610
    /* parse a 'return' statement */
611
    class CTPNStm *parse_return(int *err);
612
613
    /* parse a 'for' statement */
614
    class CTPNStm *parse_for(int *err);
615
616
    /* parse a 'foreach' statement */
617
    class CTPNStm *parse_foreach(int *err);
618
619
    /* parse a 'break' statement */
620
    class CTPNStm *parse_break(int *err);
621
622
    /* parse a 'continue' statement */
623
    class CTPNStm *parse_continue(int *err);
624
625
    /* parse a 'while' */
626
    class CTPNStm *parse_while(int *err);
627
    
628
    /* parse a 'do-while' */
629
    class CTPNStm *parse_do_while(int *err);
630
631
    /* parse a 'switch' */
632
    class CTPNStm *parse_switch(int *err);
633
634
    /* parse a 'goto' */
635
    class CTPNStm *parse_goto(int *err);
636
637
    /* parse a 'try' */
638
    class CTPNStm *parse_try(int *err);
639
640
    /* parse a 'throw' */
641
    class CTPNStm *parse_throw(int *err);
642
643
    /*
644
     *   Create a symbol node.  We'll look up the symbol in local scope.
645
     *   If we find the symbol in local scope, we'll return a resolved
646
     *   symbol node for the local scope item.  If the symbol isn't
647
     *   defined in local scope, we'll return an unresolved symbol node,
648
     *   so that the symbol's resolution can be deferred until code
649
     *   generation. 
650
     */
651
    class CTcPrsNode *create_sym_node(const textchar_t *sym, size_t sym_len);
652
653
    /*
654
     *   Get the source file descriptor and line number for the current
655
     *   source line.  We note this at the start of each statement, so
656
     *   that a statement node constructed when we finish parsing the
657
     *   statement can record the location of the start of the statement. 
658
     */
659
    class CTcTokFileDesc *get_cur_desc() const { return cur_desc_; }
660
    long get_cur_linenum() const { return cur_linenum_; }
661
662
    /*
663
     *   Get/set the current enclosing statement.  An enclosing statement
664
     *   is a 'try' or 'label:' container.  At certain times, we need to
665
     *   know the current enclosing statement, or one of its enclosing
666
     *   statements; for example, a 'break' with a label must find the
667
     *   label in the enclosing statement list to know where to jump to
668
     *   after the 'break', and must also know about all of the enclosing
669
     *   'try' blocks our to that point so that it can invoke their
670
     *   'finally' blocks.  
671
     */
672
    class CTPNStmEnclosing *get_enclosing_stm() const
673
        { return enclosing_stm_; }
674
    class CTPNStmEnclosing *set_enclosing_stm(class CTPNStmEnclosing *stm)
675
    {
676
        class CTPNStmEnclosing *old_enclosing;
677
678
        /* remember the current enclosing statement for a moment */
679
        old_enclosing = enclosing_stm_;
680
681
        /* set the new enclosing statement */
682
        enclosing_stm_ = stm;
683
684
        /* 
685
         *   return the previous enclosing statement - this allows the
686
         *   caller to restore the previous enclosing statement upon
687
         *   leaving a nested block, if that's why the caller is setting a
688
         *   new enclosing statement 
689
         */
690
        return old_enclosing;
691
    }
692
693
    /* get the current code body reference object */
694
    struct CTcCodeBodyRef *get_cur_code_body() const
695
        { return cur_code_body_; }
696
697
    /* determine if 'self' is valid in the current context */
698
    int is_self_valid() const { return self_valid_; }
699
700
    /* 
701
     *   get/set the 'self' reference status - this indicates whether or not
702
     *   'self' has been referenced, explicitly via the 'self'
703
     *   pseudo-variable or implicitly (such as via a property reference or
704
     *   method call), in the code body currently being parsed 
705
     */
706
    int self_referenced() const { return self_referenced_; }
707
    void set_self_referenced(int f) { self_referenced_ = f; }
708
709
    /* 
710
     *   get/set the full method context reference status - this indicates
711
     *   whether or not any of the method context variables (self,
712
     *   targetprop, targetobj, definingobj) have been referenced, explicitly
713
     *   or implicitly, in the code body currently being parsed 
714
     */
715
    int full_method_ctx_referenced() const
716
        { return full_method_ctx_referenced_; }
717
    void set_full_method_ctx_referenced(int f)
718
        { full_method_ctx_referenced_ = f; }
719
720
    /* 
721
     *   Get/set the flag indicating whether or not the local context of the
722
     *   outermost code body needs 'self'.  The outer code body needs 'self'
723
     *   in the local context if any lexically nested code body requires
724
     *   access to 'self'.  
725
     */
726
    int local_ctx_needs_self() const { return local_ctx_needs_self_; }
727
    void set_local_ctx_needs_self(int f) { local_ctx_needs_self_ = f; }
728
729
    /* 
730
     *   Get/set the flag indicating whether or not the local context of the
731
     *   outermost code body needs the full method context stored in its
732
     *   local context.  The outer code body needs the full context stored if
733
     *   any lexically nested code body requires access to any of the method
734
     *   context variables besides 'self' (targetprop, targetobj,
735
     *   definingobj).  
736
     */
737
    int local_ctx_needs_full_method_ctx() const
738
        { return local_ctx_needs_full_method_ctx_; }
739
    void set_local_ctx_needs_full_method_ctx(int f)
740
        { local_ctx_needs_full_method_ctx_ = f; }
741
742
    /*
743
     *   Add a code label.  This creates a 'goto' symbol table for the
744
     *   current code body if one doesn't already exist 
745
     */
746
    class CTcSymLabel *add_code_label(const class CTcToken *tok);
747
748
    /*
749
     *   Set the debugger local symbol table.  Returns the previous symbol
750
     *   table so that it can be restored if desired.  
751
     */
752
    class CTcPrsDbgSymtab *set_debug_symtab(class CTcPrsDbgSymtab *tab)
753
    {
754
        class CTcPrsDbgSymtab *old_tab;
755
756
        /* remember the original for later use */
757
        old_tab = debug_symtab_;
758
759
        /* set the new table */
760
        debug_symtab_ = tab;
761
762
        /* return the original */
763
        return old_tab;
764
    }
765
766
    /*
767
     *   given a (1-based) object file symbol index, get the symbol 
768
     */
769
    class CTcSymbol *get_objfile_sym(uint idx)
770
        { return (idx == 0 ? 0 : obj_sym_list_[idx - 1]); }
771
772
    /* 
773
     *   given a 1-based object file symbol index, get an object symbol;
774
     *   if the symbol does not refer to an object, we'll return null 
775
     */
776
    class CTcSymObj *get_objfile_objsym(uint idx);
777
778
    /* 
779
     *   given an object file (1-based) object file dictionary index, get
780
     *   the dictionary entry 
781
     */
782
    class CTcDictEntry *get_obj_dict(uint idx)
783
        { return (idx == 0 ? 0 : obj_dict_list_[idx - 1]); }
784
785
    /* add a dictionary object loaded from the object file */
786
    void add_dict_from_obj_file(class CTcSymObj *sym);
787
788
    /* add a symbol object loaded from the object file */
789
    void add_sym_from_obj_file(uint idx, class CTcSymbol *sym);
790
791
    /*
792
     *   Get the next object file symbol index.  Object file symbol
793
     *   indices are used to relate symbols stored in the object file to
794
     *   the corresponding symbol object in memory when the object file is
795
     *   reloaded.  
796
     */
797
    uint get_next_obj_file_sym_idx()
798
    {
799
        /* return the next index, consuming the index value */
800
        return obj_file_sym_idx_++;
801
    }
802
803
    /*
804
     *   Get the next object file dictionary index.
805
     */
806
    uint get_next_obj_file_dict_idx()
807
    {
808
        /* return the next index, consuming the index value */
809
        return obj_file_dict_idx_++;
810
    }
811
812
    /* 
813
     *   add an anonymous function or other anonymous top-level statement
814
     *   to our list of nested top-level statements
815
     */
816
    void add_nested_stm(class CTPNStmTop *stm);
817
818
    /* add an anonymous object to our list */
819
    void add_anon_obj(class CTcSymObj *obj);
820
821
    /* add a non-symbolic object ID */
822
    void add_nonsym_obj(tctarg_obj_id_t id);
823
824
    /* determine if the current code body has a local context */
825
    int has_local_ctx() const { return has_local_ctx_ != 0; }
826
827
    /* get the local context variable number */
828
    int get_local_ctx_var() const { return local_ctx_var_num_; }
829
830
    /* set up a local context */
831
    void init_local_ctx();
832
833
    /* allocate a context variable property ID */
834
    tctarg_prop_id_t alloc_ctx_var_prop();
835
836
    /* 
837
     *   allocate a context variable index - this assigns an array index
838
     *   for a context variable within the context object that contains
839
     *   the shared locals for its scope 
840
     */
841
    int alloc_ctx_arr_idx();
842
843
    /* allocate a local for use as a local context holder */
844
    int alloc_ctx_holder_var() { return alloc_local(); }
845
846
    /* get the maximum number of locals required in the function */
847
    int get_max_local_cnt() const { return max_local_cnt_; }
848
849
    /* 
850
     *   find a grammar production symbol, adding a new one if needed,
851
     *   returning the grammar production list entry for the object 
852
     */
853
    class CTcGramProdEntry *declare_gramprod(const char *sym, size_t len);
854
855
    /* find a grammar production list entry for a given object */
856
    class CTcGramProdEntry *get_gramprod_entry(class CTcSymObj *sym);
857
858
    /* find a grammar production symbol, adding a new one if needed */
859
    class CTcSymObj *find_or_def_gramprod(const char *txt, size_t len,
860
                                          class CTcGramProdEntry **entryp);
861
862
    /* allocate a new enumerator ID */
863
    ulong new_enum_id() { return next_enum_id_++; }
864
865
    /* get the number of enumerator ID's allocated */
866
    ulong get_enum_count() const { return next_enum_id_; }
867
868
    /* 
869
     *   Look up a property symbol, adding it if not yet defined.  If the
870
     *   symbol is defined as another type, we'll show an error if
871
     *   show_err is true, and return null.  
872
     */
873
    CTcSymProp *look_up_prop(const class CTcToken *tok, int show_err);
874
875
    /* get the '+' property for tracking the location graph */
876
    CTcSymProp *get_plus_prop() const { return plus_prop_; }
877
878
    /*
879
     *   Read a length-prefixed string from a file.  Copies the string into
880
     *   tokenizer space (which is guaranteed valid throughout compilation),
881
     *   and returns a pointer to the tokenizer copy.  If ret_len is null,
882
     *   we'll return a null-terminated string; otherwise, we'll return a
883
     *   non-null-terminated string and set *ret_len to the length of the
884
     *   string.
885
     *   
886
     *   The string must fit in the temporary buffer to be read, but the
887
     *   permanent tokenizer copy is returned rather than the temp buffer.
888
     *   If the string doesn't fit in the temp buffer (with null
889
     *   termination, if null termination is requested), we'll log the given
890
     *   error.  
891
     */
892
    static const char *read_len_prefix_str
893
        (CVmFile *fp, char *tmp_buf, size_t tmp_buf_len, size_t *ret_len,
894
         int err_if_too_long);
895
896
    /*
897
     *   Read a length-prefixed string into the given buffer, null
898
     *   terminating the result.  If the string is too long for the buffer,
899
     *   we'll flag the given error code and return non-zero.  If
900
     *   successful, we'll return zero. 
901
     */
902
    static int read_len_prefix_str(CVmFile *fp, char *buf, size_t buf_len,
903
                                   int err_if_too_long);
904
905
906
    /* get the miscVocab property symbol */
907
    tctarg_prop_id_t get_miscvocab_prop() const { return miscvocab_prop_; }
908
909
private:
910
    /* clear the anonymous function local context information */
911
    void clear_local_ctx();
912
913
    /* 
914
     *   begin a property expression, saving parser state for later
915
     *   restoration with finish_prop_expr 
916
     */
917
    void begin_prop_expr(class CTcPrsPropExprSave *save_info);
918
919
    /* 
920
     *   Finish a property expression, wrapping it in a code body if
921
     *   necessary to allow for an embedded anonymous function.  Returns
922
     *   null if no wrapping is required, in which case the original
923
     *   expression should continue to be used, or the non-null code body
924
     *   wrapper if needed, in which case the original expression should be
925
     *   discarded in favor of the fully wrapped code body.  
926
     */
927
    class CTPNCodeBody *finish_prop_expr(class CTcPrsPropExprSave *save_info,
928
                                         class CTcPrsNode *expr,
929
                                         int is_static,
930
                                         class CTcSymProp *prop_sym);
931
    
932
    /* 
933
     *   callback for symbol table enumeration for writing a symbol export
934
     *   file 
935
     */
936
    static void write_sym_cb(void *ctx, class CTcSymbol *sym);
937
    
938
    /* callback for symbol table enumeration for writing an object file */
939
    static void write_obj_cb(void *ctx, class CTcSymbol *sym);
940
    
941
    /* callback for symbol table enumeration for writing cross references */
942
    static void write_obj_ref_cb(void *ctx, class CTcSymbol *sym);
943
944
    /* callback for symbol table enumeration for named grammar rules */
945
    static void write_obj_gram_cb(void *ctx, class CTcSymbol *sym);
946
947
    /* callback for symbol table enumeration for merging grammar rules */
948
    static void build_grammar_cb(void *ctx, class CTcSymbol *sym);
949
950
951
    /*
952
     *   Enter a scope.  Upon entering, we'll remember the current local
953
     *   variable data; on leaving, we'll restore the enclosing scope.  
954
     */
955
    void enter_scope(struct tcprs_scope_t *info)
956
    {
957
        /* remember the current scope information */
958
        info->local_symtab = local_symtab_;
959
        info->enclosing_symtab = enclosing_local_symtab_;
960
        info->local_cnt = local_cnt_;
961
962
        /* 
963
         *   We haven't yet allocated a symbol table local to the new
964
         *   scope -- we defer this until we actually need to insert a
965
         *   symbol into the new scope.  In order to detect when we need
966
         *   to create our own local symbol table, we keep track of the
967
         *   enclosing symbol table; when the local table is the same as
968
         *   the enclosing table, and we need to insert a symbol, it means
969
         *   that we must create a new table for the current scope.  
970
         */
971
        enclosing_local_symtab_ = local_symtab_;
972
    }
973
974
    /* leave a scope */
975
    void leave_scope(struct tcprs_scope_t *info)
976
    {
977
        /* restore enclosing scope information */
978
        local_symtab_ = info->local_symtab;
979
        enclosing_local_symtab_ = info->enclosing_symtab;
980
981
        /* return to the local count in the enclosing scope */
982
        // $$$ we can't actually do this because variables could
983
        //     be allocated after this scope ends, but need lifetimes
984
        //     that overlap with the enclosed scope; what we actually
985
        //     need to do, if we wanted to optimize things, would be
986
        //     to allow this block of variables to be used in *disjoint*
987
        //     scopes, but not again in enclosing scopes.  We can easily,
988
        //     though suboptimally, handle this by simply not allowing
989
        //     the variables in the enclosed scope to be re-used at all
990
        //     in the current code block.
991
        // local_cnt_ = info->local_cnt;
992
    }
993
994
    /* 
995
     *   Create a local symbol table in the current scope, if necessary.
996
     *   If we've already created a local symbol table for the current
997
     *   scope, this has no effect. 
998
     */
999
    void create_scope_local_symtab();
1000
1001
    /* allocate a new local variable ID */
1002
    int alloc_local()
1003
    {
1004
        /* 
1005
         *   if this exceeds the maximum depth in the block so far, note
1006
         *   the new maximum depth 
1007
         */
1008
        if (local_cnt_ + 1 > max_local_cnt_)
1009
            max_local_cnt_ = local_cnt_ + 1;
1010
1011
        /* return the local number, and increment the counter */
1012
        return local_cnt_++;
1013
    }
1014
1015
    /* find a dictionary symbol, adding a new one if needed */
1016
    class CTcDictEntry *declare_dict(const char *sym, size_t len);
1017
1018
    /* create a new dictionary list entry */
1019
    class CTcDictEntry *create_dict_entry(class CTcSymObj *sym);
1020
1021
    /* find a dictionary list entry for a given object */
1022
    class CTcDictEntry *get_dict_entry(class CTcSymObj *sym);
1023
1024
    /* create a new grammar production list entry */
1025
    class CTcGramProdEntry *create_gramprod_entry(class CTcSymObj *sym);
1026
1027
    /* symbol enumerator - look for unresolved external references */
1028
    static void enum_sym_extref(void *ctx, class CTcSymbol *sym);
1029
1030
    /* symbol enumerator - apply internal fixups */
1031
    static void enum_sym_internal_fixup(void *ctx, class CTcSymbol *sym);
1032
1033
    /* symbol enumerator - build dictionary */
1034
    static void enum_sym_dict(void *ctx, class CTcSymbol *sym);
1035
1036
    /* enumeration callback - context local conversion */
1037
    static void enum_for_ctx_locals(void *ctx, class CTcSymbol *sym);
1038
1039
    /* global symbol table */
1040
    class CTcPrsSymtab *global_symtab_;
1041
1042
    /* the constructor property ID and symbol */
1043
    tc_prop_id constructor_prop_;
1044
    class CTcSymProp *constructor_sym_;
1045
1046
    /* the finalizer property ID */
1047
    tc_prop_id finalize_prop_;
1048
1049
    /* object-call property ID */
1050
    tc_prop_id objcall_prop_;
1051
1052
    /* grammarInfo property symbol */
1053
    class CTcSymProp *graminfo_prop_;
1054
1055
    /* miscVocab property ID */
1056
    tctarg_prop_id_t miscvocab_prop_;
1057
1058
    /* lexicalParent property symbol */
1059
    class CTcSymProp *lexical_parent_sym_;
1060
1061
    /* sourceTextOrder property symbol */
1062
    class CTcSymProp *src_order_sym_;
1063
1064
    /* sourceTextGroup property symbol */
1065
    class CTcSymProp *src_group_sym_;
1066
1067
    /* sourceTextGroupName, sourceTextGroupOrder */
1068
    class CTcSymProp *src_group_mod_sym_;
1069
    class CTcSymProp *src_group_seq_sym_;
1070
    
1071
1072
    /* 
1073
     *   Source text order index.  Each time we encounter an object
1074
     *   definition in the source code, we assign the current index value to
1075
     *   the object's 'sourceTextOrder' property, then we increment the
1076
     *   index.  This provides the game program with information on the order
1077
     *   in which static objects appear in the source code, so that the
1078
     *   program can sort a collection of objects into their source file
1079
     *   order if desired. 
1080
     */
1081
    long src_order_idx_;
1082
1083
    /*
1084
     *   Source group object.  If we're assigning source text group values,
1085
     *   we create an object for each source module to identify the module. 
1086
     */
1087
    tctarg_obj_id_t src_group_id_;
1088
1089
    /* 
1090
     *   flag: in preprocessor constant expression mode; double-quoted
1091
     *   strings should be treated the same as single-quoted strings for
1092
     *   concatenation and comparisons 
1093
     */
1094
    uint pp_expr_mode_ : 1;
1095
1096
    /* 
1097
     *   Is source text mode turned on?  If this is true, we'll generate
1098
     *   sourceTextGroup properties for objects, otherwise we won't. 
1099
     */
1100
    uint src_group_mode_ : 1;
1101
1102
    /*
1103
     *   Flag: syntax-only mode.  We use this mode to analyze the syntax
1104
     *   of the file without building the image; this is used, for
1105
     *   example, to build the exported symbol file for a source file.  In
1106
     *   this mode, we'll suppress certain warnings and avoid doing work
1107
     *   that's not necessary for syntactic analysis; for example, we
1108
     *   won't show "unreachable code" errors.  
1109
     */
1110
    uint syntax_only_ : 1;
1111
1112
    /*
1113
     *   Code block parsing state
1114
     */
1115
    
1116
    /* 
1117
     *   'goto' symbol table for the current code block - there's only one
1118
     *   'goto' scope for an entire code block, so this never changes over
1119
     *   the course of a code block 
1120
     */
1121
    class CTcPrsSymtab *goto_symtab_;
1122
1123
    /* 
1124
     *   Current local symbol table.  Each inner scope that defines its
1125
     *   own local variables has its own local symbol table, nested within
1126
     *   the enclosing scope's.  When leaving an inner scope, this should
1127
     *   always be restored to the local symbol table of the enclosing
1128
     *   scope.  
1129
     */
1130
    class CTcPrsSymtab *local_symtab_;
1131
1132
    /*
1133
     *   Enclosing local symbol table.  If this is the same as
1134
     *   local_symtab_, it means that the current scope has not yet
1135
     *   created its own local symbol table.  We defer this creation until
1136
     *   we find we actually need a local symbol table in a scope, since
1137
     *   most scopes don't define any of their own local variables. 
1138
     */
1139
    class CTcPrsSymtab *enclosing_local_symtab_;
1140
1141
    /*
1142
     *   Current debugger local symbol table.  When we're compiling a
1143
     *   debugger expression, this will provide access to the current
1144
     *   local scope in the debug records. 
1145
     */
1146
    class CTcPrsDbgSymtab *debug_symtab_;
1147
1148
    /* 
1149
     *   Number of local variables allocated so far in current code block
1150
     *   -- this reflects nesting to the current innermost scope, because
1151
     *   variables in inner scope are allocated in the same stack frame as
1152
     *   the enclosing scopes.  When leaving an inner scope, this should
1153
     *   be restored 
1154
     */
1155
    int local_cnt_;
1156
1157
    /* 
1158
     *   maximum local variable depth for the current code block -- this
1159
     *   reflects the maximum depth, including all inner scopes so far 
1160
     */
1161
    int max_local_cnt_;
1162
1163
    /*
1164
     *   Enclosing statement - this is the innermost 'try' or 'label:'
1165
     *   enclosing the current code.
1166
     */
1167
    class CTPNStmEnclosing *enclosing_stm_;
1168
1169
    /* file descriptor and line number at start of current statement */
1170
    class CTcTokFileDesc *cur_desc_;
1171
    long cur_linenum_;
1172
1173
    /* currently active dictionary */
1174
    class CTcDictEntry *dict_cur_;
1175
1176
    /* head and tail of dictionary list */
1177
    class CTcDictEntry *dict_head_;
1178
    class CTcDictEntry *dict_tail_;
1179
1180
    /* head and tail of grammar production entry list */
1181
    class CTcGramProdEntry *gramprod_head_;
1182
    class CTcGramProdEntry *gramprod_tail_;
1183
1184
    /* 
1185
     *   array of symbols loaded from the object file - these are indexed
1186
     *   by the object file symbol index stored in symbol references in
1187
     *   the object file, allowing us to fix up references from one symbol
1188
     *   to another during loading 
1189
     */
1190
    class CTcSymbol **obj_sym_list_;
1191
1192
    /* 
1193
     *   array of dictionary objects for the object file being loaded -
1194
     *   these are indexed by the dictionary index stored in symbol
1195
     *   references in the object file, allowing us to fix up references
1196
     *   from an object to its dictionary 
1197
     */
1198
    class CTcDictEntry **obj_dict_list_;
1199
1200
    /* next available object file dictionary index */
1201
    uint obj_file_dict_idx_;
1202
1203
    /* next available object file symbol index */
1204
    uint obj_file_sym_idx_;
1205
1206
    /* dictionary property list head */
1207
    class CTcDictPropEntry *dict_prop_head_;
1208
1209
    /*
1210
     *   Head and tail of list of nested top-level statements parsed for the
1211
     *   current top-level statement.  This list includes anonymous
1212
     *   functions and nested objects, since these statements must
1213
     *   ultimately be linked into the top-level statement queue, but can't
1214
     *   be linked in while they're being parsed because of their nested
1215
     *   location in the recursive descent.  We'll throw each new nested
1216
     *   top-level statement into this list as we parse them, then add this
1217
     *   list to the top-level statement list when we're done with the
1218
     *   entire program.  
1219
     */
1220
    class CTPNStmTop *nested_stm_head_;
1221
    class CTPNStmTop *nested_stm_tail_;
1222
1223
    /*
1224
     *   Anonymous object list.  This is a list of objects which are
1225
     *   defined without symbol names.  
1226
     */
1227
    class CTcSymObj *anon_obj_head_;
1228
    class CTcSymObj *anon_obj_tail_;
1229
1230
    /* 
1231
     *   Non-symbolic object list.  This is a list of objects that are
1232
     *   defined without symbols at all.
1233
     */
1234
    struct tcprs_nonsym_obj *nonsym_obj_head_;
1235
    struct tcprs_nonsym_obj *nonsym_obj_tail_;
1236
1237
    /*
1238
     *   Object template list - this is the master list of templates for the
1239
     *   root object class.  
1240
     */
1241
    class CTcObjTemplate *template_head_;
1242
    class CTcObjTemplate *template_tail_;
1243
1244
    /*
1245
     *   Object template instance parsing expression array.  Each time we
1246
     *   define a new template, we'll make sure this array is long enough
1247
     *   for the longest defined template.  We use this list when we're
1248
     *   parsing a template instance to keep track of the expressions in
1249
     *   the template instance - we can't know until we have the entire
1250
     *   list which template we're using, so we must keep track of the
1251
     *   entire list until we reach the end of the list. 
1252
     */
1253
    class CTcObjTemplateInst *template_expr_;
1254
    size_t template_expr_max_;
1255
1256
    /* head and tail of exported symbol list */
1257
    class CTcPrsExport *exp_head_;
1258
    class CTcPrsExport *exp_tail_;
1259
1260
    /* 
1261
     *   Flag: current code body has a local variable context object.  If
1262
     *   this is set, we must generate code that sets up the context
1263
     *   object on entry to the code body. 
1264
     */
1265
    unsigned int has_local_ctx_ : 1;
1266
1267
    /* local variable number of the code body's local variable context */
1268
    int local_ctx_var_num_;
1269
1270
    /* array of context variable property values */
1271
    tctarg_prop_id_t *ctx_var_props_;
1272
1273
    /* size of array */
1274
    size_t ctx_var_props_size_;
1275
1276
    /* number of context variable property values in the list */
1277
    size_t ctx_var_props_cnt_;
1278
1279
    /* 
1280
     *   number of context variable property values assigned to the
1281
     *   current code body 
1282
     */
1283
    size_t ctx_var_props_used_;
1284
1285
    /* next available local variable context index */
1286
    int next_ctx_arr_idx_;
1287
1288
    /* reference to the current code body being parsed */
1289
    CTcCodeBodyRef *cur_code_body_;
1290
1291
    /* flag: 'self' is valid in current code body */
1292
    int self_valid_;
1293
1294
    /* 
1295
     *   flag: 'self' is used (explicitly or implicitly, such as via a
1296
     *   property reference or method call) in the current code body 
1297
     */
1298
    int self_referenced_;
1299
1300
    /* 
1301
     *   Flag: method context beyond 'self' (targetprop, targetobj,
1302
     *   definingobj) is referenced (explicitly or implicitly, such as via
1303
     *   'inherited' or 'delegated') in the current code body.  
1304
     */
1305
    int full_method_ctx_referenced_;
1306
1307
    /*
1308
     *   Flags: the local context of the outermost code body requires
1309
     *   'self'/the full method context to be stored.  
1310
     */
1311
    int local_ctx_needs_self_;
1312
    int local_ctx_needs_full_method_ctx_;
1313
1314
    /* next available enumerator ID */
1315
    ulong next_enum_id_;
1316
1317
    /* 
1318
     *   The '+' property - this is the property that defines the
1319
     *   containment graph for the purposes of the '+' syntax. 
1320
     */
1321
    class CTcSymProp *plus_prop_;
1322
1323
    /*
1324
     *   '+' property location stack.  Each time the program defines an
1325
     *   object using the '+' notation to set the location, we'll update our
1326
     *   record here of the last object at that depth.  Any time an object
1327
     *   is defined at depth N (i.e., using N '+' signs), its location is
1328
     *   set to the last object at depth N-1.  An object with no '+' signs
1329
     *   is at depth zero.  
1330
     */
1331
    class CTPNStmObject **plus_stack_;
1332
    size_t plus_stack_alloc_;
1333
1334
    /*
1335
     *   The module name and sequence number, if known.  The module name is
1336
     *   the name as it appears on the command line, makefile (.t3m), or
1337
     *   library (.tl) file.  The sequence number is an ordinal giving its
1338
     *   position in the list of modules making up the overall program build.
1339
     *   We use this information in generating the sourceTextGroup object.  
1340
     */
1341
    char *module_name_;
1342
    int module_seqno_;
1343
};
1344
1345
/* ------------------------------------------------------------------------ */
1346
/*
1347
 *   Statement termination information.  This is used for certain nested
1348
 *   definition parsers, where a lack of termination in the nested
1349
 *   definition is to be interpreted as being actually caused by a lack of
1350
 *   termination of the enclosing definition. 
1351
 */
1352
struct tcprs_term_info
1353
{
1354
    /* initialize */
1355
    void init(class CTcTokFileDesc *desc, long linenum)
1356
    {
1357
        /* remember the current location */
1358
        desc_ = desc;
1359
        linenum_ = linenum;
1360
1361
        /* no termination error yet */
1362
        unterm_ = FALSE;
1363
    }
1364
1365
    /* 
1366
     *   source location where original terminator might have been - this is
1367
     *   where we decided to go into a nested definition, so if it turns out
1368
     *   that the definintion shouldn't have been nested after all, there
1369
     *   was missing termination here 
1370
     */
1371
    class CTcTokFileDesc *desc_;
1372
    long linenum_;
1373
1374
    /* 
1375
     *   flag: termination was in fact missing in the nested definition; the
1376
     *   nested parser sets this to relay the problem to the caller 
1377
     */
1378
    int unterm_;
1379
};
1380
1381
/* ------------------------------------------------------------------------ */
1382
/*
1383
 *   Object template list entry 
1384
 */
1385
class CTcObjTemplate
1386
{
1387
public:
1388
    CTcObjTemplate(class CTcObjTemplateItem *item_head, size_t item_cnt)
1389
    {
1390
        /* remember my item list */
1391
        items_ = item_head;
1392
        item_cnt_ = item_cnt;
1393
1394
        /* not in a list yet */
1395
        nxt_ = 0;
1396
    }
1397
    
1398
    /* head of list of template items */
1399
    class CTcObjTemplateItem *items_;
1400
1401
    /* number of items in the list */
1402
    size_t item_cnt_;
1403
1404
    /* next template in master list of templates */
1405
    CTcObjTemplate *nxt_;
1406
};
1407
1408
/*
1409
 *   Object template list item 
1410
 */
1411
class CTcObjTemplateItem
1412
{
1413
public:
1414
    CTcObjTemplateItem(class CTcSymProp *prop, tc_toktyp_t tok_type,
1415
                       int is_alt, int is_opt)
1416
    {
1417
        /* remember my defining information */
1418
        prop_ = prop;
1419
        tok_type_ = tok_type;
1420
        is_alt_ = is_alt;
1421
        is_opt_ = is_opt;
1422
1423
        /* not in a list yet */
1424
        nxt_ = 0;
1425
    }
1426
    
1427
    /* property that the item in this position defines */
1428
    class CTcSymProp *prop_;
1429
1430
    /* token type of item in this position */
1431
    tc_toktyp_t tok_type_;
1432
1433
    /* next item in this template's item list */
1434
    CTcObjTemplateItem *nxt_;
1435
1436
    /* flag: this item is an alternative to the previous item */
1437
    unsigned int is_alt_ : 1;
1438
1439
    /* flag: this item is optional */
1440
    unsigned int is_opt_ : 1;
1441
};
1442
1443
/*
1444
 *   Template item instance - we keep track of the actual parameters to a
1445
 *   template with these items. 
1446
 */
1447
class CTcObjTemplateInst
1448
{
1449
public:
1450
    /* 
1451
     *   expression value for the actual parameter, as either a naked
1452
     *   expression (expr_) or as a code body (code_body_) - only one of
1453
     *   expr_ or code_body_ will be valid 
1454
     */
1455
    class CTcPrsNode *expr_;
1456
    class CTPNCodeBody *code_body_;
1457
1458
    /* 
1459
     *   the introductory token of the parameter - if the parameter is
1460
     *   introduced by an operator token, this will not be part of the
1461
     *   expression 
1462
     */
1463
    tc_toktyp_t def_tok_;
1464
1465
    /* the first token of the value */
1466
    CTcToken expr_tok_;
1467
1468
    /* 
1469
     *   The property to which to assign this actual parameter value.  This
1470
     *   isn't filled in until we match the full list to an actual template,
1471
     *   since we don't know the meanings of the parameters until we match
1472
     *   the actuals to an existing template in memory.  
1473
     */
1474
    class CTcSymProp *prop_;
1475
};
1476
1477
1478
/* ------------------------------------------------------------------------ */
1479
/*
1480
 *   Non-symbolic object list entry 
1481
 */
1482
struct tcprs_nonsym_obj
1483
{
1484
    tcprs_nonsym_obj(tctarg_obj_id_t id)
1485
    {
1486
        /* remember the ID */
1487
        id_ = id;
1488
1489
        /* not in a list yet */
1490
        nxt_ = 0;
1491
    }
1492
    
1493
    /* ID of this object */
1494
    tctarg_obj_id_t id_;
1495
    
1496
    /* next entry in the list */
1497
    tcprs_nonsym_obj *nxt_;
1498
};
1499
1500
/* ------------------------------------------------------------------------ */
1501
/*
1502
 *   Dictionary property list entry.  Each time the source code defines a
1503
 *   dictionary property, we'll make an entry in this list. 
1504
 */
1505
class CTcDictPropEntry
1506
{
1507
public:
1508
    CTcDictPropEntry(class CTcSymProp *prop)
1509
    {
1510
        /* remember the property */
1511
        prop_ = prop;
1512
1513
        /* not in a list yet */
1514
        nxt_ = 0;
1515
1516
        /* not defined for current object yet */
1517
        defined_ = FALSE;
1518
    }
1519
1520
    /* my property */
1521
    class CTcSymProp *prop_;
1522
1523
    /* next entry in list */
1524
    CTcDictPropEntry *nxt_;
1525
1526
    /* flag: the current object definition includes this property */
1527
    unsigned int defined_ : 1;
1528
};
1529
1530
/* ------------------------------------------------------------------------ */
1531
/*
1532
 *   Dictionary list entry.  Each dictionary object gets an entry in this
1533
 *   list.
1534
 */
1535
class CTcDictEntry
1536
{
1537
public:
1538
    CTcDictEntry(class CTcSymObj *sym);
1539
1540
    /* get/set my object file index */
1541
    uint get_obj_idx() const { return obj_idx_; }
1542
    void set_obj_idx(uint idx) { obj_idx_ = idx; }
1543
1544
    /* get my object symbol */
1545
    class CTcSymObj *get_sym() const { return sym_; }
1546
1547
    /* get/set the next item in the list */
1548
    CTcDictEntry *get_next() const { return nxt_; }
1549
    void set_next(CTcDictEntry *nxt) { nxt_ = nxt; }
1550
1551
    /* add a word to the table */
1552
    void add_word(const char *txt, size_t len, int copy,
1553
                  tc_obj_id obj, tc_prop_id prop);
1554
1555
    /* write my symbol to the object file if I haven't already done so */
1556
    void write_sym_to_obj_file(CVmFile *fp);
1557
1558
    /* get the hash table */
1559
    class CVmHashTable *get_hash_table() const { return hashtab_; }
1560
1561
protected:
1562
    /* enumeration callback - write to object file */
1563
    static void enum_cb_writeobj(void *ctx, class CVmHashEntry *entry);
1564
    
1565
    /* associated object symbol */
1566
    class CTcSymObj *sym_;
1567
1568
    /* 
1569
     *   object file index (we use this to match up the dictionary objects
1570
     *   when we re-load the object file) 
1571
     */
1572
    uint obj_idx_;
1573
1574
    /* next item in the dictionary list */
1575
    CTcDictEntry *nxt_;
1576
1577
    /* hash table containing the word entries */
1578
    class CVmHashTable *hashtab_;
1579
};
1580
1581
1582
/*
1583
 *   entry in a dictionary list 
1584
 */
1585
struct CTcPrsDictItem
1586
{
1587
    CTcPrsDictItem(tc_obj_id obj, tc_prop_id prop)
1588
    {
1589
        obj_ = obj;
1590
        prop_ = prop;
1591
        nxt_ = 0;
1592
    }
1593
1594
    /* object */
1595
    tc_obj_id obj_;
1596
1597
    /* property */
1598
    tc_prop_id prop_;
1599
1600
    /* next entry in list */
1601
    CTcPrsDictItem *nxt_;
1602
};
1603
1604
/*
1605
 *   Parser dictionary hash table entry 
1606
 */
1607
class CVmHashEntryPrsDict: public CVmHashEntryCS
1608
{
1609
public:
1610
    CVmHashEntryPrsDict(const char *txt, size_t len, int copy)
1611
        : CVmHashEntryCS(txt, len, copy)
1612
    {
1613
        /* nothing in my list yet */
1614
        list_ = 0;
1615
    }
1616
1617
    /* add an item to my list */
1618
    void add_item(tc_obj_id obj, tc_prop_id prop);
1619
1620
    /* get the list head */
1621
    struct CTcPrsDictItem *get_list() const { return list_; }
1622
1623
protected:
1624
    /* list of object/property associations with this word */
1625
    struct CTcPrsDictItem *list_;
1626
};
1627
1628
/* ------------------------------------------------------------------------ */
1629
/*
1630
 *   State save structure for parsing property expressions 
1631
 */
1632
class CTcPrsPropExprSave
1633
{
1634
public:
1635
    unsigned int has_local_ctx_ : 1;
1636
    int local_ctx_var_num_;
1637
    size_t ctx_var_props_used_;
1638
    int next_ctx_arr_idx_;
1639
    int self_referenced_;
1640
    int full_method_ctx_referenced_;
1641
    int local_ctx_needs_self_;
1642
    int local_ctx_needs_full_method_ctx_;
1643
    struct CTcCodeBodyRef *cur_code_body_;
1644
};
1645
1646
/* ------------------------------------------------------------------------ */
1647
/*
1648
 *   Grammar production list entry 
1649
 */
1650
class CTcGramProdEntry
1651
{
1652
public:
1653
    CTcGramProdEntry(class CTcSymObj *prod_obj);
1654
1655
    /* get my production object symbol */
1656
    class CTcSymObj *get_prod_sym() const { return prod_sym_; }
1657
1658
    /* get/set the next item in the list */
1659
    CTcGramProdEntry *get_next() const { return nxt_; }
1660
    void set_next(CTcGramProdEntry *nxt) { nxt_ = nxt; }
1661
1662
    /* add an alternative */
1663
    void add_alt(class CTcGramProdAlt *alt);
1664
1665
    /* get the alternative list head */
1666
    class CTcGramProdAlt *get_alt_head() const { return alt_head_; }
1667
1668
    /* write to an object file */
1669
    void write_to_obj_file(class CVmFile *fp);
1670
1671
    /* load from an object file */
1672
    static void load_from_obj_file(class CVmFile *fp,
1673
                                   const tctarg_prop_id_t *prop_xlat,
1674
                                   const ulong *enum_xlat,
1675
                                   class CTcSymObj *private_owner);
1676
1677
    /* move alternatives from my list to the given target list */
1678
    void move_alts_to(CTcGramProdEntry *new_entry);
1679
1680
    /* get/set explicitly-declared flag */
1681
    int is_declared() const { return is_declared_; }
1682
    void set_declared(int f) { is_declared_ = f; }
1683
1684
protected:
1685
    /* associated production object symbol */
1686
    class CTcSymObj *prod_sym_;
1687
1688
    /* next item in the list */
1689
    CTcGramProdEntry *nxt_;
1690
1691
    /* head and tail of alternative list */
1692
    class CTcGramProdAlt *alt_head_;
1693
    class CTcGramProdAlt *alt_tail_;
1694
1695
    /* 
1696
     *   flag: this production was explicitly declared (this means that we
1697
     *   will consider it valid at link time even if it has no alternatives
1698
     *   defined) 
1699
     */
1700
    unsigned int is_declared_ : 1;
1701
};
1702
1703
/*
1704
 *   Grammar production alternative.  Each grammar production has one or
1705
 *   more alternatives that, when matched, generate the production. 
1706
 */
1707
class CTcGramProdAlt
1708
{
1709
public:
1710
    CTcGramProdAlt(class CTcSymObj *obj_sym, class CTcDictEntry *dict);
1711
1712
    /* get/set my score */
1713
    int get_score() const { return score_; }
1714
    void set_score(int score) { score_ = score; }
1715
1716
    /* get/set my badness */
1717
    int get_badness() const { return badness_; }
1718
    void set_badness(int badness) { badness_ = badness; }
1719
1720
    /* get my processor object symbol */
1721
    class CTcSymObj *get_processor_obj() const { return obj_sym_; }
1722
1723
    /* get/set the next list element */
1724
    CTcGramProdAlt *get_next() const { return nxt_; }
1725
    void set_next(CTcGramProdAlt *nxt) { nxt_ = nxt; }
1726
1727
    /* add a token to my list */
1728
    void add_tok(class CTcGramProdTok *tok);
1729
1730
    /* get the head of my token list */
1731
    class CTcGramProdTok *get_tok_head() const { return tok_head_; }
1732
1733
    /* write to an object file */
1734
    void write_to_obj_file(class CVmFile *fp);
1735
1736
    /* load from an object file */
1737
    static CTcGramProdAlt *
1738
        load_from_obj_file(class CVmFile *fp,
1739
                           const tctarg_prop_id_t *prop_xlat,
1740
                           const ulong *enum_xlat);
1741
1742
    /* get the dictionary in effect when the alternative was defined */
1743
    class CTcDictEntry *get_dict() const { return dict_; }
1744
1745
protected:
1746
    /* head and tail of our token list */
1747
    class CTcGramProdTok *tok_head_;
1748
    class CTcGramProdTok *tok_tail_;
1749
1750
    /* dictionary in effect when alternative was defined */
1751
    class CTcDictEntry *dict_;
1752
1753
    /* the processor object associated with this alternative */
1754
    class CTcSymObj *obj_sym_;
1755
1756
    /* next alternative in our production */
1757
    CTcGramProdAlt *nxt_;
1758
1759
    /* score */
1760
    int score_;
1761
1762
    /* badness */
1763
    int badness_;
1764
};
1765
1766
/* grammar production token types */
1767
enum tcgram_tok_type
1768
{
1769
    /* unknown */
1770
    TCGRAM_UNKNOWN,
1771
    
1772
    /* match a production (given by the production object) */
1773
    TCGRAM_PROD,
1774
1775
    /* match a part of speech (given by the dictionary property) */
1776
    TCGRAM_PART_OF_SPEECH,
1777
1778
    /* match a literal string */
1779
    TCGRAM_LITERAL,
1780
1781
    /* token-type match */
1782
    TCGRAM_TOKEN_TYPE,
1783
1784
    /* free-floating end-of-string */
1785
    TCGRAM_STAR,
1786
1787
    /* match one of several parts of speech */
1788
    TCGRAM_PART_OF_SPEECH_LIST
1789
};
1790
1791
/*
1792
 *   Grammar production alternative token 
1793
 */
1794
class CTcGramProdTok
1795
{
1796
public:
1797
    CTcGramProdTok()
1798
    {
1799
        /* not in a list yet */
1800
        nxt_ = 0;
1801
1802
        /* no type yet */
1803
        typ_ = TCGRAM_UNKNOWN;
1804
1805
        /* no property association yte */
1806
        prop_assoc_ = TCTARG_INVALID_PROP;
1807
    }
1808
1809
    /* get/set my next element */
1810
    CTcGramProdTok *get_next() const { return nxt_; }
1811
    void set_next(CTcGramProdTok *nxt) { nxt_ = nxt; }
1812
1813
    /* set me to match a production object */
1814
    void set_match_prod(class CTcSymObj *obj)
1815
    {
1816
        /* remember the production object */
1817
        typ_ = TCGRAM_PROD;
1818
        val_.obj_ = obj;
1819
    }
1820
1821
    /* set me to match a token type */
1822
    void set_match_token_type(ulong enum_id)
1823
    {
1824
        /* remember the token enum ID */
1825
        typ_ = TCGRAM_TOKEN_TYPE;
1826
        val_.enum_id_ = enum_id;
1827
    }
1828
1829
    /* set me to match a dictionary property */
1830
    void set_match_part_of_speech(tctarg_prop_id_t prop)
1831
    {
1832
        /* remember the part of speech */
1833
        typ_ = TCGRAM_PART_OF_SPEECH;
1834
        val_.prop_ = prop;
1835
    }
1836
1837
    /* 
1838
     *   set me to match a list of parts of speech; each part of speech must
1839
     *   be separately added via add_match_part_ele() 
1840
     */
1841
    void set_match_part_list();
1842
1843
    /* add an element to the part-of-speech match list */
1844
    void add_match_part_ele(tctarg_prop_id_t prop);
1845
1846
    /* set me to match a literal string */
1847
    void set_match_literal(const char *txt, size_t len)
1848
    {
1849
        /* remember the string */
1850
        typ_ = TCGRAM_LITERAL;
1851
        val_.str_.txt_ = txt;
1852
        val_.str_.len_ = len;
1853
    }
1854
1855
    /* set me to match a free-floating end-of-string */
1856
    void set_match_star()
1857
    {
1858
        /* set the type */
1859
        typ_ = TCGRAM_STAR;
1860
    }
1861
1862
    /* get my type */
1863
    tcgram_tok_type get_type() const { return typ_; }
1864
1865
    /* get my value */
1866
    class CTcSymObj *getval_prod() const { return val_.obj_; }
1867
    tctarg_prop_id_t getval_part_of_speech() const { return val_.prop_; }
1868
    const char *getval_literal_txt() const { return val_.str_.txt_; }
1869
    const size_t getval_literal_len() const { return val_.str_.len_; }
1870
    ulong getval_token_type() const { return val_.enum_id_; }
1871
    size_t getval_part_list_len() const { return val_.prop_list_.len_; }
1872
    tctarg_prop_id_t getval_part_list_ele(size_t idx) const
1873
        { return val_.prop_list_.arr_[idx]; }
1874
1875
    /* 
1876
     *   get/set my property association - this is the property to which
1877
     *   the actual match to the rule is assigned when we match the rule 
1878
     */
1879
    tctarg_prop_id_t get_prop_assoc() const { return prop_assoc_; }
1880
    void set_prop_assoc(tctarg_prop_id_t prop) { prop_assoc_ = prop; }
1881
1882
    /* write to an object file */
1883
    void write_to_obj_file(class CVmFile *fp);
1884
1885
    /* load from an object file */
1886
    static CTcGramProdTok *
1887
        load_from_obj_file(class CVmFile *fp,
1888
                           const tctarg_prop_id_t *prop_xlat,
1889
                           const ulong *enum_xlat);
1890
1891
protected:
1892
    /* next token in my list */
1893
    CTcGramProdTok *nxt_;
1894
1895
    /* my type - this specifies how this token matches */
1896
    tcgram_tok_type typ_;
1897
1898
    /* match specification - varies according to my type */
1899
    union
1900
    {
1901
        /* object - for matching a production */
1902
        class CTcSymObj *obj_;
1903
1904
        /* property - for matching a part of speech */
1905
        tctarg_prop_id_t prop_;
1906
1907
        /* token enum id - for matching a token type */
1908
        ulong enum_id_;
1909
1910
        /* literal string */
1911
        struct
1912
        {
1913
            const char *txt_;
1914
            size_t len_;
1915
        } str_;
1916
1917
        /* list of vocabulary elements */
1918
        struct
1919
        {
1920
            /* number of array entries allocated */
1921
            size_t alo_;
1922
1923
            /* number of array entries actually used */
1924
            size_t len_;
1925
1926
            /* array of entries */
1927
            tctarg_prop_id_t *arr_;
1928
        } prop_list_;
1929
    } val_;
1930
1931
    /* property association */
1932
    tctarg_prop_id_t prop_assoc_;
1933
};
1934
1935
/* ------------------------------------------------------------------------ */
1936
/*
1937
 *   Exported symbol record 
1938
 */
1939
class CTcPrsExport
1940
{
1941
public:
1942
    /* create with the given compiler symbol */
1943
    CTcPrsExport(const char *sym, size_t sym_len)
1944
    {
1945
        /* remember my name */
1946
        sym_ = sym;
1947
        sym_len_ = sym_len;
1948
1949
        /* 
1950
         *   we don't yet have an explicit external name, so export using
1951
         *   the internal name 
1952
         */
1953
        ext_name_ = sym;
1954
        ext_len_ = sym_len;
1955
1956
        /* we're not in a list yet */
1957
        nxt_ = 0;
1958
    }
1959
1960
    /* set the external name */
1961
    void set_extern_name(const char *txt, size_t len)
1962
    {
1963
        ext_name_ = txt;
1964
        ext_len_ = len;
1965
    }
1966
1967
    /* get the symbol name and length */
1968
    const char *get_sym() const { return sym_; }
1969
    size_t get_sym_len() const { return sym_len_; }
1970
1971
    /* get the external name and length */
1972
    const char *get_ext_name() const { return ext_name_; }
1973
    size_t get_ext_len() const { return ext_len_; }
1974
1975
    /* get/set the next entry in the list */
1976
    CTcPrsExport *get_next() const { return nxt_; }
1977
    void set_next(CTcPrsExport *nxt) { nxt_ = nxt; }
1978
1979
    /* write to an object file */
1980
    void write_to_obj_file(class CVmFile *fp);
1981
1982
    /* read from an object file */
1983
    static CTcPrsExport *read_from_obj_file(class CVmFile *fp);
1984
1985
    /* determine if my external name matches the given export's */
1986
    int ext_name_matches(const CTcPrsExport *exp) const
1987
    {
1988
        return (exp->get_ext_len() == get_ext_len()
1989
                && memcmp(exp->get_ext_name(), get_ext_name(),
1990
                          get_ext_len()) == 0);
1991
    }
1992
1993
    /* determine if my name matches the given string */
1994
    int ext_name_matches(const char *txt) const
1995
    {
1996
        return (get_ext_len() == get_strlen(txt)
1997
                && memcmp(get_ext_name(), txt, get_ext_len()) == 0);
1998
    }
1999
2000
    /* determine if my symbol name matches the given export's */
2001
    int sym_matches(const CTcPrsExport *exp) const
2002
    {
2003
        return (exp->get_sym_len() == get_sym_len()
2004
                && memcmp(exp->get_sym(), get_sym(), get_sym_len()) == 0);
2005
    }
2006
2007
protected:
2008
    /* symbol name - this is the internal compiler symbol being exported */
2009
    const char *sym_;
2010
    size_t sym_len_;
2011
2012
    /* external name - this is the name visible to the VM loader */
2013
    const char *ext_name_;
2014
    size_t ext_len_;
2015
    
2016
    /* next in list */
2017
    CTcPrsExport *nxt_;
2018
};
2019
2020
2021
/* ------------------------------------------------------------------------ */
2022
/*
2023
 *   Parser Symbol Table.  The parser maintains a hierarchy of symbol
2024
 *   tables; a local symbol table can be nested inside an enclosing
2025
 *   scope's symbol table, and so on up to the top-level block scope,
2026
 *   which is enclosed by the global scope.  In addition, at function
2027
 *   scope there's a separate table for "goto" labels. 
2028
 */
2029
2030
/* find_or_def actions for undefined symbols */
2031
enum tcprs_undef_action
2032
{
2033
    /* if undefined, add an "undefined" entry unconditionally */
2034
    TCPRS_UNDEF_ADD_UNDEF,
2035
2036
    /* add a "property" entry unconditionally, but warn about it */
2037
    TCPRS_UNDEF_ADD_PROP,
2038
2039
    /* add a "property" entry unconditionally, with no warning */
2040
    TCPRS_UNDEF_ADD_PROP_NO_WARNING
2041
};
2042
2043
/* parser symbol table */
2044
class CTcPrsSymtab
2045
{
2046
public:
2047
    CTcPrsSymtab(CTcPrsSymtab *parent_scope);
2048
    ~CTcPrsSymtab();
2049
2050
    /* allocate parser symbol tables out of the parser memory pool */
2051
    void *operator new(size_t siz);
2052
2053
    /* 
2054
     *   perform static initialization/termination - call once at program
2055
     *   startup and shutdown (respectively) 
2056
     */
2057
    static void s_init();
2058
    static void s_terminate();
2059
2060
    /* get the enclosing scope's symbol table */
2061
    CTcPrsSymtab *get_parent() const { return parent_; }
2062
2063
    /* find a symbol; returns null if the symbol isn't defined */
2064
    class CTcSymbol *find(const textchar_t *sym, size_t len)
2065
        { return find(sym, len, 0); }
2066
2067
    class CTcSymbol *find(const textchar_t *sym)
2068
        { return find(sym, strlen(sym), 0); }
2069
2070
    /* 
2071
     *   Find a symbol; returns null if the symbol isn't defined.  If
2072
     *   symtab is not null, we'll fill it in with the actual symbol table
2073
     *   in which we found the symbol; this might be an enclosing symbol
2074
     *   table, since we search up the enclosing scope list. 
2075
     */
2076
    class CTcSymbol *find(const textchar_t *sym, size_t len,
2077
                          CTcPrsSymtab **symtab);
2078
2079
    /* find a symbol directly in this table, without searching parents */
2080
    class CTcSymbol *find_direct(const textchar_t *sym, size_t len);
2081
2082
    /* find a symbol without changing its referenced status */
2083
    class CTcSymbol *find_noref(const textchar_t *sym, size_t len,
2084
                                CTcPrsSymtab **symtab);
2085
2086
    /* 
2087
     *   Find a symbol; if the symbol isn't defined, log an error and add
2088
     *   the symbol as type "undefined".  Because we add a symbol entry if
2089
     *   the symbol isn't defined, this *always* returns a valid symbol
2090
     *   object.  
2091
     */
2092
    class CTcSymbol *find_or_def_undef(const char *sym, size_t len,
2093
                                       int copy_str)
2094
    {
2095
        return find_or_def(sym, len, copy_str, TCPRS_UNDEF_ADD_UNDEF);
2096
    }
2097
2098
    /*
2099
     *   Find a symbol; if the symbol isn't defined, log a warning and
2100
     *   define the symbol as type property.  Because we add an entry if
2101
     *   the symbol isn't defined, this *always* returns a valid symbol
2102
     *   object.  
2103
     */
2104
    class CTcSymbol *find_or_def_prop(const char *sym, size_t len,
2105
                                      int copy_str)
2106
    {
2107
        return find_or_def(sym, len, copy_str, TCPRS_UNDEF_ADD_PROP);
2108
    }
2109
        
2110
    /*
2111
     *   Find a symbol; if the symbol isn't defined, define the symbol as
2112
     *   type property with no warning.  This should be used when it is
2113
     *   unambiguous that a symbol is meant as a property name.  Because we
2114
     *   add an entry if the symbol isn't defined, this *always* returns a
2115
     *   valid symbol object.  
2116
     */
2117
    class CTcSymbol *find_or_def_prop_explicit(const char *sym, size_t len,
2118
                                               int copy_str)
2119
    {
2120
        return find_or_def(sym, len, copy_str,
2121
                           TCPRS_UNDEF_ADD_PROP_NO_WARNING);
2122
    }
2123
        
2124
    /*
2125
     *   Find a symbol.  If the symbol isn't defined, and a "self" object
2126
     *   is available, define the symbol as a property.  If the symbol
2127
     *   isn't defined an no "self" object is available, add an
2128
     *   "undefined" entry for the symbol. 
2129
     */
2130
    class CTcSymbol *find_or_def_prop_implied(const char *sym, size_t len,
2131
                                              int copy_str, int is_self_avail)
2132
    {
2133
        return find_or_def(sym, len, copy_str,
2134
                           is_self_avail
2135
                           ? TCPRS_UNDEF_ADD_PROP : TCPRS_UNDEF_ADD_UNDEF);
2136
    }
2137
2138
    /* add a formal parameter symbol */
2139
    void add_formal(const textchar_t *sym, size_t len, int formal_num,
2140
                    int copy_str);
2141
2142
    /* add a local variable symbol */
2143
    class CTcSymLocal *add_local(const textchar_t *sym, size_t len,
2144
                                 int local_num, int copy_str,
2145
                                 int init_assigned, int init_referenced);
2146
2147
    /* add a 'goto' symbol */
2148
    class CTcSymLabel *add_code_label(const textchar_t *sym, size_t len,
2149
                                      int copy_str);
2150
2151
    /* add an entry to the table */
2152
    void add_entry(class CTcSymbol *sym);
2153
2154
    /* remove an entry */
2155
    void remove_entry(class CTcSymbol *sym);
2156
2157
    /* enumerate entries in the table through a callback */
2158
    void enum_entries(void (*func)(void *, class CTcSymbol *), void *ctx);
2159
2160
    /*
2161
     *   Scan the symbol table and check for unreferenced locals.  Logs an
2162
     *   error for each unreferenced or unassigned local.
2163
     */
2164
    void check_unreferenced_locals();
2165
2166
    /* 
2167
     *   Get/set my debugging list index - this is the index of this table
2168
     *   in the list for this function or method.  The index values start
2169
     *   at 1 - a value of zero indicates that the symbol table isn't part
2170
     *   of any list.  
2171
     */
2172
    int get_list_index() const { return list_index_; }
2173
    void set_list_index(int n) { list_index_ = n; }
2174
2175
    /* get/set the next entry in the linked list */
2176
    CTcPrsSymtab *get_list_next() const { return list_next_; }
2177
    void set_list_next(CTcPrsSymtab *nxt) { list_next_ = nxt; }
2178
2179
protected:
2180
    /* add an entry to a global symbol table */
2181
    static void add_to_global_symtab(CTcPrsSymtab *tab, CTcSymbol *entry);
2182
2183
    /* get the underlying hash table */
2184
    class CVmHashTable *get_hashtab() const { return hashtab_; }
2185
2186
    /* enumeration callback - check for unreferenced locals */
2187
    static void unref_local_cb(void *ctx, class CTcSymbol *sym);
2188
2189
    /* 
2190
     *   find a symbol, or define a new symbol, according to the given
2191
     *   action mode, if the symbol is undefined 
2192
     */
2193
    class CTcSymbol *find_or_def(const textchar_t *sym, size_t len,
2194
                                 int copy_str, tcprs_undef_action action);
2195
    
2196
    /* enclosing scope (parent) symbol table */
2197
    CTcPrsSymtab *parent_;
2198
    
2199
    /* hash table */
2200
    class CVmHashTable *hashtab_;
2201
2202
    /* hash function */
2203
    static class CVmHashFunc *hash_func_;
2204
2205
    /*
2206
     *   Next symbol table in local scope chain.  For each function or
2207
     *   method, we keep a simple linear list of the local scopes so that
2208
     *   they can be written to the debugging records.  We also keep an
2209
     *   index value giving its position in the list, so that we can store
2210
     *   references to the table using the list index.  
2211
     */
2212
    CTcPrsSymtab *list_next_;
2213
    int list_index_;
2214
};
2215
2216
2217
/* ------------------------------------------------------------------------ */
2218
/*
2219
 *   Debugger symbol table interface.  This is an abstract interface that
2220
 *   debuggers can implement to allow us to search for symbols that are
2221
 *   obtained from a compiled program's debugger records.  To keep the
2222
 *   compiler independent of the target architecture and the debugger's
2223
 *   own internal structures, we define this abstract interface that the
2224
 *   debugger must implement.
2225
 *   
2226
 *   Since this type of symbol table is provided by a debugger as a view
2227
 *   on the symbol information in a previously compiled program, the
2228
 *   parser naturally has no need to add symbols to the table; hence the
2229
 *   only required operations are symbol lookups.  
2230
 */
2231
class CTcPrsDbgSymtab
2232
{
2233
public:
2234
    /* 
2235
     *   Get information on a symbol.  Returns true if the symbol is
2236
     *   found, false if not.  If we find the symbol, fills in the
2237
     *   information structure with the appropriate data.  
2238
     */
2239
    virtual int find_symbol(const textchar_t *sym, size_t len,
2240
                            struct tcprsdbg_sym_info *info) = 0;
2241
};
2242
2243
/*
2244
 *   Debugger local symbol information structure 
2245
 */
2246
struct tcprsdbg_sym_info
2247
{
2248
    /* symbol type */
2249
    enum tc_symtype_t sym_type;
2250
    
2251
    /* local/parameter number */
2252
    uint var_id;
2253
2254
    /* context variable index - 0 if it's not a context local */
2255
    int ctx_arr_idx;
2256
2257
    /* stack frame index */
2258
    uint frame_idx;
2259
};
2260
2261
2262
2263
/* ------------------------------------------------------------------------ */
2264
/*
2265
 *   Parse Tree storage manager.
2266
 *   
2267
 *   The parse tree has some special characteristics that make it
2268
 *   desirable to use a special memory manager for it.  First, the parse
2269
 *   tree consists of many small objects, so we would like to have as
2270
 *   little overhead per object for memory tracking as possible.  Second,
2271
 *   parse tree objects all have a similar lifetime: we create the entire
2272
 *   parse tree as we scan the source, then use it to generate target
2273
 *   code, then discard the whole thing.
2274
 *   
2275
 *   To manage memory efficiently for the parse tree, we define our own
2276
 *   memory manager for parse tree objects.  The memory manager is very
2277
 *   simple, fast, and has minimal per-object overhead.  We simply
2278
 *   maintain a list of large blocks, then suballocate requests out of the
2279
 *   large blocks.  Each time we run out of space in a block, we allocate
2280
 *   a new block.  We do not keep track of any extra tracking information
2281
 *   per node, so a node cannot be individually freed; however, the entire
2282
 *   block list can be freed at once, which is exactly the behavior we
2283
 *   want. 
2284
 */
2285
class CTcPrsMem
2286
{
2287
public:
2288
    CTcPrsMem();
2289
    ~CTcPrsMem();
2290
    
2291
    /* allocate storage */
2292
    void *alloc(size_t siz);
2293
2294
    /* save the current pool state, for later resetting */
2295
    void save_state(struct tcprsmem_state_t *state);
2296
2297
    /* 
2298
     *   reset the pool to the given state - delete all objects allocated
2299
     *   in the pool since the state was saved 
2300
     */
2301
    void reset(const struct tcprsmem_state_t *state);
2302
2303
    /* reset to initial state */
2304
    void reset();
2305
2306
private:
2307
    /* delete all parser memory */
2308
    void delete_all();
2309
2310
    /* allocate a new block */
2311
    void alloc_block();
2312
2313
    /* head of list of memory blocks */
2314
    struct tcprsmem_blk_t *head_;
2315
2316
    /* tail of list and current memory block */
2317
    struct tcprsmem_blk_t *tail_;
2318
2319
    /* current allocation offset in last block */
2320
    char *free_ptr_;
2321
2322
    /* remaining space available in last block */
2323
    size_t rem_;
2324
};
2325
2326
/* 
2327
 *   state-saving structure
2328
 */
2329
struct tcprsmem_state_t
2330
{
2331
    /* current tail of memory block list */
2332
    struct tcprsmem_blk_t *tail;
2333
2334
    /* current allocation offset in last block */
2335
    char *free_ptr;
2336
2337
    /* current remaining space in last block */
2338
    size_t rem;
2339
};
2340
2341
2342
/*
2343
 *   Provide an overridden operator new for allocating objects explicitly
2344
 *   from the pool 
2345
 */
2346
inline void *operator new(size_t siz, CTcPrsMem *pool)
2347
{
2348
    return pool->alloc(siz);
2349
}
2350
2351
/* 
2352
 *   provide an array operator new as well 
2353
 */
2354
inline void *operator new[](size_t siz, CTcPrsMem *pool)
2355
{
2356
    return pool->alloc(siz);
2357
}
2358
2359
2360
/*
2361
 *   parse tree memory block 
2362
 */
2363
struct tcprsmem_blk_t
2364
{
2365
    /* next block in the list */
2366
    tcprsmem_blk_t *next_;
2367
2368
    /* 
2369
     *   This block's byte array (the array extends off the end of the
2370
     *   structure).
2371
     */
2372
    char buf_[1];
2373
};
2374
2375
/* ------------------------------------------------------------------------ */
2376
/*
2377
 *   Special array list subclass that uses parser memory 
2378
 */
2379
class CPrsArrayList: public CArrayList
2380
{
2381
protected:
2382
    /* 
2383
     *   override the memory management functions to use parser memory 
2384
     */
2385
2386
    virtual void *alloc_mem(size_t siz)
2387
    {
2388
        /* allocate from the parser pool */
2389
        return G_prsmem->alloc(siz);
2390
    }
2391
2392
    virtual void *realloc_mem(void *p, size_t oldsiz, size_t newsiz)
2393
    {
2394
        void *pnew;
2395
2396
        /* allocate a new block from the parser pool */
2397
        pnew = G_prsmem->alloc(newsiz);
2398
2399
        /* copy from the old block to the new block */
2400
        memcpy(pnew, p, oldsiz);
2401
2402
        /* return the new block */
2403
        return pnew;
2404
    }
2405
2406
    virtual void free_mem(void *p)
2407
    {
2408
        /* 
2409
         *   do nothing - the parser pool automatically frees everything as a
2410
         *   block when terminating the parser 
2411
         */
2412
    }
2413
};
2414
2415
2416
/* ------------------------------------------------------------------------ */
2417
/*
2418
 *   Expression Constant Value object.  This object is used to express the
2419
 *   value of a constant expression.  
2420
 */
2421
class CTcConstVal
2422
{
2423
public:
2424
    CTcConstVal()
2425
    {
2426
        /* the type is unknown */
2427
        typ_ = TC_CVT_UNK;
2428
    }
2429
2430
    /* 
2431
     *   determine if this is a constant value - it is a constant if it
2432
     *   has any known value 
2433
     */
2434
    int is_const() const { return (typ_ != TC_CVT_UNK); }
2435
2436
    /* 
2437
     *   set the type to unknown - this indicates that there is no valid
2438
     *   value, which generally means that the associated expression does
2439
     *   not have a constant value 
2440
     */
2441
    void set_unknown() { typ_ = TC_CVT_UNK; }
2442
2443
    /* set from another value */
2444
    void set(const CTcConstVal *val)
2445
    {
2446
        /* copy the type */
2447
        typ_ = val->typ_;
2448
2449
        /* copy the value */
2450
        val_ = val->val_;
2451
    }
2452
2453
    /* set an integer value */
2454
    void set_int(long val) { typ_ = TC_CVT_INT; val_.intval_ = val; }
2455
2456
    /* set a floating-point value */
2457
    void set_float(const char *val, size_t len)
2458
    {
2459
        typ_ = TC_CVT_FLOAT;
2460
        val_.floatval_.txt_ = val;
2461
        val_.floatval_.len_ = len;
2462
    }
2463
2464
    /* set an enumerator value */
2465
    void set_enum(ulong val) { typ_ = TC_CVT_ENUM; val_.enumval_ = val; }
2466
2467
    /* set a single-quoted string value */
2468
    void set_sstr(const char *val, size_t len);
2469
2470
    /* set a list value */
2471
    void set_list(class CTPNList *lst);
2472
2473
    /* set an object reference value */
2474
    void set_obj(ulong obj, enum tc_metaclass_t meta)
2475
    {
2476
        typ_ = TC_CVT_OBJ;
2477
        val_.objval_.id_ = obj;
2478
        val_.objval_.meta_ = meta;
2479
    }
2480
2481
    /* set a property pointer value */
2482
    void set_prop(uint prop)
2483
    {
2484
        typ_ = TC_CVT_PROP;
2485
        val_.propval_ = prop;
2486
    }
2487
2488
    /* set a function pointer value */
2489
    void set_funcptr(class CTcSymFunc *sym)
2490
    {
2491
        typ_ = TC_CVT_FUNCPTR;
2492
        val_.funcptrval_ = sym;
2493
    }
2494
2495
    /* set an anonymous function pointer value */
2496
    void set_anon_funcptr(class CTPNCodeBody *code_body)
2497
    {
2498
        typ_ = TC_CVT_ANONFUNCPTR;
2499
        val_.codebodyval_ = code_body;
2500
    }
2501
2502
    /* set a nil/true value */
2503
    void set_nil() { typ_ = TC_CVT_NIL; }
2504
    void set_true() { typ_ = TC_CVT_TRUE; }
2505
2506
    /*
2507
     *   Set a vocabulary list placeholder.  This has no actual value
2508
     *   during compilation; instead, this is just a placeholder.  During
2509
     *   linking, we'll replace each of these with a list of strings
2510
     *   giving the actual vocabulary for the property. 
2511
     */
2512
    void set_vocab_list() { typ_ = TC_CVT_VOCAB_LIST; }
2513
2514
    /* set a nil/true value based on a boolean value */
2515
    void set_bool(int val)
2516
    {
2517
        typ_ = (val ? TC_CVT_TRUE : TC_CVT_NIL);
2518
    }
2519
2520
    /* get my type */
2521
    tc_constval_type_t get_type() const { return typ_; }
2522
2523
    /* get my int value (no type checking) */
2524
    long get_val_int() const { return val_.intval_; }
2525
2526
    /* get my floating point value (no type checking) */
2527
    const char *get_val_float() const { return val_.floatval_.txt_; }
2528
    size_t get_val_float_len() const { return val_.floatval_.len_; }
2529
2530
    /* get my enumerator value (no type checking) */
2531
    ulong get_val_enum() const { return val_.enumval_; }
2532
2533
    /* get my string value (no type checking) */
2534
    const char *get_val_str() const { return val_.strval_.strval_; }
2535
    size_t get_val_str_len() const { return val_.strval_.strval_len_; }
2536
2537
    /* get my list value (no type checking) */
2538
    class CTPNList *get_val_list() const { return val_.listval_; }
2539
2540
    /* get my object reference value (no type checking) */
2541
    ulong get_val_obj() const
2542
        { return val_.objval_.id_; }
2543
    enum tc_metaclass_t get_val_obj_meta() const
2544
        { return val_.objval_.meta_; }
2545
2546
    /* get my property pointer value (no type checking) */
2547
    uint get_val_prop() const { return val_.propval_; }
2548
2549
    /* get my function pointer symbol value (no type checking) */
2550
    class CTcSymFunc *get_val_funcptr_sym() const
2551
        { return val_.funcptrval_; }
2552
2553
    /* get my anonymous function pointer value (no type checking) */
2554
    class CTPNCodeBody *get_val_anon_func_ptr() const
2555
        { return val_.codebodyval_; }
2556
2557
    /*
2558
     *   Determine if this value equals a given constant value.  Returns
2559
     *   true if so, false if not.  We'll set (*can_compare) to true if
2560
     *   the values are comparable, false if the comparison is not
2561
     *   meaningful.  
2562
     */
2563
    int is_equal_to(const CTcConstVal *val) const;
2564
2565
    /*
2566
     *   Convert an integer, nil, or true value to a string.  Fills in the
2567
     *   buffer with the result of the conversion if the value wasn't
2568
     *   already a string.  If the value is already a string, we'll simply
2569
     *   return a pointer to the original string without making a copy.
2570
     *   Returns null if the value is not convertible to a string.  
2571
     */
2572
    const char *cvt_to_str(char *buf, size_t bufl, size_t *result_len);
2573
2574
    /* 
2575
     *   Get my true/nil value.  Returns false if the value is nil or zero,
2576
     *   true if it's anything else.  
2577
     */
2578
    int get_val_bool() const
2579
    {
2580
        return !(typ_ == TC_CVT_NIL
2581
                 || (typ_ == TC_CVT_INT && get_val_int() == 0));
2582
    }
2583
2584
private:
2585
    /* my type */
2586
    tc_constval_type_t typ_;
2587
2588
    union
2589
    {
2590
        /* integer value (valid when typ_ == TC_CVT_INT) */
2591
        long intval_;
2592
2593
        /* floating-point value (valid when typ_ == TC_CVT_FLOAT) */
2594
        struct
2595
        {
2596
            const char *txt_;
2597
            size_t len_;
2598
        }
2599
        floatval_;
2600
2601
        /* enumerator value (valid when typ_ == TC_CVT_ENUM) */
2602
        ulong enumval_;
2603
2604
        /* 
2605
         *   String value (valid when typ_ == TC_CVT_TYPE_SSTR).  We need
2606
         *   to know the length separately, because the underyling string
2607
         *   may not be null-terminated.  
2608
         */
2609
        struct
2610
        {
2611
            const char *strval_;
2612
            size_t strval_len_;
2613
        }
2614
        strval_;
2615
2616
        /* my list value */
2617
        class CTPNList *listval_;
2618
2619
        /* property ID value */
2620
        uint propval_;
2621
2622
        /* object reference value */
2623
        struct
2624
        {
2625
            ulong id_;
2626
            enum tc_metaclass_t meta_;
2627
        }
2628
        objval_;
2629
2630
        /* 
2631
         *   function pointer value - we store the underlying symbol,
2632
         *   since function pointers are generally not resolved until late
2633
         *   in the compilation 
2634
         */
2635
        class CTcSymFunc *funcptrval_;
2636
2637
        /* 
2638
         *   code body pointer value - we store the underlying code body
2639
         *   for anonymous functions 
2640
         */
2641
        class CTPNCodeBody *codebodyval_;
2642
    } val_;
2643
};
2644
2645
2646
/* ------------------------------------------------------------------------ */
2647
/*
2648
 *   Assignment Types.
2649
 */
2650
2651
enum tc_asitype_t
2652
{
2653
    /* simple assignment: x = 1 */
2654
    TC_ASI_SIMPLE,
2655
2656
    /* add to: x += 1 */
2657
    TC_ASI_ADD,
2658
2659
    /* subtract from: x -= 1 */
2660
    TC_ASI_SUB,
2661
2662
    /* multiply by:  x *= 1 */
2663
    TC_ASI_MUL,
2664
2665
    /* divide by: x /= 1 */
2666
    TC_ASI_DIV,
2667
2668
    /* modulo: x %= 1 */
2669
    TC_ASI_MOD,
2670
2671
    /* bitwise-and with: x &= 1 */
2672
    TC_ASI_BAND,
2673
2674
    /* bitwise-or with: x |= 1 */
2675
    TC_ASI_BOR,
2676
2677
    /* bitwise-xor with: x ^= 1 */
2678
    TC_ASI_BXOR,
2679
2680
    /* shift left: x <<= 1 */
2681
    TC_ASI_SHL,
2682
2683
    /* shift right: x >>= 1 */
2684
    TC_ASI_SHR,
2685
2686
    /* pre-increment */
2687
    TC_ASI_PREINC,
2688
2689
    /* pre-decrement */
2690
    TC_ASI_PREDEC,
2691
2692
    /* post-increment */
2693
    TC_ASI_POSTINC,
2694
2695
    /* post-decrement */
2696
    TC_ASI_POSTDEC
2697
};
2698
2699
2700
/* ------------------------------------------------------------------------ */
2701
/*
2702
 *   Formal parameter type list.  For functions with declared formal
2703
 *   parameter types (such as multi-methods), we use this class to keep the
2704
 *   list of type names in the parameter list.  
2705
 */
2706
class CTcFormalTypeList
2707
{
2708
public:
2709
    CTcFormalTypeList()
2710
    {
2711
        /* no entries in our type list yet */
2712
        head_ = tail_ = 0;
2713
2714
        /* assume this isn't a varargs list */
2715
        varargs_ = FALSE;
2716
    }
2717
2718
    ~CTcFormalTypeList() { }
2719
2720
    /* create the decorated name */
2721
    void decorate_name(CTcToken *decorated_name,
2722
                       const CTcToken *func_base_name);
2723
2724
    /* get the first parameter in the list */
2725
    class CTcFormalTypeEle *get_first() const { return head_; }
2726
2727
    /* add a typed variable to the list */
2728
    void add_typed_param(const CTcToken *tok);
2729
2730
    /* add an untyped variable to the list */
2731
    void add_untyped_param();
2732
2733
    /* add 'n' untyped variables to the list */
2734
    void add_untyped_params(int n)
2735
    {
2736
        while (n-- > 0)
2737
            add_untyped_param();
2738
    }
2739
2740
    /* add a trailing ellispsis (varargs indicator) */
2741
    void add_ellipsis() { varargs_ = TRUE; }
2742
2743
protected:
2744
    /* add a new list element */
2745
    void add(class CTcFormalTypeEle *ele);
2746
2747
    /* add/tail of parameter list */
2748
    class CTcFormalTypeEle *head_, *tail_;
2749
2750
    /* is this a varargs list? */
2751
    int varargs_;
2752
};
2753
2754
/* formal parameter type list entry */
2755
class CTcFormalTypeEle
2756
{
2757
public:
2758
    CTcFormalTypeEle() { name_ = 0; }
2759
    CTcFormalTypeEle(const char *name, size_t len);
2760
    ~CTcFormalTypeEle()
2761
    {
2762
    }
2763
2764
    /* next element in list */
2765
    CTcFormalTypeEle *nxt_;
2766
2767
    /* type name */
2768
    char *name_;
2769
    size_t name_len_;
2770
};
2771
2772
2773
/* ------------------------------------------------------------------------ */
2774
/*
2775
 *   Expression Operator Parsers.  We construct a tree of these operator
2776
 *   parsers so that we can express the expression grammar in a relatively
2777
 *   compact and declarative notation.  
2778
 */
2779
2780
/*
2781
 *   basic operator parser 
2782
 */
2783
class CTcPrsOp
2784
{
2785
public:
2786
    /* 
2787
     *   Parse an expression with this operator.  Logs an error and
2788
     *   returns non-zero if the expression is not valid; on success,
2789
     *   returns zero.
2790
     *   
2791
     *   Fills in *val with the constant value, if any, of the expression.
2792
     *   If the expression does not have a constant value, *val's type
2793
     *   will be set to TC_CVT_UNKNOWN to indicate this.
2794
     *   
2795
     *   Returns a parse node if successful, or null if an error occurs
2796
     *   and the operator parser is unable to make a guess about what was
2797
     *   intended.  
2798
     */
2799
    virtual class CTcPrsNode *parse() const = 0;
2800
};
2801
2802
/*
2803
 *   generic left-associative binary operator
2804
 */
2805
class CTcPrsOpBin: public CTcPrsOp
2806
{
2807
public:
2808
    CTcPrsOpBin()
2809
    {
2810
        /* no left or right subexpression specified */
2811
        left_ = right_ = 0;
2812
2813
        /* as-yet unknown operator token */
2814
        op_tok_ = TOKT_INVALID;
2815
    }
2816
2817
    CTcPrsOpBin(tc_toktyp_t typ)
2818
    {
2819
        /* remember my operator token */
2820
        op_tok_ = typ;
2821
    }
2822
2823
    CTcPrsOpBin(const CTcPrsOp *left, const CTcPrsOp *right, tc_toktyp_t typ)
2824
    {
2825
        /* remember my left and right sub-operators */
2826
        left_ = left;
2827
        right_ = right;
2828
2829
        /* remember my operator token */
2830
        op_tok_ = typ;
2831
    }
2832
2833
    /* parse the binary expression */
2834
    class CTcPrsNode *parse() const;
2835
2836
    /* build a new tree out of our left-hand and right-hand subtrees */
2837
    virtual class CTcPrsNode
2838
        *build_tree(class CTcPrsNode *left,
2839
                    class CTcPrsNode *right) const = 0;
2840
2841
    /* 
2842
     *   Try evaluating a constant result.  If the two values can be
2843
     *   combined with the operator to yield a constant value result,
2844
     *   create a new parse node for the constant value (or update one of
2845
     *   the given subnodes) and return it.  If we can't provide a
2846
     *   constant value, return null.
2847
     *   
2848
     *   By default, we'll indicate that the expression does not have a
2849
     *   valid constant value.  
2850
     */
2851
    virtual class CTcPrsNode
2852
        *eval_constant(class CTcPrsNode *left,
2853
                       class CTcPrsNode *right) const
2854
    {
2855
        /* indicate that we cannot synthesize a constant value */
2856
        return 0;
2857
    }
2858
2859
    /* get/set my token */
2860
    tc_toktyp_t get_op_tok() const { return op_tok_; }
2861
    void set_op_tok(tc_toktyp_t tok) { op_tok_ = tok; }
2862
    
2863
protected:
2864
    /* operator that can be parsed for my left-hand side */
2865
    const CTcPrsOp *left_;
2866
2867
    /* operator that can be parsed for my right-hand side */
2868
    const CTcPrsOp *right_;
2869
2870
    /* my operator token */
2871
    tc_toktyp_t op_tok_;
2872
};
2873
2874
/*
2875
 *   Binary Operator Group.  This is a group of operators at a common
2876
 *   precedence level.  The group has an array of binary operators that
2877
 *   are all at the same level of precedence; we'll evaluate the left
2878
 *   suboperator, then check the token in the input stream against each of
2879
 *   our group's operators, applying the one that matches, if one matches.
2880
 */
2881
class CTcPrsOpBinGroup: public CTcPrsOp
2882
{
2883
public:
2884
    CTcPrsOpBinGroup(const CTcPrsOp *left, const CTcPrsOp *right,
2885
                     const class CTcPrsOpBin *const *ops)
2886
    {
2887
        /* remember my left and right suboperators */
2888
        left_ = left;
2889
        right_ = right;
2890
        
2891
        /* remember the operators in my group */
2892
        ops_ = ops;
2893
    }
2894
2895
    /* parse the expression */
2896
    class CTcPrsNode *parse() const;
2897
2898
protected:
2899
    /* find and apply an operator to the parsed left-hand side */
2900
    int find_and_apply_op(CTcPrsNode **lhs) const;
2901
    
2902
    /* my left and right suboperators */
2903
    const CTcPrsOp *left_;
2904
    const CTcPrsOp *right_;
2905
    
2906
    /* group of binary operators at this precedence level */
2907
    const class CTcPrsOpBin *const *ops_;
2908
};
2909
2910
/*
2911
 *   Binary operator group for comparison operators.  This is a similar to
2912
 *   other binary groups, but also includes the special "is in" and "not
2913
 *   in" operators. 
2914
 */
2915
class CTcPrsOpBinGroupCompare: public CTcPrsOpBinGroup
2916
{
2917
public:
2918
    CTcPrsOpBinGroupCompare(const class CTcPrsOp *left,
2919
                            const class CTcPrsOp *right,
2920
                            const class CTcPrsOpBin *const *ops)
2921
        : CTcPrsOpBinGroup(left, right, ops)
2922
    {
2923
    }
2924
2925
    class CTcPrsNode *parse() const;
2926
2927
protected:
2928
    /* parse the 'in' list portion of the expression */
2929
    class CTPNArglist *parse_inlist() const;
2930
};
2931
2932
/* comma operator */
2933
class CTcPrsOpComma: public CTcPrsOpBin
2934
{
2935
public:
2936
    CTcPrsOpComma(const CTcPrsOp *left, const CTcPrsOp *right)
2937
        : CTcPrsOpBin(left, right, TOKT_COMMA) { }
2938
2939
    /* evaluate constant result */
2940
    class CTcPrsNode
2941
        *eval_constant(class CTcPrsNode *left,
2942
                       class CTcPrsNode *right) const;
2943
2944
    /* build a new tree out of our left-hand and right-hand subtrees */
2945
    class CTcPrsNode
2946
        *build_tree(class CTcPrsNode *left,
2947
                    class CTcPrsNode *right) const;
2948
};
2949
2950
/* logical OR */
2951
class CTcPrsOpOr: public CTcPrsOpBin
2952
{
2953
public:
2954
    CTcPrsOpOr(const CTcPrsOp *left, const CTcPrsOp *right)
2955
        : CTcPrsOpBin(left, right, TOKT_OROR) { }
2956
2957
    /* evaluate constant result */
2958
    class CTcPrsNode
2959
        *eval_constant(class CTcPrsNode *left,
2960
                       class CTcPrsNode *right) const;
2961
2962
    /* build a new tree out of our left-hand and right-hand subtrees */
2963
    class CTcPrsNode
2964
        *build_tree(class CTcPrsNode *left,
2965
                    class CTcPrsNode *right) const;
2966
};
2967
2968
/* logical AND */
2969
class CTcPrsOpAnd: public CTcPrsOpBin
2970
{
2971
public:
2972
    CTcPrsOpAnd(const CTcPrsOp *left, const CTcPrsOp *right)
2973
        : CTcPrsOpBin(left, right, TOKT_ANDAND) { }
2974
2975
    /* evaluate constant result */
2976
    class CTcPrsNode
2977
        *eval_constant(class CTcPrsNode *left,
2978
                       class CTcPrsNode *right) const;
2979
2980
    /* build a new tree out of our left-hand and right-hand subtrees */
2981
    class CTcPrsNode
2982
        *build_tree(class CTcPrsNode *left,
2983
                    class CTcPrsNode *right) const;
2984
};
2985
2986
/* general magnitude comparison operators */
2987
class CTcPrsOpRel: public CTcPrsOpBin
2988
{
2989
public:
2990
    CTcPrsOpRel(tc_toktyp_t typ) : CTcPrsOpBin(typ) { }
2991
    
2992
    /* evaluate constant result */
2993
    class CTcPrsNode
2994
        *eval_constant(class CTcPrsNode *left,
2995
                       class CTcPrsNode *right) const;
2996
2997
protected:
2998
    /*
2999
     *   Get the result true/false value, given the result of the
3000
     *   comparison.  For example, if this is a greater-than operator,
3001
     *   this should return TRUE if comp > 0, FALSE otherwise.  
3002
     */
3003
    virtual int get_bool_val(int comparison_value) const = 0;
3004
};
3005
3006
/* comparison - greater than */
3007
class CTcPrsOpGt: public CTcPrsOpRel
3008
{
3009
public:
3010
    CTcPrsOpGt() : CTcPrsOpRel(TOKT_GT) { }
3011
    
3012
    /* get the boolean value for a comparison sense */
3013
    int get_bool_val(int comp) const { return comp > 0; }
3014
3015
    /* build a new tree out of our left-hand and right-hand subtrees */
3016
    class CTcPrsNode
3017
        *build_tree(class CTcPrsNode *left,
3018
                    class CTcPrsNode *right) const;
3019
};
3020
3021
/* comparison - greater than or equal to */
3022
class CTcPrsOpGe: public CTcPrsOpRel
3023
{
3024
public:
3025
    CTcPrsOpGe() : CTcPrsOpRel(TOKT_GE) { }
3026
3027
    /* get the boolean value for a comparison sense */
3028
    int get_bool_val(int comp) const { return comp >= 0; }
3029
3030
    /* build a new tree out of our left-hand and right-hand subtrees */
3031
    class CTcPrsNode
3032
        *build_tree(class CTcPrsNode *left,
3033
                    class CTcPrsNode *right) const;
3034
};
3035
3036
/* comparison - less than */
3037
class CTcPrsOpLt: public CTcPrsOpRel
3038
{
3039
public:
3040
    CTcPrsOpLt() : CTcPrsOpRel(TOKT_LT) { }
3041
3042
    /* get the boolean value for a comparison sense */
3043
    int get_bool_val(int comp) const { return comp < 0; }
3044
3045
    /* build a new tree out of our left-hand and right-hand subtrees */
3046
    class CTcPrsNode
3047
        *build_tree(class CTcPrsNode *left,
3048
                    class CTcPrsNode *right) const;
3049
};
3050
3051
/* comparison - less than or equal to */
3052
class CTcPrsOpLe: public CTcPrsOpRel
3053
{
3054
public:
3055
    CTcPrsOpLe() : CTcPrsOpRel(TOKT_LE) { }
3056
3057
    /* get the boolean value for a comparison sense */
3058
    int get_bool_val(int comp) const { return comp <= 0; }
3059
3060
    /* build a new tree out of our left-hand and right-hand subtrees */
3061
    class CTcPrsNode
3062
        *build_tree(class CTcPrsNode *left,
3063
                    class CTcPrsNode *right) const;
3064
};
3065
3066
/*
3067
 *   Equality/inequality comparison 
3068
 */
3069
class CTcPrsOpEqComp: public CTcPrsOpBin
3070
{
3071
public:
3072
    CTcPrsOpEqComp(tc_toktyp_t typ) : CTcPrsOpBin(typ) { }
3073
3074
    /* evaluate constant result */
3075
    class CTcPrsNode
3076
        *eval_constant(class CTcPrsNode *left,
3077
                       class CTcPrsNode *right) const;
3078
3079
protected:
3080
    /* get the boolean value to use if the operands are equal */
3081
    virtual int get_bool_val(int ops_equal) const = 0;
3082
};
3083
3084
3085
/*
3086
 *   Equality comparison 
3087
 */
3088
class CTcPrsOpEq: public CTcPrsOpEqComp
3089
{
3090
public:
3091
    /* start out in C mode - use '==' operator by default */
3092
    CTcPrsOpEq()
3093
        : CTcPrsOpEqComp(TOKT_EQEQ) { }
3094
3095
    /* set the current equality operator */
3096
    void set_eq_op(tc_toktyp_t op) { op_tok_ = op; }
3097
    
3098
    /* build a new tree out of our left-hand and right-hand subtrees */
3099
    class CTcPrsNode
3100
        *build_tree(class CTcPrsNode *left,
3101
                    class CTcPrsNode *right) const;
3102
3103
    /* get the boolean value to use if the operands are equal */
3104
    virtual int get_bool_val(int ops_equal) const { return ops_equal; }
3105
};
3106
3107
/*
3108
 *   Inequality comparison 
3109
 */
3110
class CTcPrsOpNe: public CTcPrsOpEqComp
3111
{
3112
public:
3113
    CTcPrsOpNe() : CTcPrsOpEqComp(TOKT_NE) { }
3114
3115
    /* build a new tree out of our left-hand and right-hand subtrees */
3116
    class CTcPrsNode
3117
        *build_tree(class CTcPrsNode *left,
3118
                    class CTcPrsNode *right) const;
3119
3120
    /* get the boolean value to use if the operands are equal */
3121
    virtual int get_bool_val(int ops_equal) const { return !ops_equal; }
3122
};
3123
3124
/*
3125
 *   binary arithmetic operators
3126
 */
3127
class CTcPrsOpArith: public CTcPrsOpBin
3128
{
3129
public:
3130
    CTcPrsOpArith(tc_toktyp_t typ)
3131
        : CTcPrsOpBin(typ) { }
3132
3133
    CTcPrsOpArith(const CTcPrsOp *left, const CTcPrsOp *right,
3134
                  tc_toktyp_t typ)
3135
        : CTcPrsOpBin(left, right, typ) { }
3136
3137
    /* evaluate constant result */
3138
    class CTcPrsNode
3139
        *eval_constant(class CTcPrsNode *left,
3140
                       class CTcPrsNode *right) const;
3141
3142
protected:
3143
    /* calculate the result */
3144
    virtual long calc_result(long val1, long val2) const = 0;
3145
};
3146
3147
/* bitwise OR */
3148
class CTcPrsOpBOr: public CTcPrsOpArith
3149
{
3150
public:
3151
    CTcPrsOpBOr(const CTcPrsOp *left, const CTcPrsOp *right)
3152
        : CTcPrsOpArith(left, right, TOKT_OR) { }
3153
3154
    /* build a new tree out of our left-hand and right-hand subtrees */
3155
    class CTcPrsNode
3156
        *build_tree(class CTcPrsNode *left,
3157
                    class CTcPrsNode *right) const;
3158
3159
protected:
3160
    /* calculate the result */
3161
    virtual long calc_result(long val1, long val2) const
3162
        { return val1 | val2; }
3163
};
3164
3165
/* bitwise XOR */
3166
class CTcPrsOpBXor: public CTcPrsOpArith
3167
{
3168
public:
3169
    CTcPrsOpBXor(const CTcPrsOp *left, const CTcPrsOp *right)
3170
        : CTcPrsOpArith(left, right, TOKT_XOR) { }
3171
3172
    /* build a new tree out of our left-hand and right-hand subtrees */
3173
    class CTcPrsNode
3174
        *build_tree(class CTcPrsNode *left,
3175
                    class CTcPrsNode *right) const;
3176
3177
protected:
3178
    /* calculate the result */
3179
    virtual long calc_result(long val1, long val2) const
3180
        { return val1 ^ val2; }
3181
};
3182
3183
/* bitwise AND */
3184
class CTcPrsOpBAnd: public CTcPrsOpArith
3185
{
3186
public:
3187
    CTcPrsOpBAnd(const CTcPrsOp *left, const CTcPrsOp *right)
3188
        : CTcPrsOpArith(left, right, TOKT_AND) { }
3189
3190
    /* build a new tree out of our left-hand and right-hand subtrees */
3191
    class CTcPrsNode
3192
        *build_tree(class CTcPrsNode *left,
3193
                    class CTcPrsNode *right) const;
3194
3195
protected:
3196
    /* calculate the result */
3197
    virtual long calc_result(long val1, long val2) const
3198
        { return val1 & val2; }
3199
};
3200
3201
/*
3202
 *   shift left 
3203
 */
3204
class CTcPrsOpShl: public CTcPrsOpArith
3205
{
3206
public:
3207
    CTcPrsOpShl() : CTcPrsOpArith(TOKT_SHL) { }
3208
3209
    /* build a new tree out of our left-hand and right-hand subtrees */
3210
    class CTcPrsNode
3211
        *build_tree(class CTcPrsNode *left,
3212
                    class CTcPrsNode *right) const;
3213
3214
protected:
3215
    long calc_result(long a, long b) const { return a << b; }
3216
};
3217
3218
/*
3219
 *   shift right
3220
 */
3221
class CTcPrsOpShr: public CTcPrsOpArith
3222
{
3223
public:
3224
    CTcPrsOpShr() : CTcPrsOpArith(TOKT_SHR) { }
3225
3226
    /* build a new tree out of our left-hand and right-hand subtrees */
3227
    class CTcPrsNode
3228
        *build_tree(class CTcPrsNode *left,
3229
                    class CTcPrsNode *right) const;
3230
3231
protected:
3232
    long calc_result(long a, long b) const { return a >> b; }
3233
};
3234
3235
/*
3236
 *   multiply
3237
 */
3238
class CTcPrsOpMul: public CTcPrsOpArith
3239
{
3240
public:
3241
    CTcPrsOpMul() : CTcPrsOpArith(TOKT_TIMES) { }
3242
3243
    /* build a new tree out of our left-hand and right-hand subtrees */
3244
    class CTcPrsNode
3245
        *build_tree(class CTcPrsNode *left,
3246
                    class CTcPrsNode *right) const;
3247
3248
protected:
3249
    long calc_result(long a, long b) const { return a * b; }
3250
};
3251
3252
/*
3253
 *   divide
3254
 */
3255
class CTcPrsOpDiv: public CTcPrsOpArith
3256
{
3257
public:
3258
    CTcPrsOpDiv()
3259
        : CTcPrsOpArith(TOKT_DIV) { }
3260
3261
    CTcPrsOpDiv(tc_toktyp_t tok)
3262
        : CTcPrsOpArith(tok) { }
3263
3264
    /* build a new tree out of our left-hand and right-hand subtrees */
3265
    class CTcPrsNode
3266
        *build_tree(class CTcPrsNode *left,
3267
                    class CTcPrsNode *right) const;
3268
    
3269
protected:
3270
    long calc_result(long a, long b) const;
3271
};
3272
3273
3274
/*
3275
 *   mod - inherit from divide operator to pick up divide-by-zero checking 
3276
 */
3277
class CTcPrsOpMod: public CTcPrsOpDiv
3278
{
3279
public:
3280
    CTcPrsOpMod() : CTcPrsOpDiv(TOKT_MOD) { }
3281
3282
    /* build a new tree out of our left-hand and right-hand subtrees */
3283
    class CTcPrsNode
3284
        *build_tree(class CTcPrsNode *left,
3285
                    class CTcPrsNode *right) const;
3286
3287
protected:
3288
    long calc_result(long a, long b) const;
3289
};
3290
3291
/*
3292
 *   add 
3293
 */
3294
class CTcPrsOpAdd: public CTcPrsOpArith
3295
{
3296
public:
3297
    CTcPrsOpAdd() : CTcPrsOpArith(TOKT_PLUS) { }
3298
3299
    /* build a new tree out of our left-hand and right-hand subtrees */
3300
    class CTcPrsNode
3301
        *build_tree(class CTcPrsNode *left,
3302
                    class CTcPrsNode *right) const;
3303
3304
    /* evaluate constant result */
3305
    class CTcPrsNode
3306
        *eval_constant(class CTcPrsNode *left,
3307
                       class CTcPrsNode *right) const;
3308
3309
protected:
3310
    long calc_result(long a, long b) const { return a + b; }
3311
};
3312
3313
/*
3314
 *   subtract
3315
 */
3316
class CTcPrsOpSub: public CTcPrsOpArith
3317
{
3318
public:
3319
    CTcPrsOpSub() : CTcPrsOpArith(TOKT_MINUS) { }
3320
3321
    /* build a new tree out of our left-hand and right-hand subtrees */
3322
    class CTcPrsNode
3323
        *build_tree(class CTcPrsNode *left,
3324
                    class CTcPrsNode *right) const;
3325
3326
    /* evaluate constant result */
3327
    class CTcPrsNode
3328
        *eval_constant(class CTcPrsNode *left,
3329
                       class CTcPrsNode *right) const;
3330
3331
protected:
3332
    long calc_result(long a, long b) const { return a - b; }
3333
};
3334
3335
/*
3336
 *   Unary Operators 
3337
 */
3338
class CTcPrsOpUnary: public CTcPrsOp
3339
{
3340
public:
3341
    class CTcPrsNode *parse() const;
3342
3343
    /* 
3344
     *   evaluate a constant subscript expression; returns a constant
3345
     *   parse node expression if the subscript can be evaluated to a
3346
     *   compile-time constant, or null if not 
3347
     */
3348
    static class CTcPrsNode
3349
        *eval_const_subscript(class CTcPrsNode *lhs,
3350
                              class CTcPrsNode *subscript);
3351
3352
    /* 
3353
     *   evaluate a constant NOT expression; returns a constant parse node
3354
     *   expression if the logical negation can be evaluated to a
3355
     *   compile-time constant, or null if not 
3356
     */
3357
    static class CTcPrsNode *eval_const_not(class CTcPrsNode *lhs);
3358
3359
    /* parse a double-quoted string with embedded expressions */
3360
    static class CTcPrsNode *parse_dstr_embed();
3361
3362
    /* parse a list */
3363
    static class CTcPrsNode *parse_list();
3364
3365
    /* parse a primary expression */
3366
    static class CTcPrsNode *parse_primary();
3367
3368
protected:
3369
    /* parse an anonymous function */
3370
    static class CTcPrsNode *parse_anon_func(int short_form);
3371
3372
    /* parse a logical NOT operator */
3373
    static class CTcPrsNode *parse_not(CTcPrsNode *sub);
3374
    
3375
    /* parse a bitwise NOT operator */
3376
    static class CTcPrsNode *parse_bnot(CTcPrsNode *sub);
3377
3378
    /* parse an address-of operator */
3379
    class CTcPrsNode *parse_addr() const;
3380
3381
    /* parse an arithmetic positive operator */
3382
    static class CTcPrsNode *parse_pos(CTcPrsNode *sub);
3383
3384
    /* parse an arithmetic negative operator */
3385
    static class CTcPrsNode *parse_neg(CTcPrsNode *sub);
3386
3387
    /* parse a pre- or post-increment operator */
3388
    static class CTcPrsNode *parse_inc(int pre, CTcPrsNode *sub);
3389
3390
    /* parse a pre- or post-decrement operator */
3391
    static class CTcPrsNode *parse_dec(int pre, CTcPrsNode *sub);
3392
3393
    /* parse a 'new' operator */
3394
    static class CTcPrsNode *parse_new(CTcPrsNode *sub, int is_transient);
3395
3396
    /* parse a 'delete' operator */
3397
    static class CTcPrsNode *parse_delete(CTcPrsNode *sub);
3398
3399
    /* parse a postfix expression */
3400
    static class CTcPrsNode *parse_postfix(int allow_member_expr,
3401
                                           int allow_call_expr);
3402
3403
    /* parse a function or method call */
3404
    static class CTcPrsNode *parse_call(CTcPrsNode *lhs);
3405
3406
    /* parse an argument list */
3407
    static class CTPNArglist *parse_arg_list();
3408
3409
    /* parse a subscript */
3410
    static class CTcPrsNode *parse_subscript(CTcPrsNode *lhs);
3411
3412
    /* parse a member selection ('.' operator) */
3413
    static class CTcPrsNode *parse_member(CTcPrsNode *lhs);
3414
3415
    /* parse an "inherited" expression */
3416
    static class CTcPrsNode *parse_inherited();
3417
3418
    /* parse a "delegated" expression */
3419
    static class CTcPrsNode *parse_delegated();
3420
3421
    /* local symbol enumeration callback for anonymous function setup */
3422
    static void enum_for_anon(void *ctx, class CTcSymbol *sym);
3423
3424
    /* local symbol enumeration for anon function - follow-up */
3425
    static void enum_for_anon2(void *ctx, class CTcSymbol *sym);
3426
};
3427
3428
/*
3429
 *   tertiary conditional operator 
3430
 */
3431
class CTcPrsOpIf: public CTcPrsOp
3432
{
3433
public:
3434
    class CTcPrsNode *parse() const;
3435
};
3436
3437
/*
3438
 *   Assignment operators (including the regular assignment, "="/":=",
3439
 *   plus all calculate-and-assign operators: "+=", "-=", etc) 
3440
 */
3441
class CTcPrsOpAsi: public CTcPrsOp
3442
{
3443
public:
3444
    CTcPrsOpAsi()
3445
    {
3446
        /* start out with the C-mode simple assignment operator */
3447
        asi_op_ = TOKT_EQ;
3448
    }
3449
3450
    /* parse an assignment */
3451
    class CTcPrsNode *parse() const;
3452
3453
    /* set the current simple assignment operator */
3454
    void set_asi_op(tc_toktyp_t tok) { asi_op_ = tok; }
3455
3456
private:
3457
    /* current simple assignment operator */
3458
    tc_toktyp_t asi_op_;
3459
};
3460
3461
#endif /* TCPRS_H */
3462