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