Added malloc.h includes. From Josef Goettgens.
[external/ragel.git] / ragel / rlparse.kl
1 /*
2  *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  * 
12  *  Ragel is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  * 
17  *  You should have received a copy of the GNU General Public License
18  *  along with Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22 #include "rlparse.h"
23 #include "ragel.h"
24 #include <iostream>
25 #include <errno.h>
26 #include <malloc.h>
27
28 using std::cout;
29 using std::cerr;
30 using std::endl;
31
32 ParserDict parserDict;
33
34 %%{
35
36 parser Parser;
37
38 include "rlparse.kh";
39
40 start: section_list;
41
42 section_list: section_list statement_list TK_EndSection;
43 section_list: ;
44
45 statement_list: statement_list statement;
46 statement_list: ;
47
48 statement: assignment commit;
49 statement: instantiation commit;
50 statement: action_spec commit;
51 statement: alphtype_spec commit;
52 statement: range_spec commit;
53 statement: getkey_spec commit;
54 statement: access_spec commit;
55 statement: variable_spec commit;
56
57 assignment:
58         machine_name '=' join ';' final {
59                 /* Main machine must be an instance. */
60                 bool isInstance = false;
61                 if ( strcmp($1->token.data, machineMain) == 0 ) {
62                         warning($1->token.loc) << 
63                                         "main machine will be implicitly instantiated" << endl;
64                         isInstance = true;
65                 }
66
67                 /* Generic creation of machine for instantiation and assignment. */
68                 JoinOrLm *joinOrLm = new JoinOrLm( $3->join );
69                 tryMachineDef( $1->token.loc, $1->token.data, joinOrLm, isInstance );
70         };
71
72 instantiation: 
73         machine_name TK_ColonEquals join_or_lm ';' final {
74                 /* Generic creation of machine for instantiation and assignment. */
75                 tryMachineDef( $1->token.loc, $1->token.data, $3->joinOrLm, true );
76         };
77
78 type token_type
79 {
80         Token token;
81 };
82
83 nonterm machine_name uses token_type;
84
85 machine_name: 
86         TK_Word final {
87                 /* Make/get the priority key. The name may have already been referenced
88                  * and therefore exist. */
89                 PriorDictEl *priorDictEl;
90                 if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) )
91                         pd->nextPriorKey += 1;
92                 pd->curDefPriorKey = priorDictEl->value;
93
94                 /* Make/get the local error key. */
95                 LocalErrDictEl *localErrDictEl;
96                 if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) )
97                         pd->nextLocalErrKey += 1;
98                 pd->curDefLocalErrKey = localErrDictEl->value;
99
100                 $$->token = *$1;
101         };
102
103 action_spec:
104         KW_Action TK_Word '{' inline_block '}' final {
105                 if ( pd->actionDict.find( $2->data ) ) {
106                         /* Recover by just ignoring the duplicate. */
107                         error($2->loc) << "action \"" << $2->data << "\" already defined" << endl;
108                 }
109                 else {
110                         //cerr << "NEW ACTION " << $2->data << " " << $4->inlineList << endl;
111                         /* Add the action to the list of actions. */
112                         Action *newAction = new Action( $3->loc, $2->data, $4->inlineList );
113
114                         /* Insert to list and dict. */
115                         pd->actionList.append( newAction );
116                         pd->actionDict.insert( newAction );
117                 }
118         };
119
120 # Specifies the data type of the input alphabet. One or two words followed by a
121 # semi-colon.
122 alphtype_spec:
123         KW_AlphType TK_Word TK_Word ';' final {
124                 if ( ! pd->setAlphType( $2->data, $3->data ) ) {
125                         // Recover by ignoring the alphtype statement.
126                         error($2->loc) << "\"" << $2->data << 
127                                         " " << $3->data << "\" is not a valid alphabet type" << endl;
128                 }
129         };
130
131 alphtype_spec:
132         KW_AlphType TK_Word ';' final {
133                 if ( ! pd->setAlphType( $2->data ) ) {
134                         // Recover by ignoring the alphtype statement.
135                         error($2->loc) << "\"" << $2->data << 
136                                         "\" is not a valid alphabet type" << endl;
137                 }
138         };
139
140 # Specifies a range to assume that the input characters will fall into.
141 range_spec:
142         KW_Range alphabet_num alphabet_num ';' final {
143                 // Save the upper and lower ends of the range and emit the line number.
144                 pd->lowerNum = $2->token.data;
145                 pd->upperNum = $3->token.data;
146                 pd->rangeLowLoc = $2->token.loc;
147                 pd->rangeHighLoc = $3->token.loc;
148         };
149
150 getkey_spec:
151         KW_GetKey inline_expr ';' final {
152                 pd->getKeyExpr = $2->inlineList;
153         };
154
155 access_spec:
156         KW_Access inline_expr ';' final {
157                 pd->accessExpr = $2->inlineList;
158         };
159
160 variable_spec:
161         KW_Variable opt_whitespace TK_Word inline_expr ';' final {
162                 /* FIXME: Need to implement the rest of this. */
163                 if ( strcmp( $3->data, "curstate" ) == 0 )
164                         pd->curStateExpr = $4->inlineList;
165                 else {
166                         error($3->loc) << "sorry, unimplementd" << endl;
167                 }
168         };
169
170 opt_whitespace: opt_whitespace IL_WhiteSpace;
171 opt_whitespace: ;
172
173 #
174 # Expressions
175 #
176
177 nonterm join_or_lm
178 {
179         JoinOrLm *joinOrLm;
180 };
181
182 join_or_lm: 
183         join final {
184                 $$->joinOrLm = new JoinOrLm( $1->join );
185         };
186 join_or_lm:
187         TK_BarStar lm_part_list '*' '|' final {
188                 /* Create a new factor going to a longest match structure. Record
189                  * in the parse data that we have a longest match. */
190                 LongestMatch *lm = new LongestMatch( $1->loc, $2->lmPartList );
191                 pd->lmList.append( lm );
192                 for ( LmPartList::Iter lmp = *($2->lmPartList); lmp.lte(); lmp++ )
193                         lmp->longestMatch = lm;
194                 $$->joinOrLm = new JoinOrLm( lm );
195         };
196
197 nonterm lm_part_list
198 {
199         LmPartList *lmPartList;
200 };
201
202 lm_part_list:
203         lm_part_list longest_match_part final {
204                 if ( $2->lmPart != 0 ) 
205                         $1->lmPartList->append( $2->lmPart );
206                 $$->lmPartList = $1->lmPartList;
207         };
208 lm_part_list:
209         longest_match_part final {
210                 /* Create a new list with the part. */
211                 $$->lmPartList = new LmPartList;
212                 if ( $1->lmPart != 0 )
213                         $$->lmPartList->append( $1->lmPart );
214         };
215
216 nonterm longest_match_part
217 {
218         LongestMatchPart *lmPart;
219 };
220
221 longest_match_part: 
222         action_spec final { $$->lmPart = 0; };
223 longest_match_part: 
224         assignment final { $$->lmPart = 0; };
225 longest_match_part: 
226         join opt_lm_part_action ';' final {
227                 $$->lmPart = 0;
228                 Action *action = $2->action;
229                 if ( action != 0 )
230                         action->isLmAction = true;
231                 $$->lmPart = new LongestMatchPart( $1->join, action, 
232                                 $3->loc, pd->nextLongestMatchId++ );
233         };
234
235 nonterm opt_lm_part_action
236 {
237         Action *action;
238 };
239
240 opt_lm_part_action:
241         TK_DoubleArrow action_embed final { 
242                 $$->action = $2->action;
243         };
244 opt_lm_part_action:
245         action_embed_block final {
246                 $$->action = $1->action;
247         };
248 opt_lm_part_action:
249         final {
250                 $$->action = 0;
251         };
252
253
254 nonterm join
255 {
256         Join *join;
257 };
258
259 join: 
260         join ',' expression final {
261                 /* Append the expression to the list and return it. */
262                 $1->join->exprList.append( $3->expression );
263                 $$->join = $1->join;
264         };
265 join: 
266         expression final {
267                 $$->join = new Join( $1->expression );
268         };
269
270 nonterm expression
271 {
272         Expression *expression;
273 };
274
275 expression: 
276         expression '|' term final {
277                 $$->expression = new Expression( $1->expression, 
278                                 $3->term, Expression::OrType );
279         };
280 expression: 
281         expression '&' term final {
282                 $$->expression = new Expression( $1->expression, 
283                                 $3->term, Expression::IntersectType );
284         };
285 # This priority specification overrides the innermost parsing strategy which
286 # results ordered choice interpretation of the grammar.
287 expression: 
288         expression pri(1) '-' term final {
289                 $$->expression = new Expression( $1->expression, 
290                                 $3->term, Expression::SubtractType );
291         };
292 expression: 
293         expression TK_DashDash term final {
294                 $$->expression = new Expression( $1->expression, 
295                                 $3->term, Expression::StrongSubtractType );
296         };
297 expression: 
298         term final {
299                 $$->expression = new Expression( $1->term );
300         };
301
302 nonterm term
303 {
304         Term *term;
305 };
306
307 term:
308         term factor_with_label final {
309                 $$->term = new Term( $1->term, $2->factorWithAug );
310         };
311 term:
312         term '.' factor_with_label final {
313                 $$->term = new Term( $1->term, $3->factorWithAug );
314         };
315 term:
316         term TK_ColonGt factor_with_label final {
317                 $$->term = new Term( $1->term, $3->factorWithAug, Term::RightStartType );
318         };
319 term:
320         term TK_ColonGtGt factor_with_label final {
321                 $$->term = new Term( $1->term, $3->factorWithAug, Term::RightFinishType );
322         };
323 term:
324         term TK_LtColon factor_with_label final {
325                 $$->term = new Term( $1->term, 
326                                 $3->factorWithAug, Term::LeftType );
327         };
328 term:
329         factor_with_label final {
330                 $$->term = new Term( $1->factorWithAug );
331         };
332
333 nonterm factor_with_label
334 {
335         FactorWithAug *factorWithAug;
336 };
337
338 factor_with_label: 
339         TK_Word ':' factor_with_label final { 
340                 /* Add the label to the list and pass the factor up. */
341                 $3->factorWithAug->labels.prepend( Label($1->loc, $1->data) );
342                 $$->factorWithAug = $3->factorWithAug; 
343         };
344 factor_with_label: 
345         factor_with_ep final {
346                 $$->factorWithAug = $1->factorWithAug;
347         };
348
349 nonterm factor_with_ep
350 {
351         FactorWithAug *factorWithAug;
352 };
353
354 factor_with_ep: 
355         factor_with_ep TK_Arrow local_state_ref final { 
356                 /* Add the target to the list and return the factor object. */
357                 $1->factorWithAug->epsilonLinks.append( EpsilonLink( $2->loc, nameRef ) );
358                 $$->factorWithAug = $1->factorWithAug; 
359         };
360 factor_with_ep: 
361         factor_with_aug final {
362                 $$->factorWithAug = $1->factorWithAug;
363         };
364
365 nonterm factor_with_aug
366 {
367         FactorWithAug *factorWithAug;
368 };
369
370 factor_with_aug:
371         factor_with_aug aug_type_base action_embed final {
372                 /* Append the action to the factorWithAug, record the refernce from 
373                  * factorWithAug to the action and pass up the factorWithAug. */
374                 $1->factorWithAug->actions.append( 
375                                 ParserAction( $2->loc, $2->augType, 0, $3->action ) );
376                 $$->factorWithAug = $1->factorWithAug;
377         };
378 factor_with_aug:
379         factor_with_aug aug_type_base priority_aug final {
380                 /* Append the named priority to the factorWithAug and pass it up. */
381                 $1->factorWithAug->priorityAugs.append( 
382                                 PriorityAug( $2->augType, pd->curDefPriorKey, $3->priorityNum ) );
383                 $$->factorWithAug = $1->factorWithAug;
384         };
385 factor_with_aug:
386         factor_with_aug aug_type_base '(' priority_name ',' priority_aug ')' final {
387                 /* Append the priority using a default name. */
388                 $1->factorWithAug->priorityAugs.append( 
389                                 PriorityAug( $2->augType, $4->priorityName, $6->priorityNum ) );
390                 $$->factorWithAug = $1->factorWithAug;
391         };
392 factor_with_aug:
393         factor_with_aug aug_type_cond action_embed final {
394                 $1->factorWithAug->conditions.append( ParserAction( $2->loc, 
395                                 $2->augType, 0, $3->action ) );
396                 $$->factorWithAug = $1->factorWithAug;
397         };
398 factor_with_aug:
399         factor_with_aug aug_type_to_state action_embed final {
400                 /* Append the action, pass it up. */
401                 $1->factorWithAug->actions.append( ParserAction( $2->loc, 
402                                 $2->augType, 0, $3->action ) );
403                 $$->factorWithAug = $1->factorWithAug;
404         };
405 factor_with_aug:
406         factor_with_aug aug_type_from_state action_embed final {
407                 /* Append the action, pass it up. */
408                 $1->factorWithAug->actions.append( ParserAction( $2->loc,
409                                 $2->augType, 0, $3->action ) );
410                 $$->factorWithAug = $1->factorWithAug;
411         };
412 factor_with_aug:
413         factor_with_aug aug_type_eof action_embed final {
414                 /* Append the action, pass it up. */
415                 $1->factorWithAug->actions.append( ParserAction( $2->loc,
416                                 $2->augType, 0, $3->action ) );
417                 $$->factorWithAug = $1->factorWithAug;
418         };
419 factor_with_aug:
420         factor_with_aug aug_type_gbl_error action_embed final {
421                 /* Append the action to the factorWithAug, record the refernce from 
422                  * factorWithAug to the action and pass up the factorWithAug. */
423                 $1->factorWithAug->actions.append( ParserAction( $2->loc,
424                                 $2->augType, pd->curDefLocalErrKey, $3->action ) );
425                 $$->factorWithAug = $1->factorWithAug;
426         };
427 factor_with_aug:
428         factor_with_aug aug_type_local_error action_embed final {
429                 /* Append the action to the factorWithAug, record the refernce from 
430                  * factorWithAug to the action and pass up the factorWithAug. */
431                 $1->factorWithAug->actions.append( ParserAction( $2->loc, 
432                                 $2->augType, pd->curDefLocalErrKey, $3->action ) );
433                 $$->factorWithAug = $1->factorWithAug;
434         };
435 factor_with_aug:
436         factor_with_aug aug_type_local_error '(' local_err_name ',' action_embed ')' final {
437                 /* Append the action to the factorWithAug, record the refernce from
438                  * factorWithAug to the action and pass up the factorWithAug. */
439                 $1->factorWithAug->actions.append( ParserAction( $2->loc,
440                                 $2->augType, $4->error_name, $6->action ) );
441                 $$->factorWithAug = $1->factorWithAug;
442         };
443 factor_with_aug:
444         factor_with_rep final {
445                 $$->factorWithAug = new FactorWithAug( $1->factorWithRep );
446         };
447
448 type aug_type
449 {
450         InputLoc loc;
451         AugType augType;
452 };
453
454 #  Classes of transtions on which to embed actions or change priorities.
455 nonterm aug_type_base uses aug_type;
456
457 aug_type_base: '@' final { $$->loc = $1->loc; $$->augType = at_finish; };
458 aug_type_base: '%' final { $$->loc = $1->loc; $$->augType = at_leave; };
459 aug_type_base: '$' final { $$->loc = $1->loc; $$->augType = at_all; };
460 aug_type_base: '>' final { $$->loc = $1->loc; $$->augType = at_start; };
461
462 # Embedding conditions.
463 nonterm aug_type_cond uses aug_type;
464
465 aug_type_cond: TK_StartCond final { $$->loc = $1->loc; $$->augType = at_start; };
466 aug_type_cond: '>' KW_When final { $$->loc = $1->loc; $$->augType = at_start; };
467 aug_type_cond: TK_AllCond final { $$->loc = $1->loc; $$->augType = at_all; };
468 aug_type_cond: '$' KW_When final { $$->loc = $1->loc; $$->augType = at_all; };
469 aug_type_cond: TK_LeavingCond final { $$->loc = $1->loc; $$->augType = at_leave; };
470 aug_type_cond: '%' KW_When final { $$->loc = $1->loc; $$->augType = at_leave; };
471 aug_type_cond: KW_When final { $$->loc = $1->loc; $$->augType = at_all; };
472
473 #
474 # To state actions.
475 #
476
477 nonterm aug_type_to_state uses aug_type;
478
479 aug_type_to_state: TK_StartToState 
480                 final { $$->loc = $1->loc; $$->augType = at_start_to_state; };
481 aug_type_to_state: '>' KW_To 
482                 final { $$->loc = $1->loc; $$->augType = at_start_to_state; };
483
484 aug_type_to_state: TK_NotStartToState 
485                 final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; };
486 aug_type_to_state: '<' KW_To 
487                 final { $$->loc = $1->loc; $$->augType = at_not_start_to_state; };
488
489 aug_type_to_state: TK_AllToState 
490                 final { $$->loc = $1->loc; $$->augType = at_all_to_state; };
491 aug_type_to_state: '$' KW_To 
492                 final { $$->loc = $1->loc; $$->augType = at_all_to_state; };
493
494 aug_type_to_state: TK_FinalToState
495                 final { $$->loc = $1->loc; $$->augType = at_final_to_state; };
496 aug_type_to_state: '%' KW_To
497                 final { $$->loc = $1->loc; $$->augType = at_final_to_state; };
498
499 aug_type_to_state: TK_NotFinalToState
500                 final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; };
501 aug_type_to_state: '@' KW_To
502                 final { $$->loc = $1->loc; $$->augType = at_not_final_to_state; };
503
504 aug_type_to_state: TK_MiddleToState
505                 final { $$->loc = $1->loc; $$->augType = at_middle_to_state; };
506 aug_type_to_state: TK_Middle KW_To
507                 final { $$->loc = $1->loc; $$->augType = at_middle_to_state; };
508
509 #
510 # From state actions.
511 #
512
513 nonterm aug_type_from_state uses aug_type;
514
515 aug_type_from_state: TK_StartFromState 
516                 final { $$->loc = $1->loc; $$->augType = at_start_from_state; };
517 aug_type_from_state: '>' KW_From 
518                 final { $$->loc = $1->loc; $$->augType = at_start_from_state; };
519
520 aug_type_from_state: TK_NotStartFromState 
521                 final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; };
522 aug_type_from_state: '<' KW_From 
523                 final { $$->loc = $1->loc; $$->augType = at_not_start_from_state; };
524
525 aug_type_from_state: TK_AllFromState 
526                 final { $$->loc = $1->loc; $$->augType = at_all_from_state; };
527 aug_type_from_state: '$' KW_From 
528                 final { $$->loc = $1->loc; $$->augType = at_all_from_state; };
529
530 aug_type_from_state: TK_FinalFromState 
531                 final { $$->loc = $1->loc; $$->augType = at_final_from_state; };
532 aug_type_from_state: '%' KW_From 
533                 final { $$->loc = $1->loc; $$->augType = at_final_from_state; };
534
535 aug_type_from_state: TK_NotFinalFromState 
536                 final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; };
537 aug_type_from_state: '@' KW_From 
538                 final { $$->loc = $1->loc; $$->augType = at_not_final_from_state; };
539
540 aug_type_from_state: TK_MiddleFromState 
541                 final { $$->loc = $1->loc; $$->augType = at_middle_from_state; };
542 aug_type_from_state: TK_Middle KW_From 
543                 final { $$->loc = $1->loc; $$->augType = at_middle_from_state; };
544
545 #
546 # Eof state actions.
547 #
548
549 nonterm aug_type_eof uses aug_type;
550
551 aug_type_eof: TK_StartEOF 
552                 final { $$->loc = $1->loc; $$->augType = at_start_eof; };
553 aug_type_eof: '>' KW_Eof
554                 final { $$->loc = $1->loc; $$->augType = at_start_eof; };
555
556 aug_type_eof: TK_NotStartEOF
557                 final { $$->loc = $1->loc; $$->augType = at_not_start_eof; };
558 aug_type_eof: '<' KW_Eof
559                 final { $$->loc = $1->loc; $$->augType = at_not_start_eof; };
560
561 aug_type_eof: TK_AllEOF
562                 final { $$->loc = $1->loc; $$->augType = at_all_eof; };
563 aug_type_eof: '$' KW_Eof
564                 final { $$->loc = $1->loc; $$->augType = at_all_eof; };
565
566 aug_type_eof: TK_FinalEOF
567                 final { $$->loc = $1->loc; $$->augType = at_final_eof; };
568 aug_type_eof: '%' KW_Eof
569                 final { $$->loc = $1->loc; $$->augType = at_final_eof; };
570
571 aug_type_eof: TK_NotFinalEOF
572                 final { $$->loc = $1->loc; $$->augType = at_not_final_eof; };
573 aug_type_eof: '@' KW_Eof
574                 final { $$->loc = $1->loc; $$->augType = at_not_final_eof; };
575
576 aug_type_eof: TK_MiddleEOF
577                 final { $$->loc = $1->loc; $$->augType = at_middle_eof; };
578 aug_type_eof: TK_Middle KW_Eof
579                 final { $$->loc = $1->loc; $$->augType = at_middle_eof; };
580
581 #
582 # Global error actions.
583 #
584
585 nonterm aug_type_gbl_error uses aug_type;
586
587 aug_type_gbl_error: TK_StartGblError 
588                 final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; };
589 aug_type_gbl_error: '>' KW_Err 
590                 final { $$->loc = $1->loc; $$->augType = at_start_gbl_error; };
591
592 aug_type_gbl_error: TK_NotStartGblError 
593                 final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; };
594 aug_type_gbl_error: '<' KW_Err
595                 final { $$->loc = $1->loc; $$->augType = at_not_start_gbl_error; };
596
597 aug_type_gbl_error: TK_AllGblError
598                 final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; };
599 aug_type_gbl_error: '$' KW_Err
600                 final { $$->loc = $1->loc; $$->augType = at_all_gbl_error; };
601
602 aug_type_gbl_error: TK_FinalGblError
603                 final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; };
604 aug_type_gbl_error: '%' KW_Err
605                 final { $$->loc = $1->loc; $$->augType = at_final_gbl_error; };
606
607 aug_type_gbl_error: TK_NotFinalGblError
608                 final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; };
609 aug_type_gbl_error: '@' KW_Err
610                 final { $$->loc = $1->loc; $$->augType = at_not_final_gbl_error; };
611
612 aug_type_gbl_error: TK_MiddleGblError
613                 final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; };
614 aug_type_gbl_error: TK_Middle KW_Err
615                 final { $$->loc = $1->loc; $$->augType = at_middle_gbl_error; };
616
617
618 #
619 # Local error actions.
620 #
621
622 nonterm aug_type_local_error uses aug_type;
623
624 aug_type_local_error: TK_StartLocalError
625                 final { $$->loc = $1->loc; $$->augType = at_start_local_error; };
626 aug_type_local_error: '>' KW_Lerr
627                 final { $$->loc = $1->loc; $$->augType = at_start_local_error; };
628
629 aug_type_local_error: TK_NotStartLocalError
630                 final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; };
631 aug_type_local_error: '<' KW_Lerr
632                 final { $$->loc = $1->loc; $$->augType = at_not_start_local_error; };
633
634 aug_type_local_error: TK_AllLocalError
635                 final { $$->loc = $1->loc; $$->augType = at_all_local_error; };
636 aug_type_local_error: '$' KW_Lerr
637                 final { $$->loc = $1->loc; $$->augType = at_all_local_error; };
638
639 aug_type_local_error: TK_FinalLocalError
640                 final { $$->loc = $1->loc; $$->augType = at_final_local_error; };
641 aug_type_local_error: '%' KW_Lerr
642                 final { $$->loc = $1->loc; $$->augType = at_final_local_error; };
643
644 aug_type_local_error: TK_NotFinalLocalError
645                 final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; };
646 aug_type_local_error: '@' KW_Lerr
647                 final { $$->loc = $1->loc; $$->augType = at_not_final_local_error; };
648
649 aug_type_local_error: TK_MiddleLocalError
650                 final { $$->loc = $1->loc; $$->augType = at_middle_local_error; };
651 aug_type_local_error: TK_Middle KW_Lerr
652                 final { $$->loc = $1->loc; $$->augType = at_middle_local_error; };
653
654
655 type action_ref
656 {
657         Action *action;
658 };
659
660 # Different ways to embed actions. A TK_Word is reference to an action given by
661 # the user as a statement in the fsm specification. An action can also be
662 # specified immediately.
663 nonterm action_embed uses action_ref;
664
665 action_embed: action_embed_word final { $$->action = $1->action; };
666 action_embed: action_embed_block final { $$->action = $1->action; };
667
668 nonterm action_embed_word uses action_ref;
669
670 action_embed_word:
671         TK_Word final {
672                 /* Set the name in the actionDict. */
673                 Action *action = pd->actionDict.find( $1->data );
674                 if ( action != 0 ) {
675                         /* Pass up the action element */
676                         $$->action = action;
677                 }
678                 else {
679                         /* Will recover by returning null as the action. */
680                         error($1->loc) << "action lookup of \"" << $1->data << "\" failed" << endl;
681                         $$->action = 0;
682                 }
683         };
684
685 nonterm action_embed_block uses action_ref;
686
687 action_embed_block:
688         '{' inline_block '}' final {
689                 /* Create the action, add it to the list and pass up. */
690                 Action *newAction = new Action( $1->loc, 0, $2->inlineList );
691                 pd->actionList.append( newAction );
692                 $$->action = newAction;
693         };
694
695 nonterm priority_name
696 {
697         int priorityName;
698 };
699
700 # A specified priority name. Looks up the name in the current priority
701 # dictionary.
702 priority_name:
703         TK_Word final {
704                 // Lookup/create the priority key.
705                 PriorDictEl *priorDictEl;
706                 if ( pd->priorDict.insert( $1->data, pd->nextPriorKey, &priorDictEl ) )
707                         pd->nextPriorKey += 1;
708
709                 // Use the inserted/found priority key.
710                 $$->priorityName = priorDictEl->value;
711         };
712
713 nonterm priority_aug
714 {
715         int priorityNum;
716 };
717
718 # Priority change specs.
719 priority_aug: 
720         priority_aug_num final {
721                 // Convert the priority number to a long. Check for overflow.
722                 errno = 0;
723                 //cerr << "PRIOR AUG: " << $1->token.data << endl;
724                 int aug = strtol( $1->token.data, 0, 10 );
725                 if ( errno == ERANGE && aug == LONG_MAX ) {
726                         /* Priority number too large. Recover by setting the priority to 0. */
727                         error($1->token.loc) << "priority number " << $1->token.data << 
728                                         " overflows" << endl;
729                         $$->priorityNum = 0;
730                 }
731                 else if ( errno == ERANGE && aug == LONG_MIN ) {
732                         /* Priority number too large in the neg. Recover by using 0. */
733                         error($1->token.loc) << "priority number " << $1->token.data << 
734                                         " underflows" << endl;
735                         $$->priorityNum = 0;
736                 }
737                 else {
738                         /* No overflow or underflow. */
739                         $$->priorityNum = aug;
740                 }
741         };
742
743 nonterm priority_aug_num uses token_type;
744
745 priority_aug_num:
746         TK_UInt final {
747                 $$->token = *$1;
748         };
749 priority_aug_num:
750         '+' TK_UInt final {
751                 $$->token.set( "+", 1 );
752                 $$->token.loc = $1->loc;
753                 $$->token.append( *$2 );
754         };
755 priority_aug_num:
756         '-' TK_UInt final {
757                 $$->token.set( "-", 1 );
758                 $$->token.loc = $1->loc;
759                 $$->token.append( *$2 );
760         };
761
762 nonterm local_err_name
763 {
764         int error_name;
765 };
766
767 local_err_name:
768         TK_Word final {
769                 /* Lookup/create the priority key. */
770                 LocalErrDictEl *localErrDictEl;
771                 if ( pd->localErrDict.insert( $1->data, pd->nextLocalErrKey, &localErrDictEl ) )
772                         pd->nextLocalErrKey += 1;
773
774                 /* Use the inserted/found priority key. */
775                 $$->error_name = localErrDictEl->value;
776         };
777
778
779
780 # The fourth level of precedence. These are the trailing unary operators that
781 # allow for repetition.
782
783 nonterm factor_with_rep
784 {
785         FactorWithRep *factorWithRep;
786 };
787
788 factor_with_rep:
789         factor_with_rep '*' final {
790                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
791                                 0, 0, FactorWithRep::StarType );
792         };
793 factor_with_rep:
794         factor_with_rep TK_StarStar final {
795                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
796                                 0, 0, FactorWithRep::StarStarType );
797         };
798 factor_with_rep:
799         factor_with_rep '?' final {
800                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
801                                 0, 0, FactorWithRep::OptionalType );
802         };
803 factor_with_rep:
804         factor_with_rep '+' final {
805                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
806                                 0, 0, FactorWithRep::PlusType );
807         };
808 factor_with_rep:
809         factor_with_rep '{' factor_rep_num '}' final {
810                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
811                                 $3->rep, 0, FactorWithRep::ExactType );
812         };
813 factor_with_rep:
814         factor_with_rep '{' ',' factor_rep_num '}' final {
815                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
816                                 0, $4->rep, FactorWithRep::MaxType );
817         };
818 factor_with_rep:
819         factor_with_rep '{' factor_rep_num ',' '}' final {
820                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep,
821                                 $3->rep, 0, FactorWithRep::MinType );
822         };
823 factor_with_rep:
824         factor_with_rep '{' factor_rep_num ',' factor_rep_num '}' final {
825                 $$->factorWithRep = new FactorWithRep( $2->loc, $1->factorWithRep, 
826                                 $3->rep, $5->rep, FactorWithRep::RangeType );
827         };
828 factor_with_rep:
829         factor_with_neg final {
830                 $$->factorWithRep = new FactorWithRep( $1->factorWithNeg );
831         };
832
833 nonterm factor_rep_num
834 {
835         int rep;
836 };
837
838 factor_rep_num:
839         TK_UInt final {
840                 // Convert the priority number to a long. Check for overflow.
841                 errno = 0;
842                 int rep = strtol( $1->data, 0, 10 );
843                 if ( errno == ERANGE && rep == LONG_MAX ) {
844                         // Repetition too large. Recover by returing repetition 1. */
845                         error($1->loc) << "repetition number " << $1->data << " overflows" << endl;
846                         $$->rep = 1;
847                 }
848                 else {
849                         // Cannot be negative, so no overflow.
850                         $$->rep = rep;
851                 }
852         };
853
854
855 #
856 # The fifth level up in precedence. Negation.
857 #
858
859 nonterm factor_with_neg
860 {
861         FactorWithNeg *factorWithNeg;
862 };
863
864 factor_with_neg:
865         '!' factor_with_neg final {
866                 $$->factorWithNeg = new FactorWithNeg( $1->loc,
867                                 $2->factorWithNeg, FactorWithNeg::NegateType );
868         };
869 factor_with_neg:
870         '^' factor_with_neg final {
871                 $$->factorWithNeg = new FactorWithNeg( $1->loc,
872                                 $2->factorWithNeg, FactorWithNeg::CharNegateType );
873         };
874 factor_with_neg:
875         factor final {
876                 $$->factorWithNeg = new FactorWithNeg( $1->factor );
877         };
878
879 nonterm factor
880 {
881         Factor *factor;
882 };
883
884 factor: 
885         TK_Literal final {
886                 /* Create a new factor node going to a concat literal. */
887                 $$->factor = new Factor( new Literal( *$1, Literal::LitString ) );
888         };
889 factor: 
890         alphabet_num final {
891                 /* Create a new factor node going to a literal number. */
892                 $$->factor = new Factor( new Literal( $1->token, Literal::Number ) );
893         };
894 factor:
895         TK_Word final {
896                 /* Find the named graph. */
897                 GraphDictEl *gdNode = pd->graphDict.find( $1->data );
898                 if ( gdNode == 0 ) {
899                         /* Recover by returning null as the factor node. */
900                         error($1->loc) << "graph lookup of \"" << $1->data << "\" failed" << endl;
901                         $$->factor = 0;
902                 }
903                 else if ( gdNode->isInstance ) {
904                         /* Recover by retuning null as the factor node. */
905                         error($1->loc) << "references to graph instantiations not allowed "
906                                         "in expressions" << endl;
907                         $$->factor = 0;
908                 }
909                 else {
910                         /* Create a factor node that is a lookup of an expression. */
911                         $$->factor = new Factor( $1->loc, gdNode->value );
912                 }
913         };
914 factor:
915         RE_SqOpen regular_expr_or_data RE_SqClose final {
916                 /* Create a new factor node going to an OR expression. */
917                 $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock ) );
918         };
919 factor:
920         RE_SqOpenNeg regular_expr_or_data RE_SqClose final {
921                 /* Create a new factor node going to a negated OR expression. */
922                 $$->factor = new Factor( new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock ) );
923         };
924 factor:
925         RE_Slash regular_expr RE_Slash final {
926                 if ( $3->length > 1 ) {
927                         for ( char *p = $3->data; *p != 0; p++ ) {
928                                 if ( *p == 'i' )
929                                         $2->regExpr->caseInsensitive = true;
930                         }
931                 }
932
933                 /* Create a new factor node going to a regular exp. */
934                 $$->factor = new Factor( $2->regExpr );
935         };
936 factor:
937         range_lit TK_DotDot range_lit final {
938                 /* Create a new factor node going to a range. */
939                 $$->factor = new Factor( new Range( $1->literal, $3->literal ) );
940         };
941 factor:
942         '(' join ')' final {
943                 /* Create a new factor going to a parenthesized join. */
944                 $$->factor = new Factor( $2->join );
945         };
946
947 nonterm range_lit
948 {
949         Literal *literal;
950 };
951
952 # Literals which can be the end points of ranges.
953 range_lit:
954         TK_Literal final {
955                 /* Range literas must have only one char. We restrict this in the parse tree. */
956                 $$->literal = new Literal( *$1, Literal::LitString );
957         };
958 range_lit:
959         alphabet_num final {
960                 /* Create a new literal number. */
961                 $$->literal = new Literal( $1->token, Literal::Number );
962         };
963
964 nonterm alphabet_num uses token_type;
965
966 # Any form of a number that can be used as a basic machine. */
967 alphabet_num:
968         TK_UInt final { 
969                 $$->token = *$1;
970         };
971 alphabet_num: 
972         '-' TK_UInt final { 
973                 $$->token.set( "-", 1 );
974                 $$->token.loc = $1->loc;
975                 $$->token.append( *$2 );
976         };
977 alphabet_num: 
978         TK_Hex final { 
979                 $$->token = *$1;
980         };
981 #
982 # Regular Expressions.
983 #
984
985 nonterm regular_expr
986 {
987         RegExpr *regExpr;
988 };
989
990 # Parser for regular expression fsms. Any number of expression items which
991 # generally gives a machine one character long or one character long stared.
992 regular_expr:
993         regular_expr regular_expr_item final {
994                 /* An optimization to lessen the tree size. If a non-starred char is
995                  * directly under the left side on the right and the right side is
996                  * another non-starred char then paste them together and return the
997                  * left side. Otherwise just put the two under a new reg exp node. */
998                 if ( $2->reItem->type == ReItem::Data && !$2->reItem->star &&
999                         $1->regExpr->type == RegExpr::RecurseItem &&
1000                         $1->regExpr->item->type == ReItem::Data && !$1->regExpr->item->star )
1001                 {
1002                         /* Append the right side to the right side of the left and toss the
1003                          * right side. */
1004                         $1->regExpr->item->token.append( $2->reItem->token );
1005                         delete $2->reItem;
1006                         $$->regExpr = $1->regExpr;
1007                 }
1008                 else {
1009                         $$->regExpr = new RegExpr( $1->regExpr, $2->reItem );
1010                 }
1011         };
1012 regular_expr:
1013         final {
1014                 /* Can't optimize the tree. */
1015                 $$->regExpr = new RegExpr();
1016         };
1017
1018 nonterm regular_expr_item
1019 {
1020         ReItem *reItem;
1021 };
1022
1023 # RegularExprItems can be a character spec with an optional staring of the char.
1024 regular_expr_item:
1025         regular_expr_char RE_Star final {
1026                 $1->reItem->star = true;
1027                 $$->reItem = $1->reItem;
1028         };
1029 regular_expr_item:
1030         regular_expr_char final {
1031                 $$->reItem = $1->reItem;
1032         };
1033
1034 nonterm regular_expr_char
1035 {
1036         ReItem *reItem;
1037 };
1038
1039 # A character spec can be a set of characters inside of square parenthesis, a
1040 # dot specifying any character or some explicitly stated character.
1041 regular_expr_char:
1042         RE_SqOpen regular_expr_or_data RE_SqClose final {
1043                 $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::OrBlock );
1044         };
1045 regular_expr_char:
1046         RE_SqOpenNeg regular_expr_or_data RE_SqClose final {
1047                 $$->reItem = new ReItem( $1->loc, $2->reOrBlock, ReItem::NegOrBlock );
1048         };
1049 regular_expr_char:
1050         RE_Dot final {
1051                 $$->reItem = new ReItem( $1->loc, ReItem::Dot );
1052         };
1053 regular_expr_char:
1054         RE_Char final {
1055                 $$->reItem = new ReItem( $1->loc, *$1 );
1056         };
1057
1058 # The data inside of a [] expression in a regular expression. Accepts any
1059 # number of characters or ranges. */
1060 nonterm regular_expr_or_data
1061 {
1062         ReOrBlock *reOrBlock;
1063 };
1064
1065 regular_expr_or_data:
1066         regular_expr_or_data regular_expr_or_char final {
1067                 /* An optimization to lessen the tree size. If an or char is directly
1068                  * under the left side on the right and the right side is another or
1069                  * char then paste them together and return the left side. Otherwise
1070                  * just put the two under a new or data node. */
1071                 if ( $2->reOrItem->type == ReOrItem::Data &&
1072                                 $1->reOrBlock->type == ReOrBlock::RecurseItem &&
1073                                 $1->reOrBlock->item->type == ReOrItem::Data )
1074                 {
1075                         /* Append the right side to right side of the left and toss the
1076                          * right side. */
1077                         $1->reOrBlock->item->token.append( $2->reOrItem->token );
1078                         delete $2->reOrItem;
1079                         $$->reOrBlock = $1->reOrBlock;
1080                 }
1081                 else {
1082                         /* Can't optimize, put the left and right under a new node. */
1083                         $$->reOrBlock = new ReOrBlock( $1->reOrBlock, $2->reOrItem );
1084                 }
1085         };
1086 regular_expr_or_data:
1087         final {
1088                 $$->reOrBlock = new ReOrBlock();
1089         };
1090
1091 # A single character inside of an or expression. Can either be a character or a
1092 # set of characters.
1093 nonterm regular_expr_or_char
1094 {
1095         ReOrItem *reOrItem;
1096 };
1097
1098 regular_expr_or_char:
1099         RE_Char final {
1100                 $$->reOrItem = new ReOrItem( $1->loc, *$1 );
1101         };
1102 regular_expr_or_char:
1103         RE_Char RE_Dash RE_Char final {
1104                 $$->reOrItem = new ReOrItem( $2->loc, $1->data[0], $3->data[0] );
1105         };
1106
1107 #
1108 # Inline Lists for inline host code.
1109 #
1110
1111 type inline_list
1112 {
1113         InlineList *inlineList;
1114 };
1115
1116 nonterm inline_block uses inline_list;
1117
1118 inline_block:
1119         inline_block inline_block_item 
1120         final {
1121                 /* Append the item to the list, return the list. */
1122                 $$->inlineList = $1->inlineList;
1123                 $$->inlineList->append( $2->inlineItem );
1124         };
1125
1126 inline_block:
1127         final {
1128                 /* Start with empty list. */
1129                 $$->inlineList = new InlineList;
1130         };
1131
1132 type inline_item
1133 {
1134         InlineItem *inlineItem;
1135 };
1136
1137 nonterm inline_block_item uses inline_item;
1138 nonterm inline_block_interpret uses inline_item;
1139
1140 inline_block_item:
1141         inline_expr_any 
1142         final {
1143                 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text );
1144         };
1145
1146 inline_block_item:
1147         inline_block_symbol 
1148         final {
1149                 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text );
1150         };
1151
1152 inline_block_item:
1153         inline_block_interpret
1154         final {
1155                 /* Pass the inline item up. */
1156                 $$->inlineItem = $1->inlineItem;
1157         };
1158
1159 nonterm inline_block_symbol uses token_type;
1160
1161 inline_block_symbol: ',' final { $$->token = *$1; };
1162 inline_block_symbol: ';' final { $$->token = *$1; };
1163 inline_block_symbol: '(' final { $$->token = *$1; };
1164 inline_block_symbol: ')' final { $$->token = *$1; };
1165 inline_block_symbol: '*' final { $$->token = *$1; };
1166 inline_block_symbol: TK_NameSep final { $$->token = *$1; };
1167
1168 # Interpreted statements in a struct block. */
1169 inline_block_interpret:
1170         inline_expr_interpret final {
1171                 /* Pass up interpreted items of inline expressions. */
1172                 $$->inlineItem = $1->inlineItem;
1173         };
1174 inline_block_interpret:
1175         KW_Hold ';' final {
1176                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Hold );
1177         };
1178 inline_block_interpret:
1179         KW_Exec inline_expr ';' final {
1180                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Exec );
1181                 $$->inlineItem->children = $2->inlineList;
1182         };
1183 inline_block_interpret:
1184         KW_Goto state_ref ';' final { 
1185                 $$->inlineItem = new InlineItem( $1->loc, 
1186                                 new NameRef(nameRef), InlineItem::Goto );
1187         };
1188 inline_block_interpret:
1189         KW_Goto '*' inline_expr ';' final {
1190                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::GotoExpr );
1191                 $$->inlineItem->children = $3->inlineList;
1192         };
1193 inline_block_interpret:
1194         KW_Next state_ref ';' final { 
1195                 $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Next );
1196         };
1197 inline_block_interpret:
1198         KW_Next '*' inline_expr ';' final {
1199                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::NextExpr );
1200                 $$->inlineItem->children = $3->inlineList;
1201         };
1202 inline_block_interpret:
1203         KW_Call state_ref ';' final {
1204                 $$->inlineItem = new InlineItem( $1->loc, new NameRef(nameRef), InlineItem::Call );
1205         };
1206 inline_block_interpret:
1207         KW_Call '*' inline_expr ';' final {
1208                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::CallExpr );
1209                 $$->inlineItem->children = $3->inlineList;
1210         };
1211 inline_block_interpret:
1212         KW_Ret ';' final {
1213                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Ret );
1214         };
1215 inline_block_interpret:
1216         KW_Break ';' final {
1217                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Break );
1218         };
1219
1220 nonterm inline_expr uses inline_list;
1221
1222 inline_expr:
1223         inline_expr inline_expr_item 
1224         final {
1225                 $$->inlineList = $1->inlineList;
1226                 $$->inlineList->append( $2->inlineItem );
1227         };
1228 inline_expr:
1229         final {
1230                 /* Init the list used for this expr. */
1231                 $$->inlineList = new InlineList;
1232         };
1233
1234 nonterm inline_expr_item uses inline_item;
1235
1236 inline_expr_item: 
1237         inline_expr_any 
1238         final {
1239                 /* Return a text segment. */
1240                 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text );
1241         };
1242 inline_expr_item:
1243         inline_expr_symbol
1244         final {
1245                 /* Return a text segment, must heap alloc the text. */
1246                 $$->inlineItem = new InlineItem( $1->token.loc, $1->token.data, InlineItem::Text );
1247         };
1248 inline_expr_item:
1249         inline_expr_interpret
1250         final{
1251                 /* Pass the inline item up. */
1252                 $$->inlineItem = $1->inlineItem;
1253         };
1254
1255 nonterm inline_expr_any uses token_type;
1256
1257 inline_expr_any: IL_WhiteSpace try { $$->token = *$1; };
1258 inline_expr_any: IL_Comment try { $$->token = *$1; };
1259 inline_expr_any: IL_Literal try { $$->token = *$1; };
1260 inline_expr_any: IL_Symbol try { $$->token = *$1; };
1261 inline_expr_any: TK_UInt try { $$->token = *$1; };
1262 inline_expr_any: TK_Hex try { $$->token = *$1; };
1263 inline_expr_any: TK_Word try { $$->token = *$1; };
1264
1265 # Anything in a ExecValExpr that is not dynamically allocated. This includes
1266 # all special symbols caught in inline code except the semi.
1267
1268 nonterm inline_expr_symbol uses token_type;
1269
1270 inline_expr_symbol: ',' try { $$->token = *$1; };
1271 inline_expr_symbol: '(' try { $$->token = *$1; };
1272 inline_expr_symbol: ')' try { $$->token = *$1; };
1273 inline_expr_symbol: '*' try { $$->token = *$1; };
1274 inline_expr_symbol: TK_NameSep try { $$->token = *$1; };
1275
1276 nonterm inline_expr_interpret uses inline_item;
1277
1278 inline_expr_interpret:
1279         KW_PChar 
1280         final {
1281                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::PChar );
1282         };
1283 inline_expr_interpret:
1284         KW_Char 
1285         final {
1286                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Char );
1287         };
1288 inline_expr_interpret:
1289         KW_CurState 
1290         final {
1291                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Curs );
1292         };
1293 inline_expr_interpret:
1294         KW_TargState 
1295         final {
1296                 $$->inlineItem = new InlineItem( $1->loc, InlineItem::Targs );
1297         };
1298 inline_expr_interpret:
1299         KW_Entry '(' state_ref ')' 
1300         final {
1301                 $$->inlineItem = new InlineItem( $1->loc, 
1302                         new NameRef(nameRef), InlineItem::Entry );
1303         };
1304
1305 #  A local state reference. Cannot have :: prefix.
1306 local_state_ref:
1307         no_name_sep state_ref_names;
1308
1309 # Clear the name ref structure.
1310 no_name_sep:
1311         final {
1312                 nameRef.empty();
1313         };
1314
1315 # A qualified state reference.
1316 state_ref: opt_name_sep state_ref_names;
1317
1318 # Optional leading name separator.
1319 opt_name_sep:
1320         TK_NameSep 
1321         final {
1322                 /* Insert an initial null pointer val to indicate the existence of the
1323                  * initial name seperator. */
1324                 nameRef.setAs( 0 );
1325         };
1326 opt_name_sep:
1327         final {
1328                 nameRef.empty();
1329         };
1330
1331 # List of names separated by ::
1332 state_ref_names:
1333         state_ref_names TK_NameSep TK_Word
1334         final {
1335                 nameRef.append( $3->data );
1336         };
1337 state_ref_names:
1338         TK_Word 
1339         final {
1340                 nameRef.append( $1->data );
1341         };
1342
1343 }%%
1344
1345 %%{
1346         write types;
1347         write data;
1348 }%%
1349
1350 void Parser::init()
1351 {
1352         %% write init;
1353 }
1354
1355 int Parser::parseLangEl( int type, const Token *token )
1356 {
1357         %% write exec;
1358         return errCount == 0 ? 0 : -1;
1359 }
1360
1361 void Parser::tryMachineDef( InputLoc &loc, char *name, 
1362                 JoinOrLm *joinOrLm, bool isInstance )
1363 {
1364         GraphDictEl *newEl = pd->graphDict.insert( name );
1365         if ( newEl != 0 ) {
1366                 /* New element in the dict, all good. */
1367                 newEl->value = new VarDef( name, joinOrLm );
1368                 newEl->isInstance = isInstance;
1369                 newEl->loc = loc;
1370
1371                 /* It it is an instance, put on the instance list. */
1372                 if ( isInstance )
1373                         pd->instanceList.append( newEl );
1374         }
1375         else {
1376                 // Recover by ignoring the duplicate.
1377                 error(loc) << "fsm \"" << name << "\" previously defined" << endl;
1378         }
1379 }
1380
1381 ostream &Parser::parse_error( int tokId, Token &token )
1382 {
1383         /* Maintain the error count. */
1384         gblErrorCount += 1;
1385
1386         cerr << token.loc.fileName << ":" << token.loc.line << ":" << token.loc.col << ": ";
1387         cerr << "at token ";
1388         if ( tokId < 128 )
1389                 cerr << "\"" << Parser_lelNames[tokId] << "\"";
1390         else 
1391                 cerr << Parser_lelNames[tokId];
1392         if ( token.data != 0 )
1393                 cerr << " with data \"" << token.data << "\"";
1394         cerr << ": ";
1395         
1396         return cerr;
1397 }
1398
1399 int Parser::token( InputLoc &loc, int tokId, char *tokstart, int toklen )
1400 {
1401         Token token;
1402         token.data = tokstart;
1403         token.length = toklen;
1404         token.loc = loc;
1405         int res = parseLangEl( tokId, &token );
1406         if ( res < 0 ) {
1407                 parse_error(tokId, token) << "parse error" << endl;
1408                 exit(1);
1409         }
1410         return res;
1411 }