~ubuntu-branches/ubuntu/utopic/cdrdao/utopic

« back to all changes in this revision

Viewing changes to pccts/sorcerer/sor.g

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Suffield
  • Date: 2004-06-24 22:33:16 UTC
  • Revision ID: james.westby@ubuntu.com-20040624223316-534onzugaeeyq61j
Tags: upstream-1.1.9
ImportĀ upstreamĀ versionĀ 1.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SORCERER Version 1.00B
 
3
 *
 
4
 * Terence Parr
 
5
 * U of MN, AHPCRC
 
6
 * April 1995
 
7
 */
 
8
 
 
9
#header <<
 
10
    /*  23-Sep-97   thm     Accomodate user who needs to redefine ZZLEXBUFSIZE  */
 
11
 
 
12
#ifndef ZZLEXBUFSIZE
 
13
#define ZZLEXBUFSIZE    8000
 
14
#endif
 
15
  #include "pcctscfg.h"    /* MR20 G. Hobbelt __USE_PROTOS #define */
 
16
        #include "charbuf.h"
 
17
        #include "hash.h"
 
18
        #include "set.h"
 
19
        #include "sor.h"
 
20
        #define AST_FIELDS      \
 
21
                        int token; char text[MaxAtom+1], label[MaxRuleName+1]; \
 
22
                        char *action;           /* if action node, here is ptr to it */ \
 
23
                        char in,out; \
 
24
                        char init_action;       /* set if Action and 1st action of alt */ \
 
25
                        int file; int line; /* set for BLOCK, ALT, nonterm nodes */ \
 
26
                        int upper_range;        /* only if T1..T2 found */      \
 
27
                        GLA *start_state;       /* ptr into GLA for this block */ \
 
28
                        int no_copy;            /* copy input ptr to output ptr? */ \
 
29
                        ListNode *refvars;      /* any ref vars defined for this rule */ \
 
30
                        unsigned char is_root; /* this token is a root #( A ... ) */
 
31
        #define zzcr_ast(node, cur, _tok, _text)        \
 
32
                {(node)->token=_tok; strncpy((node)->text, _text,MaxAtom);}
 
33
        #define USER_ZZSYN
 
34
        #define zzAST_DOUBLE
 
35
        extern int define_num;
 
36
>>
 
37
 
 
38
<<
 
39
/* MR20 G. Hobbelt Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled */
 
40
#if defined(__TURBOC__)
 
41
#pragma warn -aus  /* unused assignment of 'xxx' */
 
42
#endif
 
43
 
 
44
 
 
45
#include "sym.h"
 
46
#include "proto.h"
 
47
>>
 
48
 
 
49
#lexaction <<
 
50
#include "sym.h"
 
51
#include "proto.h"
 
52
 
 
53
int define_num = 0;
 
54
 
 
55
char *
 
56
#ifdef __USE_PROTOS
 
57
scarf_to_end_of_func_call(void)
 
58
#else
 
59
scarf_to_end_of_func_call()
 
60
#endif
 
61
{
 
62
        static char func_call_str[MaxAtom+1];
 
63
        char *p;
 
64
 
 
65
        p = &func_call_str[0];
 
66
 
 
67
more:
 
68
        if ( zzchar==')' ) { *p++ = zzchar; *p++ = '\0'; zzadvance(); return func_call_str; }
 
69
        if ( zzchar=='"' )
 
70
        {
 
71
                *p++ = zzchar; zzadvance();
 
72
                while ( zzchar!='"' )
 
73
                {
 
74
                        if ( zzchar=='\\' ) { *p++ = zzchar; zzadvance(); }
 
75
                        *p++ = zzchar; zzadvance();
 
76
                }
 
77
        }
 
78
        *p++ = zzchar; zzadvance();
 
79
        goto more;
 
80
}
 
81
>>
 
82
 
 
83
<<
 
84
void    /* MR9 23-Sep-97 Eliminate complaint about no return value */
 
85
#ifdef __USE_PROTOS
 
86
lisp( AST *tree, FILE *output )
 
87
#else
 
88
lisp( tree, output )
 
89
AST *tree;
 
90
FILE *output;
 
91
#endif
 
92
{
 
93
        while ( tree != NULL )
 
94
        {
 
95
                if ( tree->down != NULL ) fprintf(output," (");
 
96
                if ( tree->text[0]!='\0' ) {
 
97
                        fprintf(output, " \"");
 
98
                        if ( tree->label[0]!='\0' ) fprintf(output, "%s:", tree->label);
 
99
                        switch ( tree->token ) {
 
100
                                case OPT :
 
101
                                case POS_CLOSURE :
 
102
                                case CLOSURE :
 
103
                                case PRED_OP :
 
104
                                        fprintf(output, "%s", tree->text);
 
105
                                        break;
 
106
                                default :
 
107
                                        fprintf(output, "%s[%s]", zztokens[tree->token], tree->text);
 
108
                        }
 
109
                        fprintf(output, "\"");
 
110
                }
 
111
                else {
 
112
                        fprintf(output, " %s", zztokens[tree->token]);
 
113
                }
 
114
                lisp(tree->down, output);
 
115
                if ( tree->down != NULL ) fprintf(output," )");
 
116
                tree = tree->right;
 
117
        }
 
118
}
 
119
 
 
120
AST *
 
121
#ifdef __USE_PROTOS
 
122
zzmk_ast(AST *node, int token)
 
123
#else
 
124
zzmk_ast(node, token)
 
125
AST *node;
 
126
int token;
 
127
#endif
 
128
{
 
129
        node->token = token;
 
130
    return node;
 
131
}
 
132
 
 
133
AST *
 
134
#ifdef __USE_PROTOS
 
135
read_sor_desc(FILE *f)
 
136
#else
 
137
read_sor_desc(f)
 
138
FILE *f;
 
139
#endif
 
