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