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