140
{
 
141
        AST *root = NULL;
 
142
 
 
143
        zzline = 1;
 
144
        ANTLR(sordesc(&root), f);
 
145
 
 
146
        if ( found_error ) return NULL;
 
147
 
 
148
        if ( print_guts ) {
 
149
                fprintf(stderr, "Internal Represenation of Tree Grammar:\n");
 
150
                lisp(root, stderr);
 
151
                fprintf(stderr, "\n");
 
152
        }
 
153
 
 
154
        last_valid_token = token_type;
 
155
        end_of_input = token_type++;/* end of input token type is 1 + last real token */
 
156
        epsilon = token_type++;         /* epsilon token type is 2 + last real token */
 
157
        wild_card = token_type++;       /* wild_card_token is 3 + last real token */
 
158
        token_association(end_of_input, "$");
 
159
        token_association(epsilon, "[Ep]");
 
160
        token_association(wild_card, ".");
 
161
 
 
162
        zzdouble_link(root, NULL, NULL);
 
163
        rules = root;
 
164
        if ( root!=NULL ) build_GLA(root);
 
165
 
 
166
        if ( print_guts ) {
 
167
                fprintf(stderr, "Internal Represenation of Grammar Lookahead Automaton:\n");
 
168
                dump_GLAs(root);
 
169
                fprintf(stderr, "\n");
 
170
        }
 
171
        return root;
 
172
}
 
173
>>
 
174
 
 
175
#lexclass STRINGS
 
176
#token RExpr "\""                       << zzmode(START); >>
 
177
#token "\n|\r|\r\n"                     <<                  /* MR16a */
 
178
                                                        zzline++;
 
179
                                                        warn("eoln found in string");
 
180
                                                        zzskip();
 
181
                                                        >>
 
182
#token "\\~[]"                          << zzmore(); >>
 
183
#token "~[\n\r\"\\]+"           << zzmore(); >>     /* MR16a */
 
184
 
 
185
#lexclass ACTION_STRINGS
 
186
#token "\""                                     << zzmode(ACTIONS); zzmore(); >>
 
187
#token "\n|\r|\r\n"                     <<                  /* MR16a */
 
188
                                                        zzline++;
 
189
                                                        warn("eoln found in string (in user action)");
 
190
                                                        zzskip();
 
191
                                                        >>
 
192
#token "\\~[]"                          << zzmore(); >>
 
193
#token "~[\n\r\"\\]+"           << zzmore(); >>     /* MR16a */
 
194
 
 
195
#lexclass ACTION_CHARS
 
196
#token "'"                                      << zzmode(ACTIONS); zzmore(); >>
 
197
#token "\n|\r|\r\n"                     <<                  /* MR16a */
 
198
                                                        zzline++;
 
199
                                                        warn("eoln found in char literal (in user action)");
 
200
                                                        zzskip();
 
201
                                                        >>
 
202
#token "\\~[]"                          << zzmore(); >>
 
203
#token "~[\n\r'\\]+"            << zzmore(); >>     /* MR16a */
 
204
 
 
205
#lexclass ACTION_COMMENTS
 
206
#token "\*/"                            << zzmode(ACTIONS); zzmore(); >>
 
207
#token "\*"                                     << zzmore(); >>
 
208
#token "\n|\r|\r\n"                     << zzline++; zzmore(); >>   /* MR16a */
 
209
#token "~[\n\r\*]+"                     << zzmore(); >>             /* MR16a */
 
210
 
 
211
#lexclass ACTION_CPP_COMMENTS
 
212
#token "\n|\r|\r\n"                     << zzline++; zzmode(ACTIONS); zzmore(); >>  /* MR16a */
 
213
#token "~[\n\r]+"                       << zzmore(); >>                             /* MR16a */
 
214
 
 
215
#lexclass CPP_COMMENTS
 
216
#token "\n|\r|\r\n"                     << zzline++; zzmode(START); zzskip(); >>    /* MR16a */
 
217
#token "~[\n\r]+"                       << zzskip(); >>                             /* MR16a */
 
218
 
 
219
#lexclass COMMENTS
 
220
#token "\*/"                            << zzmode(START); zzskip(); >>
 
221
#token "\*"                                     << zzskip(); >>
 
222
#token "\n|\r|\r\n"                     << zzline++; zzskip(); >>                   /* MR16a */
 
223
#token "~[\n\r\*]+"                     << zzskip(); >>                             /* MR16a */
 
224
 
 
225
#lexclass REFVAR_SCARF          /* everything until a ')' */
 
226
#token "~[\)]+ \)"                      <<{
 
227
                                                        RefVarRec *rf;
 
228
                                                        zzskip();
 
229
                            zzbegexpr[strlen(zzbegexpr)-1] = '\0';
 
230
                                                        rf=refVarRec(zzbegexpr);
 
231
                                                        list_add(&AllRefVars, rf);
 
232
                                                        list_add(&RefVars, rf);
 
233
                            zzmode(ACTIONS); zzmore(); zzreplstr("");
 
234
                                                        }>>
 
235
 
 
236
/*
 
237
 * This lexical class accepts actions of type [..] and <<..>>
 
238
 *
 
239
 * It translates the following special items:
 
240
 *
 
241
 * #[args]      --> "ast_node(args)" add "classname::" for C++, however.
 
242
 * #[]          --> "ast_empty_node()"
 
243
 * #( root, child1, ..., childn )
 
244
                        --> "ast_make(root, child1, ...., childn, NULL)"
 
245
 * #()          --> "NULL"
 
246
 *
 
247
 * Things for reference variables are also recognized:
 
248
 * blah blah
 
249
 *
 
250
 * To escape,
 
251
 *
 
252
 * \]           --> ]
 
253
 * \)           --> )
 
254
 * \$           --> $
 
255
 * \#           --> #
 
256
 *
 
257
 * A stack is used to nest action terminators because they can be nested
 
258
 * like crazy:  << #[#[..],..] >>
 
259
 */
 
260
#lexclass ACTIONS
 
261
#token Action "\>\>"        << /* these do not nest */
 
262
                              zzmode(START);
 
263
                              NLATEXT[0] = ' ';
 
