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