~ubuntu-branches/ubuntu/raring/weka/raring

« back to all changes in this revision

Viewing changes to weka/core/parser/java_cup/production.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner, Soeren Sonnenburg, Torsten Werner
  • Date: 2008-08-10 21:27:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080810212705-tr8etpnkdx2ziktp
Tags: 3.5.8-1
[ Soeren Sonnenburg ]
* Bump Standards Version to 3.8.0.
* Remove references to non-free Java in debian/copyright.

[ Torsten Werner ]
* new upstream release
* Switch to openjdk-6.
* Move package to main.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * STANDARD ML OF NEW JERSEY COPYRIGHT NOTICE, LICENSE AND DISCLAIMER.
 
3
 * 
 
4
 * Copyright (c) 1989-1998 by Lucent Technologies
 
5
 * 
 
6
 * Permission to use, copy, modify, and distribute this software and its
 
7
 * documentation for any purpose and without fee is hereby granted, provided
 
8
 * that the above copyright notice appear in all copies and that both the
 
9
 * copyright notice and this permission notice and warranty disclaimer appear
 
10
 * in supporting documentation, and that the name of Lucent Technologies, Bell
 
11
 * Labs or any Lucent entity not be used in advertising or publicity pertaining
 
12
 * to distribution of the software without specific, written prior permission.
 
13
 *
 
14
 * Lucent disclaims all warranties with regard to this software, including all
 
15
 * implied warranties of merchantability and fitness. In no event shall Lucent
 
16
 * be liable for any special, indirect or consequential damages or any damages
 
17
 * whatsoever resulting from loss of use, data or profits, whether in an action
 
18
 * of contract, negligence or other tortious action, arising out of or in
 
19
 * connection with the use or performance of this software. 
 
20
 *
 
21
 * Taken from this URL:
 
22
 * http://www.smlnj.org/license.html
 
23
 * 
 