264
                              NLATEXT[1] = ' ';
 
265
                              zzbegexpr[0] = ' ';
 
266
                              zzbegexpr[1] = ' ';
 
267
                                                          if ( zzbufovf ) {
 
268
                                                                found_error = 1;
 
269
                                                                err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
 
270
                                                          }
 
271
                            >>
 
272
#token PassAction "\]"          << if ( topint() == ']' ) {
 
273
                                                                  popint();
 
274
                                                                  if ( istackempty() )  /* terminate action */
 
275
                                                                  {
 
276
                                                                          zzmode(START);
 
277
                                                                          NLATEXT[0] = ' ';
 
278
                                                                          zzbegexpr[0] = ' ';
 
279
                                                                          if ( zzbufovf ) {
 
280
                                                                                found_error = 1;
 
281
                                                                                err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
 
282
                                                                          }
 
283
                                                                  }
 
284
                                                                  else {
 
285
                                                                          /* terminate #[..] */
 
286
                                                                          zzreplstr(")");
 
287
                                                                          zzmore();
 
288
                                                                  }
 
289
                                                           }
 
290
                                                           else if ( topint() == '|' ) { /* end of simple [...] */
 
291
                                                                  popint();
 
292
                                                                  zzmore();
 
293
                                                           }
 
294
                                                           else zzmore();
 
295
                                                        >>
 
296
#token "\n|\r|\r\n"                     << zzline++; zzmore(); >>   /* MR16a */
 
297
#token "\>"                                     << zzmore(); >>
 
298
#token "#[_a-zA-Z][_a-zA-Z0-9]*"
 
299
                                                        <<
 
300
                                                        if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||
 
301
                                                                 strcmp(zzbegexpr, "#else")==0 ||
 
302
                                                                 strcmp(zzbegexpr, "#endif")==0 ||
 
303
                                                                 strcmp(zzbegexpr, "#ifndef")==0 ||
 
304
                                                                 strcmp(zzbegexpr, "#if")==0 ||
 
305
                                                                 strcmp(zzbegexpr, "#define")==0 ||
 
306
                                                                 strcmp(zzbegexpr, "#pragma")==0 ||
 
307
                                                                 strcmp(zzbegexpr, "#undef")==0 ||
 
308
                                                                 strcmp(zzbegexpr, "#import")==0 ||
 
309
                                                                 strcmp(zzbegexpr, "#line")==0 ||
 
310
                                                                 strcmp(zzbegexpr, "#include")==0 ||
 
311
                                                                 strcmp(zzbegexpr, "#error")==0) )
 
312
                                                        {
 
313
                                                                static char buf[100];
 
314
                                                                if ( !transform ) {
 
315
                                                                  warn("#id used in nontransform mode; # ignored");
 
316
                                                                  sprintf(buf, "%s", zzbegexpr+1);
 
317
                                                                }
 
318
                                                                else {
 
319
                                                                        if ( CurRule==NULL )
 
320
                                                                          {warn("#id used in action outside of rule; ignored");}
 
321
                                                                        else if ( strcmp(zzbegexpr+1,CurRule)==0 )
 
322
                                                                                strcpy(buf, "(*_result)");
 
323
                                                                }
 
324
                                                                zzreplstr(buf);
 
325
                                                        }
 
326
                                                        zzmore();
 
327
                                                        >>
 
328
#token "#\[\]"                          <<
 
329
                                                        if ( GenCPP ) zzreplstr("new SORAST");
 
330
                                                        else zzreplstr("ast_empty_node()");
 
331
                                                        zzmore();
 
332
                                                        >>
 
333
#token "#\(\)"                          << zzreplstr("NULL"); zzmore(); >>
 
334
#token "#\["                            <<
 
335
                                                        pushint(']');
 
336
                                                        if ( GenCPP ) zzreplstr("new SORAST(");
 
337
                                                        else zzreplstr("ast_node(");
 
338
                                                        zzmore();
 
339
                                                        >>
 
340
#token "#\("                            <<
 
341
                                                        pushint('}');
 
342
                                                        if ( GenCPP ) zzreplstr("PCCTS_AST::make(");
 
343
                                                        else zzreplstr("ast_make(");
 
344
                                                        zzmore();
 
345
                                                        >>
 
346
#token "#"                                      << zzmore(); >>
 
347
#token "\)"                                     <<
 
348
                                                        if ( istackempty() )
 
349
                                                                zzmore();
 
350
                                                        else if ( topint()==')' ) {
 
351
                                                                popint();
 
352
                                                        }
 
353
                                                        else if ( topint()=='}' ) {
 
354
                                                                popint();
 
355
                                                                /* terminate #(..) */
 
356
                                                                zzreplstr(", NULL)");
 
357
                                                        }
 
358
                                                        zzmore();
 
359
                                                        >>
 
360
#token "\["                                     <<
 
361
                                                        pushint('|');   /* look for '|' to terminate simple [...] */
 
362
                                                        zzmore();
 
363
                                                        >>
 
364
#token "\("                                     <<
 
365
                                                        pushint(')');
 
366
                                                        zzmore();
 
367
                                                        >>
 
368
 
 
369
#token "\\\]"                           << zzreplstr("]");  zzmore(); >>
 
370
#token "\\\)"                           << zzreplstr(")");  zzmore(); >>
 
371
#token "\\>"                            << zzreplstr(">");  zzmore(); >>
 
372
 
 
373
 
 
374
#token "'"                                      << zzmode(ACTION_CHARS); zzmore();>>
 
375
#token "\""                                     << zzmode(ACTION_STRINGS); zzmore();>>
 
376
#token "\\#"                            << zzreplstr("#");  zzmore(); >>
 
377
/*#token "\\\\"                         << zzmore(); >> /* need this for some reason */
 
378
#token "\\~[\]\)>#]"            << zzmore(); >> /* escaped char, always ignore */
 
379
#token "/"                                      << zzmore(); >>
 
380
#token "/\*"                            << zzmode(ACTION_COMMENTS); zzmore(); >>
 
