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