~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/tcprs.h

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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