381
#token "\*/"                            << err("Missing /*; found dangling */ in action"); zzmore(); >>
 
382
#token "//"                                     << zzmode(ACTION_CPP_COMMENTS); zzmore(); >>
 
383
 
 
384
#token "\@\("                           <<zzmode(REFVAR_SCARF); zzmore(); zzreplstr("");>>
 
385
 
 
386
#token "\@"                                     <<
 
387
                                                        zzmore(); if ( !GenCPP ) zzreplstr("_parser->");
 
388
                                                        >>
 
389
 
 
390
#token "[a-zA-Z_]+\("           <<
 
391
                                                        if ( (GenCPP && strcmp(zzbegexpr,"ast_scan(")==0) ||
 
392
                                                             (!GenCPP && strcmp(zzbegexpr,"ast_scan(")==0) ) {
 
393
                                                                char *args=scarf_to_end_of_func_call();
 
394
                                                                zzreplstr(cvt_token_str(zzbegexpr, args));
 
395
                                                                zzmore();
 
396
                                                        }
 
397
                                                        else { pushint(')'); zzmore(); }
 
398
                                                        >>
 
399
#token "[a-zA-Z_]+"                     << zzmore(); >>
 
400
#token "~[a-zA-Z_\n\r\)\(\\#\>\]\[\"'/\@]+" << zzmore(); >>     /* MR16a */
 
401
 
 
402
#lexclass START
 
403
#token "[\t\ ]+"                        << zzskip(); >>                         /* Ignore White */
 
404
#token "\n|\r|\n\r"                     << zzline++; zzskip(); >>       /* Track Line # */  /* MR16a */
 
405
#token "\["                 << zzmode(ACTIONS); zzmore();
 
406
                               istackreset();
 
407
                               pushint(']'); >>
 
408
#token "\<\<"               << action_file=CurFile; action_line=zzline;
 
409
                               zzmode(ACTIONS); zzmore();
 
410
                               istackreset();
 
411
                               pushint('>'); >>
 
412
#token "\""                                     << zzmode(STRINGS); zzmore(); >>
 
413
#token "/\*"                            << zzmode(COMMENTS); zzskip(); >>
 
414
#token "\*/"                            << err("Missing /*; found dangling */"); zzskip(); >>
 
415
#token "//"                                     << zzmode(CPP_COMMENTS); zzskip(); >>
 
416
#token "\>\>"                           << err("Missing <<; found dangling \>\>"); zzskip(); >>
 
417
#token Eof                                      "@"
 
418
                                                        <<      /* L o o k  F o r  A n o t h e r  F i l e */
 
419
                                                        {
 
420
                                                        FILE *new_input;
 
421
                                                        new_input = NextFile();
 
422
                                                        if ( new_input != NULL ) {
 
423
                                                                fclose( input );
 
424
                                                                input = new_input;
 
425
                                                                zzrdstream( input );
 
426
                                                                /*zzadvance();  ** Get 1st char of this file */
 
427
                                                                zzskip();       /* Skip the Eof (@) char i.e continue */
 
428
                                                        }
 
429
                                                        }
 
430
                                                        >>
 
431
 
 
432
#token Header           "#header"
 
433
#token Tokdef           "#tokdefs"
 
434
#token BLOCK                    /* used only as place-holder in intermediate tree */
 
435
#token ALT                              /* used only as place-holder in intermediate tree */
 
436
#token LABEL            ":"     /* used only as place-holder in intermediate tree */
 
437
#token OPT                      "\{" /* These are labeled so we can ref them in trees */
 
438
#token POS_CLOSURE      "\+"
 
439
#token CLOSURE          "\*"
 
440
#token WILD                     "."
 
441
#token PRED_OP          "?"
 
442
#token BT                       "#\("
 
443
#token RULE
 
444
#token REFVAR
 
445
 
 
446
#errclass "atomic-element" { WILD NonTerm Token }
 
447
#errclass "rule-header" { PassAction LABEL "\<" "\>" }
 
448
 
 
449
/*
 
450
 * Build trees for a sorcerer description
 
451
 */
 
452
sordesc
 
453
        :       <<int he=0,to=0;>>
 
454
                (       header <<he++;>>
 
455
                |       tokdef <<to++;>>
 
456
                )*
 
457
                <<
 
458
                if ( he==0 && !Inline && !GenCPP ) warnNoFL("missing #header statement");
 
459
                if ( he>1 ) warnNoFL("extra #header statement");
 
460
                if ( to>1 ) warnNoFL("extra #tokdef statement");
 
461
                >>
 
462
                (       Action!
 
463
                        <<list_add(&before_actions, actiondup(LATEXT(1)));>>
 
464
                )*
 
465
                { class_def }
 
466
                (       Action!
 
467
                        <<
 
468
                        if ( CurClassName[0]!='\0' )
 
469
                                list_add(&class_actions, actiondup(LATEXT(1)));
 
470
                        else
 
471
                                list_add(&before_actions, actiondup(LATEXT(1)));
 
472
                        >>
 
473
                )*
 
474
                ( rule )*
 
475
                (       Action!
 
476
                        <<
 
477
                        if ( CurClassName[0]!='\0' )
 
478
                                list_add(&class_actions, actiondup(LATEXT(1)));
 
479
                        else
 
480
                                list_add(&before_actions, actiondup(LATEXT(1)));
 
481
                        >>
 
482
                )*
 
483
                {       "\}"!   // end of class def
 
484
                        <<
 
485
                        if ( CurClassName[0]=='\0' )
 
486
                                err("missing class definition for trailing '}'");
 
487
                        >>
 
488
                }
 
489
                (       Action!
 
490
                        <<list_add(&after_actions, actiondup(LATEXT(1)));>>
 
491
                )*
 
492
                "@"!
 
493
        ;
 
494
        <<found_error=1;>>
 
495
 
 
496
header: "#header"! Action! <<header_action = actiondup(LATEXT(1));>>
 
497
          ;
 
498
        <<found_error=1;>>
 
