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