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