499
 
 
500
tokdef: "#tokdefs"! RExpr!
 
501
                <<{
 
502
                AST *dumb = NULL;
 
503
                zzantlr_state st; FILE *f; struct zzdlg_state dst;
 
504
                strcpy(tokdefs_file, LATEXT(1));
 
505
                strcpy(tokdefs_file, tokdefs_file+1); /* remove quotes */
 
506
                tokdefs_file[strlen(tokdefs_file)-1] = '\0';
 
507
                zzsave_antlr_state(&st);
 
508
                zzsave_dlg_state(&dst);
 
509
                define_num=0;
 
510
                f = fopen(tokdefs_file, "r");
 
511
                if ( f==NULL ) {found_error=1; err(eMsg1("cannot open token defs file '%s'", tokdefs_file));}
 
512
                else {ANTLRm(enum_file(&dumb), f, PARSE_ENUM_FILE);}
 
513
                zzrestore_antlr_state(&st);
 
514
                zzrestore_dlg_state(&dst);
 
515
                UserDefdTokens = 1;
 
516
                }>>
 
517
          ;
 
518
        <<found_error=1;>>
 
519
 
 
520
class_def!
 
521
        :       "class"
 
522
                (       NonTerm         <<strncpy(CurClassName,LATEXT(1),MaxAtom);>>
 
523
                |       Token           <<strncpy(CurClassName,LATEXT(1),MaxAtom);>>
 
524
                )
 
525
                <<if ( !GenCPP ) { err("class meta-op used without C++ option"); }>>
 
526
                "\{"
 
527
        ;
 
528
 
 
529
/*
 
530
 * Create a rule tree:
 
531
 *
 
532
 *  NonTerm[arg_action, ret_val_action]
 
533
 *      |
 
534
 *      v
 
535
 *    block
 
536
 */
 
537
rule:   <<SymEntry *p; int trouble=0, no_copy=0;>>
 
538
                NonTerm^
 
539
                <<
 
540
                #0->file = CurFile;
 
541
                #0->line = zzline;
 
542
                CurRule = $1.text;
 
543
                p = (SymEntry *) hash_get(symbols, $1.text);
 
544
                if ( p==NULL ) {
 
545
                        p = (SymEntry *) hash_add(symbols, $1.text, (Entry *) newSymEntry($1.text));
 
546
                        p->token = NonTerm;
 
547
                        p->defined = 1;
 
548
                        p->definition = #0;
 
549
                }
 
550
                else if ( p->token != NonTerm ) {
 
551
                        err(eMsg2("rule definition clashes with %s definition: '%s'", zztokens[p->token], p->str));
 
552
                        trouble = 1;
 
553
                }
 
554
                else {
 
555
                        if ( p->defined ) {
 
556
                                trouble = 1;
 
557
                                err(eMsg1("rule multiply defined: '%s'", $1.text));
 
558
                        }
 
559
                        else {
 
560
                                p->defined = 1;
 
561
                                p->definition = #0;
 
562
                        }
 
563
                }
 
564
                >>
 
