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