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