565
                { "!"! <<if (!trouble) #0->no_copy=no_copy=1;>> }
 
566
                (       { "\<"! } PassAction!   <<if (!trouble) p->args = actiondup(LATEXT(1));>>
 
567
                |
 
568
                )
 
569
                {       "\>"! PassAction!               <<if (!trouble) p->rt = actiondup(LATEXT(1));>>
 
570
                }
 
571
                ":"!
 
572
                block[no_copy]
 
573
                ";"!
 
574
                <<
 
575
                if ( !trouble ) #0->refvars = RefVars;
 
576
                RefVars=NULL;
 
577
                >>
 
578
                <<
 
579
                if ( trouble ) #0 = NULL;
 
580
                CurRule = NULL;
 
581
                >>
 
582
        ;
 
583
        <<found_error=1;>>
 
584
 
 
585
/* Create a tree for a block:
 
586
 *
 
587
 *  BLOCK
 
588
 *    |
 
589
 *    v
 
590
 *   alt1 ---> alt2 ---> ... ---> altn
 
591
 */
 
592
block[int no_copy]
 
593
        :       <<int line=zzline, file=CurFile;>>
 
594
                alt[$no_copy]
 
595
                (       "\|"! alt[$no_copy]
 
596
                )*
 
597
                <<
 
598
                #0 = #( #[BLOCK], #0 );
 
599
                #0->file = file;
 
600
                #0->line = line;
 
601
                >>
 
602
        ;
 
603
        <<found_error=1;>>
 
604
 
 
605
/* Create a tree for an alternative:
 
606
 *
 
607
 *  ALT
 
608
 *   |
 
609
 *   v
 
610
 *  e1 ---> e2 ---> ... ---> en
 
611
 */
 
612
alt[int no_copy]
 
613
                :       <<int line=zzline, file=CurFile; int local_no_copy=0;>>
 
614
                        { "!"! <<local_no_copy=1;>> }
 
615
                        {
 
616
                                (       labeled_element[$no_copy||local_no_copy]
 
617
                                |       element[$no_copy||local_no_copy]
 
618
                                |       tree[$no_copy||local_no_copy]
 
619
                                )+
 
620
                        }
 
621
                        <<
 
622
                        #0 = #( #[ALT], #0 );
 
623
                        #0->file = file;
 
624
                        #0->line = line;
 
625
                        >>
 
626
        ;
 
627
        <<found_error=1;>>
 
628
 
 
629
/* a rule ref looks like:
 
630
 *
 
631
 *   NonTerm
 
632
 *       |
 
633
 *       v
 
634
 *   arg_action ---> ret_val_action
 
635
 *
 
636
 * Blocks that have a suffix look like this:
 
637
 *
 
638
 *     OP
 
639
 *     |
 
640
 *     v
 
641
 *   block
 
642
 *
 
643
 * Optional blocks look like:
 
644
 *
 
645
 *    OPT
 
646
 *     |
 
647
 *     v
 
648
 *   block
 
649
 *
 
650
 * Predicates are like actions except they have a root: #( PRED_OP Action )
 
651
 */
 
652
element[int no_copy]
 
653
        :       <</**** SymEntry *p; **** MR10 ****/ int file,line; int local_no_copy=0;>>
 
654
                token[$no_copy]
 
655
        |       <<file = CurFile; line=zzline;>>
 
656
                NonTerm^
 
657
                { "!"! <<local_no_copy = 1;>> }
 
658
                { { "\<"! } PassAction <<#0->in = 1;>> }
 
659
                { "\>"! PassAction <<#0->out = 1;>> }
 
660
                <<#0->file = file; #0->line=line;>>
 
661
                <<#0->no_copy = $no_copy || local_no_copy;>>
 
662
        |       <<file = CurFile; line=zzline;>>
 
663
                Action          <<#1->action = actiondup(LATEXT(1));>>
 
664
                { "?"^ }        <<#0->file = file; #0->line=line;>>
 
665
        |       <<file = CurFile; line=zzline;>>
 
666
                "\("! block[$no_copy] "\)"!
 
667
                (       "\*"^
 
668
                |       "\+"^
 
669
                |       "?"^    <<found_guess_block=1;>>
 
670
                |
 
671
                )
 
672
                <<#0->file = file; #0->line=line;>>
 
673
        |       "\{"^ block[$no_copy] "\}"!
 
674
        |       <<file = CurFile; line=zzline;>>
 
675
                "."
 
676
                { "!"! <<local_no_copy = 1;>> }
 
677
                <<#0->no_copy = $no_copy || local_no_copy;>>
 
678
                <<#0->file = file; #0->line=line;>>
 
679
        ;
 
680
        <<found_error=1;>>
 
681
 
 
682
/* labels on an element look like: #( LABEL element ) */
 
683
labeled_element[int no_copy]
 
684
        :       <<Attrib label; int file,line; SymEntry *s; int local_no_copy=0;>>
 
685
                (       Token!          <<label = $1;>>
 
686
                |       NonTerm!        <<label = $1;>>
 
687
                )
 
688
                <<
 
689
                s = (SymEntry *) hash_get(symbols, label.text);
 
690
                if ( s==NULL ) {
 
691
                        s = (SymEntry *) hash_add(symbols, label.text, (Entry *) newSymEntry(label.text));
 
692
                        s->token = LABEL;
 
693
                }
 
694
                else if ( s->token!=LABEL ) {
 
695
                        err(eMsg2("label definition clashes with %s definition: '%s'", zztokens[s->token], label.text));
 
696
                }
 
697
                >>
 
698
                ":"!                            
 
699
                (       <<file = CurFile; line=zzline;>>
 
700
                        token[$no_copy]         <<strcpy(#1->label, label.text);>>
 
701
                        <<#0->file = file; #0->line=line;>>
 
702
                |       <<file = CurFile; line=zzline;>>
 
703
                        NonTerm^        <<strcpy(#1->label, label.text);>>
 
704
                        { "!"! <<local_no_copy = 1;>> }
 
705
                        { { "\<"! } PassAction <<#0->in = 1;>> }
 
706
                        { "\>"! PassAction <<#0->out = 1;>> }
 
707
                        <<#0->file = file; #0->line=line;>>
 
708
                        <<#0->no_copy = $no_copy || local_no_copy;>>
 
709
                |       <<file = CurFile; line=zzline;>>
 
710
                        "."                     <<strcpy(#1->label, label.text);>>
 
711
                        { "!"! <<local_no_copy = 1;>> }
 
712
                        <<#0->no_copy = $no_copy || local_no_copy;>>
 
713
                        <<#0->file = file; #0->line=line;>>
 
714
                |       ("\|" | ";" | PassAction | Action | Eof | "\(" | "\{" | "\)" | "\}" | "#\(")
 
715
                        <<
 
716
                        err("cannot label this grammar construct");
 
717
                        found_error = 1;
 
718
                        >>
 
719
                )
 
720
        ;
 
721
        <<found_error=1;>>
 
722
 
 
723
token[int no_copy]
 
724
        :       <<SymEntry *p; int file, line; int local_no_copy=0;>>
 
725
                <<file = CurFile; line=zzline;>>
 
726
                Token
 
727
                <<#0->file = file; #0->line=line;>>
 
728
                <<define_token($1.text);>>
 
729
                {       ".."! Token!
 
730
                        { "!"! <<local_no_copy=1;>>}
 
731
                        <<
 
732
                        if ( !UserDefdTokens ) {
 
733
                                err("range operator is illegal without #tokdefs directive");
 
734
                        }
 
735
                        else {
 
736
                                p = define_token($2.text);
 
737
                                require(p!=NULL, "token: hash table is broken");
 
738
                                #0->upper_range = p->token_type;
 
739
                        }
 
740
                        >>
 
741
                |       "!"! <<local_no_copy=1;>>
 
742
                }
 
743
                <<#0->no_copy = $no_copy||local_no_copy;>>
 
744
        ;
 
745
 
 
746
/* A tree description looks like:
 
747
 *
 
748
 *   BT
 
749
 *   |
 
750
 *   v
 
751
 *  root ---> sibling1 ---> ... ---> siblingn
 
752
 */
 
753
tree[int no_copy]
 
754
        :       <<Attrib label; SymEntry *p, *s; int local_no_copy=0; AST *t=NULL;>>
 
755
                "#\("!
 
756
                (       Token^ <<t=#1;>>
 
757
                        <<define_token($1.text);>>
 
758
                        {       ".."! Token!    /* inline rather than 'token' because must be root */
 
759
                                { "!"! <<local_no_copy=1;>>}
 
760
                                <<
 
761
                                if ( !UserDefdTokens ) {
 
762
                                        err("range operator is illegal without #tokdefs directive");
 
763
                                }
 
764
                                else {
 
765
                                        p = define_token($2.text);
 
766
                                        require(p!=NULL, "element: hash table is broken");
 
767
                                        t->upper_range = p->token_type;
 
768
                                }
 
769
                                >>
 
770
                        |       "!"! <<local_no_copy=1;>>
 
771
                        }
 
772
                        <<t->no_copy = $no_copy||local_no_copy; t->is_root = 1;>>
 
773
                |       "."^
 
774
                        { "!"! <<local_no_copy = 1;>> }
 
775
                        <<#1->no_copy = $no_copy || local_no_copy; #1->is_root = 1;>>
 
776
                |       (       Token!          <<label = $1;>>
 
777
                        |       NonTerm!        <<label = $1;>>
 
778
                        )
 
779
                        <<
 
780
                        s = (SymEntry *) hash_get(symbols, label.text);
 
781
                        if ( s==NULL ) {
 
782
                                s = (SymEntry *) hash_add(symbols, label.text, (Entry *) newSymEntry(label.text));
 
783
                                s->token = LABEL;
 
784
                        }
 
785
                        else if ( s->token!=LABEL ) {
 
786
                                err(eMsg2("label definition clashes with %s definition: '%s'", zztokens[s->token], label.text));
 
787
                        }
 
788
                        >>
 
789
                        ":"!
 
790
                        (       Token^          <<strcpy(#1->label, label.text); t = #1;>>
 
791
                                <<define_token($1.text);>>
 
792
                                {       ".."! Token!    /* inline rather than 'token' because must be root */
 
793
                                        { "!"! <<local_no_copy=1;>>}
 
794
                                        <<
 
795
                                        if ( !UserDefdTokens ) {
 
796
                                                err("range operator is illegal without #tokdefs directive");
 
797
                                        }
 
798
                                        else {
 
799
                                                p = define_token($2.text);
 
800
                                                require(p!=NULL, "element: hash table is broken");
 
801
                                                t->upper_range = p->token_type;
 
802
                                        }
 
803
                                        >>
 
804
                                |       "!"! <<local_no_copy=1;>>
 
805
                                }
 
806
                                <<t->no_copy = $no_copy||local_no_copy;>>
 
807
                        |       "."^ <<strcpy(#1->label, label.text);>>
 
808
                                { "!"! <<local_no_copy = 1;>> }
 
809
                                <<#1->no_copy = $no_copy || local_no_copy;>>
 
810
                        )
 
811
                        <<t->is_root = 1;>>
 
812
                )
 
813
                ( labeled_element[$no_copy] | element[$no_copy] | tree[$no_copy] )*
 
814
                "\)"!
 
815
        ;
 
816
        <<found_error=1;>>
 
817
 
 
818
#token NonTerm                  "[a-z] [A-Za-z0-9_]*"
 
819
#token Token                    "[A-Z] [A-Za-z0-9_]*"
 
820
#token "#[A-Za-z0-9_]*" <<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>
 
821
 
 
822
                     /* # t o k d e f s  s t u f f */
 
823
 
 
824
#lexclass TOK_DEF_COMMENTS
 
825
#token "\*/"                            << zzmode(PARSE_ENUM_FILE); zzmore(); >>
 
826
#token "\*"                                     << zzmore(); >>
 
827
#token "\n|\r|\r\n"                     << zzline++; zzmore(); >>   /* MR16a */
 
828
#token "~[\n\r\*]+"                     << zzmore(); >>             /* MR16a */
 
829
 
 
830
#lexclass TOK_DEF_CPP_COMMENTS
 
831
#token "\n|\r|\r\n"                     << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); >> /* MR16a */
 
832
#token "~[\n\r]+"                       << zzskip(); >>                                    /* MR16a */
 
833
 
 
834
#lexclass PARSE_ENUM_FILE
 
835
 
 
836
#token "[\t\ ]+"                        << zzskip(); >>                         /* Ignore White */
 
837
#token "\n|\r|\r\n"                     << zzline++; zzskip(); >>       /* Track Line # */  /* MR16a */
 
838
#token "//"                                     << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >>
 
839
#token "/\*"                            << zzmode(TOK_DEF_COMMENTS); zzmore(); >>
 
840
#token "#ifndef"                        <<  >>
 
841
#token "#ifdef"                         << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
 
842
#token "#else"                          << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
 
843
#token "#define"                        <<
 
844
                                                        >>
 
845
#token "#endif"                         << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
 
846
#token "@"                                      << /*zzmode(START); zzskip();*/ >>
 
847
 
 
848
enum_file!
 
849
        :       <<SymEntry *p=NULL;>>
 
850
                {       "#ifndef" ID
 
851
                        {       "#define" ID /* ignore if it smells like a gate */
 
852
                                /* First #define after the first #ifndef (if any) is ignored */
 
853
                        }
 
854
                }
 
855
                ( enum_def )+
 
856
        |       defines
 
857
        |
 
858
        ;
 
859
 
 
860
defines!
 
861
        :       <<int maxt= -1; /**** char *t; **** MR10 ****/ SymEntry *p; int ignore=0;>>
 
862
                (
 
863
                        "#define" ID
 
864
                        <<
 
865
                        p = (SymEntry *) hash_get(symbols, $2.text);
 
866
                        if ( p==NULL ) {
 
867
                                p = (SymEntry *) hash_add(symbols, $2.text,
 
868
                                                                                  (Entry *) newSymEntry($2.text));
 
869
                                require(p!=NULL, "can't add to sym tab");
 
870
                                p->token = Token;
 
871
                                list_add(&token_list, (void *)p);
 
872
                                set_orel(p->token_type, &referenced_tokens);
 
873
                        }
 
874
                        else
 
875
                        {
 
876
                                err(eMsg1("redefinition of token %s; ignored",$2.text));
 
877
                                ignore = 1;
 
878
                        }
 
879
                        >>
 
880
                        INT
 
881
                        <<
 
882
                        if ( !ignore ) {
 
883
                                p->token_type = atoi($3.text);
 
884
                                token_association(p->token_type, p->str);
 
885
/*                              fprintf(stderr, "#token %s=%d\n", p->str, p->token_type);*/
 
886
                                if ( p->token_type>maxt ) maxt=p->token_type;
 
887
                                ignore = 0;
 
888
                        }
 
889
                        >>
 
890
                )+
 
891
                <<token_type = maxt + 1;>>      /* record max defined token */
 
892
        ;
 
893
 
 
894
enum_def!
 
895
        :       <<int maxt = -1, v= -1; /**** char *t; **** MR10 ****/ SymEntry *p; int ignore=0;>>
 
896
                "enum" {ID}
 
897
                "\{"
 
898
                        ID
 
899
                        <<
 
900
                        p = (SymEntry *) hash_get(symbols, $4.text);
 
901
                        if ( p==NULL ) {
 
902
                                p = (SymEntry *) hash_add(symbols, $4.text,
 
903
                                                                                  (Entry *) newSymEntry($4.text));
 
904
                                require(p!=NULL, "can't add to sym tab");
 
905
                                p->token = Token;
 
906
                                list_add(&token_list, (void *)p);
 
907
                                set_orel(p->token_type, &referenced_tokens);
 
908
                        }
 
909
                        else
 
910
                        {
 
911
                                err(eMsg1("redefinition of token %s; ignored",$4.text));
 
912
                                ignore = 1;
 
913
                        }
 
914
                        >>
 
915
                        (       "=" INT <<v=atoi($2.text);>>
 
916
                        |                       <<v++;>>
 
917
                        )
 
918
                        <<
 
919
                        if ( !ignore ) {
 
920
/*                              fprintf(stderr, "#token %s=%d\n", p->str, v);*/
 
921
                                if ( v>maxt ) maxt=v;
 
922
                                p->token_type = v;
 
923
                                token_association(p->token_type, p->str);
 
924
                                ignore = 0;
 
925
                        }
 
926
                        >>
 
927
                        (       ","
 
928
                { "DLGminToken" { "=" INT }          /* 1.33MR6 compatibility */
 
929
                | "DLGmaxToken" { "=" INT }          /* 1.33MR6 compatibility */
 
930
                                |       ID
 
931
                                        <<
 
932
                                        p = (SymEntry *) hash_get(symbols, $1.text);
 
933
                                        if ( p==NULL ) {
 
934
                                                p = (SymEntry *) hash_add(symbols, $1.text,
 
935
                                                                                                  (Entry *) newSymEntry($1.text));
 
936
                                                require(p!=NULL, "can't add to sym tab");
 
937
                                                p->token = Token;
 
938
                                                list_add(&token_list, (void *)p);
 
939
                                                set_orel(p->token_type, &referenced_tokens);
 
940
                                        }
 
941
                                        else
 
942
                                        {
 
943
                                                err(eMsg1("redefinition of token %s; ignored",$1.text));
 
944
                                                ignore = 1;
 
945
                                        }
 
946
                                        >>
 
947
                                        (       "=" INT <<v=atoi($2.text);>>
 
948
                                        |                       <<v++;>>
 
949
                                        )
 
950
                                        <<
 
951
                                        if ( !ignore ) {
 
952
/*                                              fprintf(stderr, "#token %s=%d\n", p->str, v);*/
 
953
                                                if ( v>maxt ) maxt=v;
 
954
                                                p->token_type = v;
 
955
                                                token_association(p->token_type, p->str);
 
956
                                                ignore = 0;
 
957
                                        }
 
958
                                        >>
 
959
                                }
 
960
                        )*
 
961
                "\}"
 
962
                ";"
 
963
                <<token_type = maxt + 1;>>      /* record max defined token */
 
964
        ;
 
965
 
 
966
#token INT      "[0-9]+"
 
967
#token ID       "[a-zA-Z_][_a-zA-Z0-9]*"
 
968
 
 
969
#lexclass START
 
970
 
 
971
<<
 
972
/* SORCERER-specific syntax error message generator
 
973
 * (define USER_ZZSYN when compiling so don't get 2 definitions)
 
974
 */
 
975
void
 
976
#ifdef __USE_PROTOS
 
977
zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text)
 
978
#else
 
979
zzsyn(text, tok, egroup, eset, etok, k, bad_text)
 
980
char *text, *egroup, *bad_text;
 
981
int tok;
 
982
int etok;
 
983
int k;
 
984
SetWordType *eset;
 
985
#endif
 
986
{
 
987
        fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
 
988
        fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
 
989
        if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
 
990
        if ( k==1 ) fprintf(stderr, " missing");
 
991
        else
 
992
        {
 
993
                fprintf(stderr, "; \"%s\" not", bad_text);
 
994
                if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
 
995
        }
 
996
        if ( zzset_deg(eset)>0 ) zzedecode(eset);
 
997
        else fprintf(stderr, " %s", zztokens[etok]);
 
998
        if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
 
999
        fprintf(stderr, "\n");
 
1000
}
 
1001
 
 
1002
SymEntry *
 
1003
#ifdef __USE_PROTOS
 
1004
define_token(char *text)
 
1005
#else
 
1006
define_token(text)
 
1007
char *text;
 
1008
#endif
 
1009
{
 
1010
        SymEntry *p;
 
1011
 
 
1012
        p = (SymEntry *) hash_get(symbols, text);
 
1013
        if ( p==NULL ) {
 
1014
                if ( UserDefdTokens ) {
 
1015
                        err(eMsg1("implicit token definition of '%s' not allowed with #tokdefs",text));
 
1016
                }
 
1017
                p = (SymEntry *) hash_add(symbols, text, (Entry *) newSymEntry(text));
 
1018
                p->token = Token;
 
1019
                p->token_type = token_type++;
 
1020
                token_association(p->token_type, p->str);
 
1021
                list_add(&token_list, (void *)p);
 
1022
                set_orel(p->token_type, &referenced_tokens);
 
1023
        }
 
1024
        else {
 
1025
                if ( p->token!=Token )
 
1026
                        err(eMsg2("token definition clashes with %s definition: '%s'", zztokens[p->token], text));
 
1027
        }
 
1028
        return p;
 
1029
}
 
1030
>>