24
 * This license is compatible with the GNU GPL (see section "Standard ML of New
 
25
 * Jersey Copyright License"):
 
26
 * http://www.gnu.org/licenses/license-list.html#StandardMLofNJ
 
27
 */
 
28
 
 
29
/*
 
30
 * Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian
 
31
 */
 
32
 
 
33
package weka.core.parser.java_cup;
 
34
 
 
35
import java.util.Hashtable;
 
36
import java.util.Enumeration;
 
37
 
 
38
/** This class represents a production in the grammar.  It contains
 
39
 *  a LHS non terminal, and an array of RHS symbols.  As various 
 
40
 *  transformations are done on the RHS of the production, it may shrink.
 
41
 *  As a result a separate length is always maintained to indicate how much
 
42
 *  of the RHS array is still valid.<p>
 
43
 * 
 
44
 *  I addition to construction and manipulation operations, productions provide
 
45
 *  methods for factoring out actions (see  remove_embedded_actions()), for
 
46
 *  computing the nullability of the production (i.e., can it derive the empty
 
47
 *  string, see check_nullable()), and operations for computing its first
 
48
 *  set (i.e., the set of terminals that could appear at the beginning of some
 
49
 *  string derived from the production, see check_first_set()).
 
50
 * 
 
51
 * @see     weka.core.parser.java_cup.production_part
 
52
 * @see     weka.core.parser.java_cup.symbol_part
 
53
 * @see     weka.core.parser.java_cup.action_part
 
54
 * @version last updated: 7/3/96
 
55
 * @author  Frank Flannery
 
56
 */
 
57
 
 
58
public class production {
 
59
 
 
60
  /*-----------------------------------------------------------*/
 
61
  /*--- Constructor(s) ----------------------------------------*/
 
62
  /*-----------------------------------------------------------*/
 
63
 
 
64
  /** Full constructor.  This constructor accepts a LHS non terminal,
 
65
   *  an array of RHS parts (including terminals, non terminals, and 
 
66
   *  actions), and a string for a final reduce action.   It does several
 
67
   *  manipulations in the process of  creating a production object.
 
68
   *  After some validity checking it translates labels that appear in
 
69
   *  actions into code for accessing objects on the runtime parse stack.
 
70
   *  It them merges adjacent actions if they appear and moves any trailing
 
71
   *  action into the final reduce actions string.  Next it removes any
 
72
   *  embedded actions by factoring them out with new action productions.  
 
73
   *  Finally it assigns a unique index to the production.<p>
 
74
   *
 
75
   *  Factoring out of actions is accomplished by creating new "hidden"
 
76
   *  non terminals.  For example if the production was originally: <pre>
 
77
   *    A ::= B {action} C D
 
78
   *  </pre>
 
79
   *  then it is factored into two productions:<pre>
 
80
   *    A ::= B X C D
 
81
   *    X ::= {action}
 
82
   *  </pre> 
 
83
   *  (where X is a unique new non terminal).  This has the effect of placing
 
84
   *  all actions at the end where they can be handled as part of a reduce by
 
85
   *  the parser.
 
86
   */
 
87
  public production(
 
88
    non_terminal    lhs_sym, 
 
89
    production_part rhs_parts[], 
 
90
    int             rhs_l,
 
91
    String          action_str)
 
92
    throws internal_error
 
93
    {
 
94
      int         i;
 
95
      action_part tail_action;
 
96
      String declare_str;
 
97
      int rightlen = rhs_l;
 
98
 
 
99
      /* remember the length */
 
100
      if (rhs_l >= 0)
 
101
        _rhs_length = rhs_l;
 
102
      else if (rhs_parts != null)
 
103
        _rhs_length = rhs_parts.length;
 
104
      else
 
105
        _rhs_length = 0;
 
106
        
 
107
      /* make sure we have a valid left-hand-side */
 
108
      if (lhs_sym == null) 
 
109
        throw new internal_error(
 
110
          "Attempt to construct a production with a null LHS");
 
111
 
 
112
      /* I'm not translating labels anymore, I'm adding code to declare
 
113
         labels as valid variables.  This way, the users code string is
 
114
         untouched 
 
115
         6/96 frankf */
 
116
 
 
117
      /* check if the last part of the right hand side is an action.  If
 
118
         it is, it won't be on the stack, so we don't want to count it 
 
119
         in the rightlen.  Then when we search down the stack for a
 
120
         Symbol, we don't try to search past action */
 
121
 
 
122
      if (rhs_l > 0) {
 
123
        if (rhs_parts[rhs_l - 1].is_action()) {
 
124
          rightlen = rhs_l - 1;
 
125
        } else {
 
126
          rightlen = rhs_l;
 
127
        }
 
128
      }
 
129
 
 
130
      /* get the generated declaration code for the necessary labels. */
 
131
      declare_str = declare_labels(
 
132
                    rhs_parts, rightlen, action_str);
 
133
 
 
134
      if (action_str == null) 
 
135
        action_str = declare_str;
 
136
      else 
 
137
        action_str = declare_str + action_str;            
 
138
 
 
139
      /* count use of lhs */
 
140
      lhs_sym.note_use();
 
141
 
 
142
      /* create the part for left-hand-side */
 
143
      _lhs = new symbol_part(lhs_sym);
 
144
 
 
145
      /* merge adjacent actions (if any) */
 
146
      _rhs_length = merge_adjacent_actions(rhs_parts, _rhs_length);
 
147
 
 
148
      /* strip off any trailing action */
 
149
      tail_action = strip_trailing_action(rhs_parts, _rhs_length);
 
150
      if (tail_action != null) _rhs_length--;
 
151
 
 
152
      /* Why does this run through the right hand side happen
 
153
         over and over?  here a quick combination of two 
 
154
         prior runs plus one I wanted of my own
 
155
         frankf 6/25/96 */
 
156
      /* allocate and copy over the right-hand-side */
 
157
      /* count use of each rhs symbol */
 
158
      _rhs = new production_part[_rhs_length];
 
159
      for (i=0; i<_rhs_length; i++) {
 
160
        _rhs[i] = rhs_parts[i];
 
161
        if (!_rhs[i].is_action()) {
 
162
          ((symbol_part)_rhs[i]).the_symbol().note_use();
 
163
          if (((symbol_part)_rhs[i]).the_symbol() instanceof terminal) {
 
164
            _rhs_prec = 
 
165
              ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_num();
 
166
            _rhs_assoc = 
 
167
              ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_side();
 
168
          }
 
169
        }
 
170
      }
 
171
 
 
172
      /*now action string is really declaration string, so put it in front!
 
173
        6/14/96 frankf */
 
174
      if (action_str == null) action_str = "";
 
175
      if (tail_action != null && tail_action.code_string() != null)
 
176
        action_str = action_str + "\t\t" +  tail_action.code_string();
 
177
 
 
178
      /* stash the action */
 
179
      _action = new action_part(action_str);
 
180
 
 
181
      /* rewrite production to remove any embedded actions */
 
182
      remove_embedded_actions();
 
183
 
 
184
      /* assign an index */
 
185
      _index = next_index++;
 
186
 
 
187
      /* put us in the global collection of productions */
 
188
      _all.put(new Integer(_index),this);
 
189
 
 
190
      /* put us in the production list of the lhs non terminal */
 
191
      lhs_sym.add_production(this);
 
192
    }
 
193
 
 
194
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
195
 
 
196
  /** Constructor with no action string. */
 
197
  public production(
 
198
    non_terminal    lhs_sym, 
 
199
    production_part rhs_parts[], 
 
200
    int             rhs_l)
 
201
    throws internal_error
 
202
    {
 
203
      this(lhs_sym,rhs_parts,rhs_l,null);
 
204
    }
 
205
 
 
206
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
207
 
 
208
  /* Constructor with precedence and associativity of production
 
209
     contextually define */
 
210
  public production(
 
211
    non_terminal    lhs_sym, 
 
212
    production_part rhs_parts[], 
 
213
    int             rhs_l,
 
214
    String          action_str,
 
215
    int             prec_num,
 
216
    int             prec_side)
 
217
    throws internal_error
 
218
    {
 
219
      this(lhs_sym,rhs_parts,rhs_l,action_str);
 
220
      
 
221
      /* set the precedence */
 
222
      set_precedence_num(prec_num);
 
223
      set_precedence_side(prec_side);
 
224
    }
 
225
 
 
226
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/       
 
227
     
 
228
  /* Constructor w/ no action string and contextual precedence
 
229
     defined */
 
230
  public production(
 
231
    non_terminal    lhs_sym, 
 
232
    production_part rhs_parts[], 
 
233
    int             rhs_l,
 
234
    int             prec_num,
 
235
    int             prec_side)
 
236
    throws internal_error
 
237
    {
 
238
      this(lhs_sym,rhs_parts,rhs_l,null);
 
239
      /* set the precedence */
 
240
      set_precedence_num(prec_num);
 
241
      set_precedence_side(prec_side);
 
242
    }
 
243
 
 
244
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
245
 
 
246
  /*-----------------------------------------------------------*/
 
247
  /*--- (Access to) Static (Class) Variables ------------------*/
 
248
  /*-----------------------------------------------------------*/
 
249
 
 
250
    
 
251
  /** Table of all productions.  Elements are stored using their index as 
 
252
   *  the key.
 
253
   */
 
254
  protected static Hashtable _all = new Hashtable();
 
255
 
 
256
  /** Access to all productions. */
 
257
  public static Enumeration all() {return _all.elements();}
 
258
 
 
259
    /** Lookup a production by index. */
 
260
  public static production find(int indx) {
 
261
    return (production) _all.get(new Integer(indx));
 
262
  }
 
263
 
 
264
  //Hm Added clear  to clear all static fields
 
265
  public static void clear() {
 
266
      _all.clear();
 
267
      next_index=0;
 
268
  }
 
269
  
 
270
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
271
 
 
272
  /** Total number of productions. */
 
273
  public static int number() {return _all.size();}
 
274
 
 
275
  /** Static counter for assigning unique index numbers. */
 
276
  protected static int next_index;
 
277
 
 
278
  /*-----------------------------------------------------------*/
 
279
  /*--- (Access to) Instance Variables ------------------------*/
 
280
  /*-----------------------------------------------------------*/
 
281
 
 
282
  /** The left hand side non-terminal. */
 
283
  protected symbol_part _lhs;
 
284
 
 
285
  /** The left hand side non-terminal. */
 
286
  public symbol_part lhs() {return _lhs;}
 
287
 
 
288
 
 
289
  /** The precedence of the rule */
 
290
  protected int _rhs_prec = -1;
 
291
  protected int _rhs_assoc = -1;
 
292
 
 
293
  /** Access to the precedence of the rule */
 
294
  public int precedence_num() { return _rhs_prec; }
 
295
  public int precedence_side() { return _rhs_assoc; }
 
296
 
 
297
  /** Setting the precedence of a rule */
 
298
  public void set_precedence_num(int prec_num) {  
 
299
    _rhs_prec = prec_num;
 
300
  }
 
301
  public void set_precedence_side(int prec_side) { 
 
302
    _rhs_assoc = prec_side;
 
303
  }
 
304
 
 
305
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
306
 
 
307
  /** A collection of parts for the right hand side. */
 
308
  protected production_part _rhs[];
 
309
 
 
310
  /** Access to the collection of parts for the right hand side. */
 
311
  public production_part rhs(int indx) throws internal_error
 
312
    {
 
313
      if (indx >= 0 && indx < _rhs_length)
 
314
        return _rhs[indx];
 
315
      else
 
316
        throw new internal_error(
 
317
          "Index out of range for right hand side of production");
 
318
    }
 
319
 
 
320
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
321
 
 
322
  /** How much of the right hand side array we are presently using. */
 
323
  protected int _rhs_length;
 
324
 
 
325
  /** How much of the right hand side array we are presently using. */
 
326
  public int rhs_length() {return _rhs_length;}
 
327
 
 
328
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
329
 
 
330
  /** An action_part containing code for the action to be performed when we 
 
331
   *  reduce with this production. 
 
332
   */
 
333
  protected action_part _action;
 
334
 
 
335
  /** An action_part containing code for the action to be performed when we 
 
336
   *  reduce with this production. 
 
337
   */
 
338
  public action_part action() {return _action;}
 
339
 
 
340
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
341
 
 
342
  /** Index number of the production. */
 
343
  protected int _index;
 
344
 
 
345
  /** Index number of the production. */
 
346
  public int index() {return _index;}
 
347
 
 
348
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
349
 
 
350
  /** Count of number of reductions using this production. */
 
351
  protected int _num_reductions = 0;
 
352
 
 
353
  /** Count of number of reductions using this production. */
 
354
  public int num_reductions() {return _num_reductions;}
 
355
 
 
356
  /** Increment the count of reductions with this non-terminal */
 
357
  public void note_reduction_use() {_num_reductions++;}
 
358
 
 
359
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
360
 
 
361
  /** Is the nullability of the production known or unknown? */
 
362
  protected boolean _nullable_known = false;
 
363
 
 
364
  /** Is the nullability of the production known or unknown? */
 
365
  public boolean nullable_known() {return _nullable_known;}
 
366
 
 
367
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
368
 
 
369
  /** Nullability of the production (can it derive the empty string). */
 
370
  protected boolean _nullable = false;
 
371
 
 
372
  /** Nullability of the production (can it derive the empty string). */
 
373
  public boolean nullable() {return _nullable;}
 
374
 
 
375
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
376
 
 
377
  /** First set of the production.  This is the set of terminals that 
 
378
   *  could appear at the front of some string derived from this production.
 
379
   */
 
380
  protected terminal_set _first_set = new terminal_set();
 
381
 
 
382
  /** First set of the production.  This is the set of terminals that 
 
383
   *  could appear at the front of some string derived from this production.
 
384
   */
 
385
  public terminal_set first_set() {return _first_set;}
 
386
 
 
387
  /*-----------------------------------------------------------*/
 
388
  /*--- Static Methods ----------------------------------------*/
 
389
  /*-----------------------------------------------------------*/
 
390
 
 
391
  /** Determine if a given character can be a label id starter. 
 
392
   * @param c the character in question. 
 
393
   */
 
394
  protected static boolean is_id_start(char c)
 
395
    {
 
396
      return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
 
397
 
 
398
      //later need to handle non-8-bit chars here
 
399
    }
 
400
 
 
401
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
402
 
 
403
  /** Determine if a character can be in a label id. 
 
404
   * @param c the character in question.
 
405
   */
 
406
  protected static boolean is_id_char(char c)
 
407
    {
 
408
      return is_id_start(c) || (c >= '0' && c <= '9');
 
409
    }
 
410
 
 
411
  /*-----------------------------------------------------------*/
 
412
  /*--- General Methods ---------------------------------------*/
 
413
  /*-----------------------------------------------------------*/
 
414
  
 
415
 
 
416
  /** Return label declaration code
 
417
   * @param labelname    the label name
 
418
   * @param stack_type   the stack type of label?
 
419
   * @author frankf
 
420
   */ 
 
421
  protected String make_declaration(
 
422
                                    String  labelname,
 
423
                                    String  stack_type,
 
424
                                    int     offset)
 
425
    {
 
426
      String ret;
 
427
 
 
428
      /* Put in the left/right value labels */
 
429
      if (emit.lr_values())
 
430
        ret = "\t\tint " + labelname + "left = ((weka.core.parser.java_cup.runtime.Symbol)" + 
 
431
          emit.pre("stack") + 
 
432
            // TUM 20050917
 
433
            ((offset==0)?".peek()":(".elementAt(" + emit.pre("top") + "-" + offset + ")"))+
 
434
            ").left;\n" +
 
435
          "\t\tint " + labelname + "right = ((weka.core.parser.java_cup.runtime.Symbol)" + 
 
436
          emit.pre("stack") +
 
437
            // TUM 20050917
 
438
            ((offset==0)?".peek()":(".elementAt(" + emit.pre("top") + "-" + offset + ")"))+
 
439
            ").right;\n";
 
440
      else ret = "";
 
441
 
 
442
      /* otherwise, just declare label. */
 
443
        return ret + "\t\t" + stack_type + " " + labelname + " = (" + stack_type + 
 
444
          ")((" + "weka.core.parser.java_cup.runtime.Symbol) " + emit.pre("stack") + 
 
445
            // TUM 20050917
 
446
            ((offset==0)?".peek()":(".elementAt(" + emit.pre("top") + "-" + offset + ")"))+
 
447
            ").value;\n";
 
448
 
 
449
    }
 
450
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
451
 
 
452
  /** Declare label names as valid variables within the action string
 
453
   * @param rhs          array of RHS parts.
 
454
   * @param rhs_len      how much of rhs to consider valid.
 
455
   * @param final_action the final action string of the production. 
 
456
   * @param lhs_type     the object type associated with the LHS symbol.
 
457
   */ 
 
458
  protected String declare_labels(
 
459
    production_part  rhs[], 
 
460
    int              rhs_len, 
 
461
    String           final_action)
 
462
    {
 
463
      String declaration = "";
 
464
 
 
465
      symbol_part part;
 
466
      action_part act_part;
 
467
      int         pos;
 
468
 
 
469
      /* walk down the parts and extract the labels */
 
470
      for (pos = 0; pos < rhs_len; pos++)
 
471
        {
 
472
          if (!rhs[pos].is_action())
 
473
            {
 
474
              part = (symbol_part)rhs[pos];
 
475
 
 
476
              /* if it has a label, make declaration! */
 
477
              if (part.label() != null)
 
478
                {
 
479
                  declaration = declaration + 
 
480
                    make_declaration(part.label(), part.the_symbol().stack_type(), 
 
481
                                     rhs_len-pos-1);
 
482
                }
 
483
            }
 
484
        }
 
485
      return declaration;
 
486
    }
 
487
 
 
488
 
 
489
 
 
490
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
491
 
 
492
  /** Helper routine to merge adjacent actions in a set of RHS parts 
 
493
   * @param rhs_parts array of RHS parts.
 
494
   * @param len       amount of that array that is valid.
 
495
   * @return          remaining valid length.
 
496
   */
 
497
  protected int merge_adjacent_actions(production_part rhs_parts[], int len)
 
498
    {
 
499
      int from_loc, to_loc, merge_cnt;
 
500
 
 
501
      /* bail out early if we have no work to do */
 
502
      if (rhs_parts == null || len == 0) return 0;
 
503
 
 
504
      merge_cnt = 0;
 
505
      to_loc = -1;
 
506
      for (from_loc=0; from_loc<len; from_loc++)
 
507
        {
 
508
          /* do we go in the current position or one further */
 
509
          if (to_loc < 0 || !rhs_parts[to_loc].is_action() 
 
510
                         || !rhs_parts[from_loc].is_action())
 
511
            {
 
512
              /* next one */
 
513
              to_loc++;
 
514
 
 
515
              /* clear the way for it */
 
516
              if (to_loc != from_loc) rhs_parts[to_loc] = null;
 
517
            }
 
518
 
 
519
          /* if this is not trivial? */
 
520
          if (to_loc != from_loc)
 
521
            {
 
522
              /* do we merge or copy? */
 
523
              if (rhs_parts[to_loc] != null && rhs_parts[to_loc].is_action() && 
 
524
                  rhs_parts[from_loc].is_action())
 
525
              {
 
526
                /* merge */
 
527
                rhs_parts[to_loc] = new action_part(
 
528
                  ((action_part)rhs_parts[to_loc]).code_string() +
 
529
                  ((action_part)rhs_parts[from_loc]).code_string());
 
530
                merge_cnt++;
 
531
              }
 
532
            else
 
533
              {
 
534
                /* copy */
 
535
                rhs_parts[to_loc] = rhs_parts[from_loc];
 
536
              }
 
537
            }
 
538
        }
 
539
 
 
540
      /* return the used length */
 
541
      return len - merge_cnt;
 
542
    }
 
543
 
 
544
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
545
 
 
546
  /** Helper routine to strip a trailing action off rhs and return it
 
547
   * @param rhs_parts array of RHS parts.
 
548
   * @param len       how many of those are valid.
 
549
   * @return          the removed action part.
 
550
   */
 
551
  protected action_part strip_trailing_action(
 
552
    production_part rhs_parts[],
 
553
    int             len)
 
554
    {
 
555
      action_part result;
 
556
 
 
557
      /* bail out early if we have nothing to do */
 
558
      if (rhs_parts == null || len == 0) return null;
 
559
 
 
560
      /* see if we have a trailing action */
 
561
      if (rhs_parts[len-1].is_action())
 
562
        {
 
563
          /* snip it out and return it */
 
564
          result = (action_part)rhs_parts[len-1];
 
565
          rhs_parts[len-1] = null;
 
566
          return result;
 
567
        }
 
568
      else
 
569
        return null;
 
570
    }
 
571
 
 
572
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
573
 
 
574
  /** Remove all embedded actions from a production by factoring them 
 
575
   *  out into individual action production using new non terminals.
 
576
   *  if the original production was:  <pre>
 
577
   *    A ::= B {action1} C {action2} D 
 
578
   *  </pre>
 
579
   *  then it will be factored into: <pre>
 
580
   *    A ::= B NT$1 C NT$2 D
 
581
   *    NT$1 ::= {action1}
 
582
   *    NT$2 ::= {action2}
 
583
   *  </pre>
 
584
   *  where NT$1 and NT$2 are new system created non terminals.
 
585
   */
 
586
 
 
587
  /* the declarations added to the parent production are also passed along,
 
588
     as they should be perfectly valid in this code string, since it
 
589
     was originally a code string in the parent, not on its own.
 
590
     frank 6/20/96 */
 
591
  protected void remove_embedded_actions(
 
592
           
 
593
            ) throws internal_error
 
594
    {
 
595
      non_terminal new_nt;
 
596
      production   new_prod;
 
597
      String declare_str;
 
598
      int lastLocation = -1;
 
599
      /* walk over the production and process each action */
 
600
      for (int act_loc = 0; act_loc < rhs_length(); act_loc++)
 
601
        if (rhs(act_loc).is_action())
 
602
          {
 
603
            
 
604
            
 
605
            declare_str = declare_labels(
 
606
                      _rhs, act_loc, "");
 
607
            /* create a new non terminal for the action production */
 
608
            new_nt = non_terminal.create_new(null, lhs().the_symbol().stack_type()); // TUM 20060608 embedded actions patch
 
609
            new_nt.is_embedded_action = true; /* 24-Mar-1998, CSA */
 
610
 
 
611
            /* create a new production with just the action */
 
612
            new_prod = new action_production(this, new_nt, null, 0, 
 
613
                declare_str + ((action_part)rhs(act_loc)).code_string(), (lastLocation==-1)?-1:(act_loc-lastLocation));
 
614
 
 
615
            /* replace the action with the generated non terminal */
 
616
            _rhs[act_loc] = new symbol_part(new_nt);
 
617
            lastLocation = act_loc;
 
618
          }
 
619
    }
 
620
 
 
621
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
622
 
 
623
  /** Check to see if the production (now) appears to be nullable.
 
624
   *  A production is nullable if its RHS could derive the empty string.
 
625
   *  This results when the RHS is empty or contains only non terminals
 
626
   *  which themselves are nullable.
 
627
   */
 
628
  public boolean check_nullable() throws internal_error
 
629
    {
 
630
      production_part part;
 
631
      symbol          sym;
 
632
      int             pos;
 
633
 
 
634
      /* if we already know bail out early */
 
635
      if (nullable_known()) return nullable();
 
636
 
 
637
      /* if we have a zero size RHS we are directly nullable */
 
638
      if (rhs_length() == 0)
 
639
        {
 
640
          /* stash and return the result */
 
641
          return set_nullable(true);
 
642
        }
 
643
 
 
644
      /* otherwise we need to test all of our parts */
 
645
      for (pos=0; pos<rhs_length(); pos++)
 
646
        {
 
647
          part = rhs(pos);
 
648
 
 
649
          /* only look at non-actions */
 
650
          if (!part.is_action())
 
651
            {
 
652
              sym = ((symbol_part)part).the_symbol();
 
653
 
 
654
              /* if its a terminal we are definitely not nullable */
 
655
              if (!sym.is_non_term()) 
 
656
                return set_nullable(false);
 
657
              /* its a non-term, is it marked nullable */
 
658
              else if (!((non_terminal)sym).nullable())
 
659
                /* this one not (yet) nullable, so we aren't */
 
660
                return false;
 
661
            }
 
662
        }
 
663
 
 
664
      /* if we make it here all parts are nullable */
 
665
      return set_nullable(true);
 
666
    }
 
667
 
 
668
  /** set (and return) nullability */
 
669
  boolean set_nullable(boolean v)
 
670
    {
 
671
      _nullable_known = true;
 
672
      _nullable = v;
 
673
      return v;
 
674
    }
 
675
 
 
676
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
677
 
 
678
  /** Update (and return) the first set based on current NT firsts. 
 
679
   *  This assumes that nullability has already been computed for all non 
 
680
   *  terminals and productions. 
 
681
   */
 
682
  public terminal_set check_first_set() throws internal_error
 
683
    {
 
684
      int    part;
 
685
      symbol sym;
 
686
 
 
687
      /* walk down the right hand side till we get past all nullables */
 
688
      for (part=0; part<rhs_length(); part++)
 
689
        {
 
690
          /* only look at non-actions */
 
691
          if (!rhs(part).is_action())
 
692
            {
 
693
              sym = ((symbol_part)rhs(part)).the_symbol();
 
694
 
 
695
              /* is it a non-terminal?*/
 
696
              if (sym.is_non_term())
 
697
                {
 
698
                  /* add in current firsts from that NT */
 
699
                  _first_set.add(((non_terminal)sym).first_set());
 
700
 
 
701
                  /* if its not nullable, we are done */
 
702
                  if (!((non_terminal)sym).nullable())
 
703
                    break;
 
704
                }
 
705
              else
 
706
                {
 
707
                  /* its a terminal -- add that to the set */
 
708
                  _first_set.add((terminal)sym);
 
709
 
 
710
                  /* we are done */
 
711
                  break;
 
712
                }
 
713
            }
 
714
        }
 
715
 
 
716
      /* return our updated first set */
 
717
      return first_set();
 
718
    }
 
719
 
 
720
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
721
 
 
722
  /** Equality comparison. */
 
723
  public boolean equals(production other)
 
724
    {
 
725
      if (other == null) return false;
 
726
      return other._index == _index;
 
727
    }
 
728
 
 
729
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
730
 
 
731
  /** Generic equality comparison. */
 
732
  public boolean equals(Object other)
 
733
    {
 
734
      if (!(other instanceof production))
 
735
        return false;
 
736
      else
 
737
        return equals((production)other);
 
738
    }
 
739
 
 
740
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
741
 
 
742
  /** Produce a hash code. */
 
743
  public int hashCode()
 
744
    {
 
745
      /* just use a simple function of the index */
 
746
      return _index*13;
 
747
    }
 
748
 
 
749
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
750
 
 
751
  /** Convert to a string. */
 
752
  public String toString() 
 
753
    {
 
754
      String result;
 
755
      
 
756
      /* catch any internal errors */
 
757
      try {
 
758
        result = "production [" + index() + "]: "; 
 
759
        result += ((lhs() != null) ? lhs().toString() : "$$NULL-LHS$$");
 
760
        result += " :: = ";
 
761
        for (int i = 0; i<rhs_length(); i++)
 
762
          result += rhs(i) + " ";
 
763
        result += ";";
 
764
        if (action()  != null && action().code_string() != null) 
 
765
          result += " {" + action().code_string() + "}";
 
766
 
 
767
        if (nullable_known())
 
768
          if (nullable())
 
769
            result += "[NULLABLE]";
 
770
          else
 
771
            result += "[NOT NULLABLE]";
 
772
      } catch (internal_error e) {
 
773
        /* crash on internal error since we can't throw it from here (because
 
774
           superclass does not throw anything. */
 
775
        e.crash();
 
776
        result = null;
 
777
      }
 
778
 
 
779
      return result;
 
780
    }
 
781
 
 
782
  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 
783
 
 
784
  /** Convert to a simpler string. */
 
785
  public String to_simple_string() throws internal_error
 
786
    {
 
787
      String result;
 
788
 
 
789
      result = ((lhs() != null) ? lhs().the_symbol().name() : "NULL_LHS");
 
790
      result += " ::= ";
 
791
      for (int i = 0; i < rhs_length(); i++)
 
792
        if (!rhs(i).is_action())
 
793
          result += ((symbol_part)rhs(i)).the_symbol().name() + " ";
 
794
 
 
795
      return result;
 
796
    }
 
797
 
 
798
  /*-----------------------------------------------------------*/
 
799
 
 
800
}