2 * Copyright 2001-2007 Adrian Thurston <thurston@complang.org>
5 /* This file is part of Ragel.
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.
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.
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
35 Key readKey( char *td, char **end );
36 long readOffsetPtr( char *td, char **end );
37 unsigned long readLength( char *td );
49 include "xmlparse.kh";
54 /* If we get no input the assumption is that the frontend died and
55 * emitted an error. This forces the backend to return a non-zero
56 * exit status, but does not print an error. */
60 tag_ragel: tag_ragel_head ragel_def_list host_or_write_list '/' TAG_ragel;
62 tag_ragel_head: TAG_ragel
64 /* Check version used to generated the intermediate file. */
65 Attribute *versionAttr = $1->tag->findAttr( "version" );
66 if ( versionAttr == 0 )
67 error($1->loc) << "tag <ragel> requires a version attribute" << endp;
68 if ( strcmp( versionAttr->value, VERSION ) != 0 )
69 error($1->loc) << "version mismatch between frontend and backend" << endp;
71 /* Check for file name attribute. */
72 Attribute *fileNameAttr = $1->tag->findAttr( "filename" );
73 if ( fileNameAttr == 0 )
74 error($1->loc) << "tag <ragel> requires a filename attribute" << endp;
75 sourceFileName = fileNameAttr->value;
77 /* Check for language attribute. */
78 Attribute *langAttr = $1->tag->findAttr( "lang" );
80 error($1->loc) << "tag <ragel> requires a lang attribute" << endp;
83 outStream = dotOpenOutput( sourceFileName );
84 else if ( strcmp( langAttr->value, "C" ) == 0 ) {
85 hostLang = &hostLangC;
86 outStream = cdOpenOutput( sourceFileName );
88 else if ( strcmp( langAttr->value, "D" ) == 0 ) {
89 hostLang = &hostLangD;
90 outStream = cdOpenOutput( sourceFileName );
92 else if ( strcmp( langAttr->value, "Java" ) == 0 ) {
93 hostLang = &hostLangJava;
94 outStream = javaOpenOutput( sourceFileName );
96 else if ( strcmp( langAttr->value, "Ruby" ) == 0 ) {
97 hostLang = &hostLangRuby;
98 outStream = rubyOpenOutput( sourceFileName );
100 else if ( strcmp( langAttr->value, "C#" ) == 0 ) {
101 hostLang = &hostLangCSharp;
102 outStream = csharpOpenOutput( sourceFileName );
105 error($1->loc) << "expecting lang attribute to be "
106 "one of C, D, Java, Ruby or C#" << endp;
110 ragel_def_list: ragel_def_list ragel_def;
113 host_or_write_list: host_or_write_list host_or_write;
114 host_or_write_list: ;
116 host_or_write: tag_host;
117 host_or_write: tag_write;
120 TAG_host '/' TAG_host
122 Attribute *lineAttr = $1->tag->findAttr( "line" );
124 error($1->loc) << "tag <host> requires a line attribute" << endp;
126 int line = atoi( lineAttr->value );
128 lineDirective( *outStream, sourceFileName, line );
132 *outStream << $3->tag->content;
136 tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def
138 /* Do this before distributing transitions out to singles and defaults
139 * makes life easier. */
140 cgd->redFsm->maxKey = cgd->findMaxKey();
142 cgd->redFsm->assignActionLocs();
144 /* Find the first final state (The final state with the lowest id). */
145 cgd->redFsm->findFirstFinState();
147 /* Call the user's callback. */
148 cgd->finishRagelDef();
151 tag_ragel_def_head: TAG_ragel_def
154 Attribute *nameAttr = $1->tag->findAttr( "name" );
155 if ( nameAttr != 0 ) {
156 fsmName = nameAttr->value;
158 CodeGenMapEl *mapEl = codeGenMap.find( fsmName );
162 cgd = makeCodeGen( sourceFileName, fsmName, *outStream, wantComplete );
163 codeGenMap.insert( fsmName, cgd );
167 cgd = makeCodeGen( sourceFileName, fsmName,
168 *outStream, wantComplete );
171 ::keyOps = &cgd->thisKeyOps;
174 ragel_def_item_list: ragel_def_item_list ragel_def_item;
175 ragel_def_item_list: ;
177 ragel_def_item: tag_alph_type;
178 ragel_def_item: tag_getkey_expr;
179 ragel_def_item: tag_access_expr;
180 ragel_def_item: tag_prepush_expr;
181 ragel_def_item: tag_postpop_expr;
182 ragel_def_item: tag_export_list;
183 ragel_def_item: tag_machine;
184 ragel_def_item: tag_p_expr;
185 ragel_def_item: tag_pe_expr;
186 ragel_def_item: tag_eof_expr;
187 ragel_def_item: tag_cs_expr;
188 ragel_def_item: tag_top_expr;
189 ragel_def_item: tag_stack_expr;
190 ragel_def_item: tag_act_expr;
191 ragel_def_item: tag_tokstart_expr;
192 ragel_def_item: tag_tokend_expr;
193 ragel_def_item: tag_data_expr;
195 tag_export_list: TAG_exports export_list '/' TAG_exports;
197 export_list: export_list tag_export;
200 tag_export: TAG_ex '/' TAG_ex
202 Attribute *nameAttr = $1->tag->findAttr( "name" );
204 error($1->loc) << "tag <ex> requires a name attribute" << endp;
206 char *td = $3->tag->content;
207 Key exportKey = readKey( td, &td );
208 cgd->exportList.append( new Export( nameAttr->value, exportKey ) );
212 tag_alph_type: TAG_alphtype '/' TAG_alphtype
214 if ( ! cgd->setAlphType( $3->tag->content ) )
215 error($1->loc) << "tag <alphtype> specifies unknown alphabet type" << endp;
218 tag_getkey_expr: TAG_getkey inline_list '/' TAG_getkey
220 cgd->getKeyExpr = $2->inlineList;
223 tag_access_expr: TAG_access inline_list '/' TAG_access
225 cgd->accessExpr = $2->inlineList;
228 tag_prepush_expr: TAG_prepush inline_list '/' TAG_prepush
230 cgd->prePushExpr = $2->inlineList;
233 tag_postpop_expr: TAG_postpop inline_list '/' TAG_postpop
235 cgd->postPopExpr = $2->inlineList;
238 tag_p_expr: TAG_p_expr inline_list '/' TAG_p_expr
239 final { cgd->pExpr = $2->inlineList; };
240 tag_pe_expr: TAG_pe_expr inline_list '/' TAG_pe_expr
241 final { cgd->peExpr = $2->inlineList; };
242 tag_eof_expr: TAG_eof_expr inline_list '/' TAG_eof_expr
243 final { cgd->eofExpr = $2->inlineList; };
244 tag_cs_expr: TAG_cs_expr inline_list '/' TAG_cs_expr
245 final { cgd->csExpr = $2->inlineList; };
246 tag_top_expr: TAG_top_expr inline_list '/' TAG_top_expr
247 final { cgd->topExpr = $2->inlineList; };
248 tag_stack_expr: TAG_stack_expr inline_list '/' TAG_stack_expr
249 final { cgd->stackExpr = $2->inlineList; };
250 tag_act_expr: TAG_act_expr inline_list '/' TAG_act_expr
251 final { cgd->actExpr = $2->inlineList; };
252 tag_tokstart_expr: TAG_tokstart_expr inline_list '/' TAG_tokstart_expr
253 final { cgd->tokstartExpr = $2->inlineList; };
254 tag_tokend_expr: TAG_tokend_expr inline_list '/' TAG_tokend_expr
255 final { cgd->tokendExpr = $2->inlineList; };
256 tag_data_expr: TAG_data_expr inline_list '/' TAG_data_expr
257 final { cgd->dataExpr = $2->inlineList; };
260 tag_write: tag_write_head write_option_list '/' TAG_write
262 /* Terminate the options list and call the write statement handler. */
263 writeOptions.append(0);
264 cgd->writeStatement( $1->loc, writeOptions.length()-1, writeOptions.data );
266 /* Clear the options in prep for the next write statement. */
267 writeOptions.empty();
270 nonterm tag_write_head
275 tag_write_head: TAG_write
277 Attribute *nameAttr = $1->tag->findAttr( "def_name" );
278 Attribute *lineAttr = $1->tag->findAttr( "line" );
279 Attribute *colAttr = $1->tag->findAttr( "col" );
282 error($1->loc) << "tag <write> requires a def_name attribute" << endp;
284 error($1->loc) << "tag <write> requires a line attribute" << endp;
286 error($1->loc) << "tag <write> requires a col attribute" << endp;
288 if ( nameAttr != 0 && lineAttr != 0 && colAttr != 0 ) {
289 $$->loc.line = atoi(lineAttr->value);
290 $$->loc.col = atoi(colAttr->value);
292 CodeGenMapEl *mapEl = codeGenMap.find( nameAttr->value );
294 source_error($$->loc) << "write statement given "
295 "but there are no machine instantiations" << endp;
299 ::keyOps = &cgd->thisKeyOps;
305 write_option_list: write_option_list tag_arg;
313 tag_arg: TAG_arg '/' TAG_arg
315 writeOptions.append( $3->tag->content );
318 tag_machine: tag_machine_head machine_item_list '/' TAG_machine
323 tag_machine_head: TAG_machine
325 cgd->createMachine();
328 machine_item_list: machine_item_list machine_item;
331 machine_item: tag_start_state;
332 machine_item: tag_error_state;
333 machine_item: tag_entry_points;
334 machine_item: tag_state_list;
335 machine_item: tag_action_list;
336 machine_item: tag_action_table_list;
337 machine_item: tag_cond_space_list;
343 tag_start_state: TAG_start_state '/' TAG_start_state
345 unsigned long startState = strtoul( $3->tag->content, 0, 10 );
346 cgd->setStartState( startState );
349 tag_error_state: TAG_error_state '/' TAG_error_state
351 unsigned long errorState = strtoul( $3->tag->content, 0, 10 );
352 cgd->setErrorState( errorState );
355 tag_entry_points: TAG_entry_points entry_point_list '/' TAG_entry_points
357 Attribute *errorAttr = $1->tag->findAttr( "error" );
358 if ( errorAttr != 0 )
359 cgd->setForcedErrorState();
362 entry_point_list: entry_point_list tag_entry;
365 tag_entry: TAG_entry '/' TAG_entry
367 Attribute *nameAttr = $1->tag->findAttr( "name" );
368 if ( nameAttr == 0 ) {
369 error($1->loc) << "tag <entry_points>::<entry> "
370 "requires a name attribute" << endp;
373 char *data = $3->tag->content;
374 unsigned long entry = strtoul( data, &data, 10 );
375 cgd->addEntryPoint( nameAttr->value, entry );
379 tag_state_list: tag_state_list_head state_list '/' TAG_state_list;
381 tag_state_list_head: TAG_state_list
383 Attribute *lengthAttr = $1->tag->findAttr( "length" );
384 if ( lengthAttr == 0 )
385 error($1->loc) << "tag <state_list> requires a length attribute" << endp;
387 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
388 cgd->initStateList( length );
393 state_list: state_list tag_state;
396 tag_state: TAG_state state_item_list '/' TAG_state
398 Attribute *idAttr = $1->tag->findAttr( "id" );
400 error($1->loc) << "tag <state> requires an id attribute" << endp;
402 int id = atoi( idAttr->value );
403 cgd->setId( curState, id );
406 Attribute *lengthAttr = $1->tag->findAttr( "final" );
407 if ( lengthAttr != 0 )
408 cgd->setFinal( curState );
412 state_item_list: state_item_list state_item;
415 state_item: tag_state_actions;
416 state_item: tag_eof_t;
417 state_item: tag_state_cond_list;
418 state_item: tag_trans_list;
420 tag_state_actions: TAG_state_actions '/' TAG_state_actions
422 char *ad = $3->tag->content;
424 long toStateAction = readOffsetPtr( ad, &ad );
425 long fromStateAction = readOffsetPtr( ad, &ad );
426 long eofAction = readOffsetPtr( ad, &ad );
428 cgd->setStateActions( curState, toStateAction,
429 fromStateAction, eofAction );
432 tag_eof_t: TAG_eof_t '/' TAG_eof_t
434 char *et = $3->tag->content;
435 long targ = readOffsetPtr( et, &et );
436 long eofAction = readOffsetPtr( et, &et );
438 cgd->setEofTrans( curState, targ, eofAction );
441 tag_state_cond_list: tag_state_cond_list_head state_cond_list '/' TAG_cond_list;
443 tag_state_cond_list_head: TAG_cond_list
445 Attribute *lengthAttr = $1->tag->findAttr( "length" );
446 if ( lengthAttr == 0 )
447 error($1->loc) << "tag <cond_list> requires a length attribute" << endp;
449 ulong length = readLength( lengthAttr->value );
450 cgd->initStateCondList( curState, length );
455 state_cond_list: state_cond_list state_cond;
458 state_cond: TAG_c '/' TAG_c
460 char *td = $3->tag->content;
461 Key lowKey = readKey( td, &td );
462 Key highKey = readKey( td, &td );
463 long condId = readOffsetPtr( td, &td );
464 cgd->addStateCond( curState, lowKey, highKey, condId );
467 tag_trans_list: tag_trans_list_head trans_list '/' TAG_trans_list
469 cgd->finishTransList( curState );
472 tag_trans_list_head: TAG_trans_list
474 Attribute *lengthAttr = $1->tag->findAttr( "length" );
475 if ( lengthAttr == 0 )
476 error($1->loc) << "tag <trans_list> requires a length attribute" << endp;
478 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
479 cgd->initTransList( curState, length );
484 trans_list: trans_list tag_trans;
487 tag_trans: TAG_t '/' TAG_t
489 char *td = $3->tag->content;
490 Key lowKey = readKey( td, &td );
491 Key highKey = readKey( td, &td );
492 long targ = readOffsetPtr( td, &td );
493 long action = readOffsetPtr( td, &td );
495 cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
502 tag_action_list: tag_action_list_head action_list '/' TAG_action_list;
504 tag_action_list_head: TAG_action_list
506 Attribute *lengthAttr = $1->tag->findAttr( "length" );
507 if ( lengthAttr == 0 )
508 error($1->loc) << "tag <action_list> requires a length attribute" << endp;
510 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
511 cgd->initActionList( length );
516 action_list: action_list tag_action;
523 tag_action: TAG_action inline_list '/' TAG_action
525 Attribute *lineAttr = $1->tag->findAttr( "line" );
526 Attribute *colAttr = $1->tag->findAttr( "col" );
527 Attribute *nameAttr = $1->tag->findAttr( "name" );
528 if ( lineAttr == 0 || colAttr == 0)
529 error($1->loc) << "tag <action> requires a line and col attributes" << endp;
531 unsigned long line = strtoul( lineAttr->value, 0, 10 );
532 unsigned long col = strtoul( colAttr->value, 0, 10 );
536 name = nameAttr->value;
538 cgd->newAction( curAction++, name, line, col, $2->inlineList );
544 GenInlineList *inlineList;
548 inline_list: inline_list inline_item
550 /* Append the item to the list, return the list. */
551 $1->inlineList->append( $2->inlineItem );
552 $$->inlineList = $1->inlineList;
557 /* Start with empty list. */
558 $$->inlineList = new GenInlineList;
561 nonterm inline_item_type
563 GenInlineItem *inlineItem;
566 nonterm inline_item uses inline_item_type;
568 inline_item: tag_text final { $$->inlineItem = $1->inlineItem; };
569 inline_item: tag_goto final { $$->inlineItem = $1->inlineItem; };
570 inline_item: tag_call final { $$->inlineItem = $1->inlineItem; };
571 inline_item: tag_next final { $$->inlineItem = $1->inlineItem; };
572 inline_item: tag_goto_expr final { $$->inlineItem = $1->inlineItem; };
573 inline_item: tag_call_expr final { $$->inlineItem = $1->inlineItem; };
574 inline_item: tag_next_expr final { $$->inlineItem = $1->inlineItem; };
575 inline_item: tag_ret final { $$->inlineItem = $1->inlineItem; };
576 inline_item: tag_break final { $$->inlineItem = $1->inlineItem; };
577 inline_item: tag_pchar final { $$->inlineItem = $1->inlineItem; };
578 inline_item: tag_char final { $$->inlineItem = $1->inlineItem; };
579 inline_item: tag_hold final { $$->inlineItem = $1->inlineItem; };
580 inline_item: tag_exec final { $$->inlineItem = $1->inlineItem; };
581 inline_item: tag_curs final { $$->inlineItem = $1->inlineItem; };
582 inline_item: tag_targs final { $$->inlineItem = $1->inlineItem; };
583 inline_item: tag_il_entry final { $$->inlineItem = $1->inlineItem; };
584 inline_item: tag_init_tokstart final { $$->inlineItem = $1->inlineItem; };
585 inline_item: tag_init_act final { $$->inlineItem = $1->inlineItem; };
586 inline_item: tag_get_tokend final { $$->inlineItem = $1->inlineItem; };
587 inline_item: tag_set_tokstart final { $$->inlineItem = $1->inlineItem; };
588 inline_item: tag_set_tokend final { $$->inlineItem = $1->inlineItem; };
589 inline_item: tag_set_act final { $$->inlineItem = $1->inlineItem; };
590 inline_item: tag_sub_action final { $$->inlineItem = $1->inlineItem; };
591 inline_item: tag_lm_switch final { $$->inlineItem = $1->inlineItem; };
593 nonterm tag_text uses inline_item_type;
594 nonterm tag_goto uses inline_item_type;
595 nonterm tag_call uses inline_item_type;
596 nonterm tag_next uses inline_item_type;
597 nonterm tag_goto_expr uses inline_item_type;
598 nonterm tag_call_expr uses inline_item_type;
599 nonterm tag_next_expr uses inline_item_type;
600 nonterm tag_ret uses inline_item_type;
601 nonterm tag_break uses inline_item_type;
602 nonterm tag_pchar uses inline_item_type;
603 nonterm tag_char uses inline_item_type;
604 nonterm tag_hold uses inline_item_type;
605 nonterm tag_exec uses inline_item_type;
606 nonterm tag_curs uses inline_item_type;
607 nonterm tag_targs uses inline_item_type;
608 nonterm tag_il_entry uses inline_item_type;
609 nonterm tag_init_tokstart uses inline_item_type;
610 nonterm tag_init_act uses inline_item_type;
611 nonterm tag_get_tokend uses inline_item_type;
612 nonterm tag_set_tokstart uses inline_item_type;
613 nonterm tag_set_tokend uses inline_item_type;
614 nonterm tag_set_act uses inline_item_type;
615 nonterm tag_sub_action uses inline_item_type;
616 nonterm tag_lm_switch uses inline_item_type;
618 tag_text: TAG_text '/' TAG_text
620 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text );
621 $$->inlineItem->data = $3->tag->content;
624 tag_goto: TAG_goto '/' TAG_goto
626 int targ = strtol( $3->tag->content, 0, 10 );
627 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto );
628 $$->inlineItem->targId = targ;
631 tag_call: TAG_call '/' TAG_call
633 int targ = strtol( $3->tag->content, 0, 10 );
634 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Call );
635 $$->inlineItem->targId = targ;
638 tag_next: TAG_next '/' TAG_next
640 int targ = strtol( $3->tag->content, 0, 10 );
641 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Next );
642 $$->inlineItem->targId = targ;
645 tag_goto_expr: TAG_goto_expr inline_list '/' TAG_goto_expr
647 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::GotoExpr );
648 $$->inlineItem->children = $2->inlineList;
651 tag_call_expr: TAG_call_expr inline_list '/' TAG_call_expr
653 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::CallExpr );
654 $$->inlineItem->children = $2->inlineList;
657 tag_next_expr: TAG_next_expr inline_list '/' TAG_next_expr
659 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::NextExpr );
660 $$->inlineItem->children = $2->inlineList;
663 tag_ret: TAG_ret '/' TAG_ret
665 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Ret );
668 tag_break: TAG_break '/' TAG_break
670 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Break );
673 tag_pchar: TAG_pchar '/' TAG_pchar
675 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::PChar );
678 tag_char: TAG_char '/' TAG_char
680 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Char );
683 tag_hold: TAG_hold '/' TAG_hold
685 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Hold );
688 tag_exec: TAG_exec inline_list '/' TAG_exec
690 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec );
691 $$->inlineItem->children = $2->inlineList;
694 tag_curs: TAG_curs '/' TAG_curs
696 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Curs );
699 tag_targs: TAG_targs '/' TAG_targs
701 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Targs );
704 tag_il_entry: TAG_entry '/' TAG_entry
706 int targ = strtol( $3->tag->content, 0, 10 );
707 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Entry );
708 $$->inlineItem->targId = targ;
711 tag_init_tokstart: TAG_init_tokstart '/' TAG_init_tokstart
713 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart );
716 tag_init_act: TAG_init_act '/' TAG_init_act
718 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct );
721 tag_get_tokend: TAG_get_tokend '/' TAG_get_tokend
723 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd );
726 tag_set_tokstart: TAG_set_tokstart '/' TAG_set_tokstart
728 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart );
729 cgd->hasLongestMatch = true;
732 tag_set_tokend: TAG_set_tokend '/' TAG_set_tokend
734 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd );
735 $$->inlineItem->offset = strtol( $3->tag->content, 0, 10 );
738 tag_set_act: TAG_set_act '/' TAG_set_act
740 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId );
741 $$->inlineItem->lmId = strtol( $3->tag->content, 0, 10 );
744 tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action
746 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
747 $$->inlineItem->children = $2->inlineList;
751 tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch
753 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch );
754 $$->inlineItem->children = $2->inlineList;
757 nonterm lm_action_list
759 GenInlineList *inlineList;
762 lm_action_list: lm_action_list tag_inline_action
764 $$->inlineList = $1->inlineList;
765 $$->inlineList->append( $2->inlineItem );
769 $$->inlineList = new GenInlineList;
772 nonterm tag_inline_action uses inline_item_type;
774 tag_inline_action: TAG_sub_action inline_list '/' TAG_sub_action
776 $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::SubAction );
777 $$->inlineItem->children = $2->inlineList;
779 Attribute *idAttr = $1->tag->findAttr( "id" );
781 unsigned long id = strtoul( idAttr->value, 0, 10 );
782 $$->inlineItem->lmId = id;
790 tag_action_table_list:
791 tag_action_table_list_head action_table_list '/' TAG_action_table_list;
793 tag_action_table_list_head: TAG_action_table_list
795 Attribute *lengthAttr = $1->tag->findAttr( "length" );
796 if ( lengthAttr == 0 ) {
797 error($1->loc) << "tag <action_table_list> requires "
798 "a length attribute" << endp;
801 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
802 cgd->initActionTableList( length );
807 action_table_list: action_table_list tag_action_table;
810 tag_action_table: TAG_action_table '/' TAG_action_table
812 /* Find the length of the action table. */
813 Attribute *lengthAttr = $1->tag->findAttr( "length" );
814 if ( lengthAttr == 0 )
815 error($1->loc) << "tag <at> requires a length attribute" << endp;
817 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
819 /* Collect the action table. */
820 RedAction *redAct = cgd->allActionTables + curActionTable;
821 redAct->actListId = curActionTable;
822 redAct->key.setAsNew( length );
823 char *ptr = $3->tag->content;
825 while ( *ptr != 0 ) {
826 unsigned long actionId = strtoul( ptr, &ptr, 10 );
827 redAct->key[pos].key = 0;
828 redAct->key[pos].value = cgd->allActions+actionId;
832 /* Insert into the action table map. */
833 cgd->redFsm->actionMap.insert( redAct );
843 tag_cond_space_list: tag_cond_space_list_head cond_space_list '/' TAG_cond_space_list;
845 tag_cond_space_list_head: TAG_cond_space_list
847 Attribute *lengthAttr = $1->tag->findAttr( "length" );
848 if ( lengthAttr == 0 ) {
849 error($1->loc) << "tag <cond_space_list> "
850 "requires a length attribute" << endp;
853 ulong length = readLength( lengthAttr->value );
854 cgd->initCondSpaceList( length );
859 cond_space_list: cond_space_list tag_cond_space;
860 cond_space_list: tag_cond_space;
862 tag_cond_space: TAG_cond_space '/' TAG_cond_space
864 Attribute *lengthAttr = $1->tag->findAttr( "length" );
865 Attribute *idAttr = $1->tag->findAttr( "id" );
866 if ( lengthAttr == 0 )
867 error($1->loc) << "tag <cond_space> requires a length attribute" << endp;
869 if ( lengthAttr == 0 )
870 error($1->loc) << "tag <cond_space> requires an id attribute" << endp;
872 unsigned long condSpaceId = strtoul( idAttr->value, 0, 10 );
873 ulong length = readLength( lengthAttr->value );
875 char *td = $3->tag->content;
876 Key baseKey = readKey( td, &td );
878 cgd->newCondSpace( curCondSpace, condSpaceId, baseKey );
879 for ( ulong a = 0; a < length; a++ ) {
880 long actionOffset = readOffsetPtr( td, &td );
881 cgd->condSpaceItem( curCondSpace, actionOffset );
895 void XmlParser::init()
900 int XmlParser::parseLangEl( int type, const Token *token )
903 return errCount == 0 ? 0 : -1;
907 unsigned long readLength( char *td )
909 return strtoul( td, 0, 10 );
912 Key readKey( char *td, char **end )
914 if ( keyOps->isSigned )
915 return Key( strtol( td, end, 10 ) );
917 return Key( strtoul( td, end, 10 ) );
920 long readOffsetPtr( char *td, char **end )
922 while ( *td == ' ' || *td == '\t' )
931 return strtol( td, end, 10 );
934 ostream &XmlParser::warning( const InputLoc &loc )
936 cerr << fileName << ":" << loc.line << ":" << loc.col << ": warning: ";
940 ostream &XmlParser::error( const InputLoc &loc )
943 assert( fileName != 0 );
944 cerr << fileName << ":" << loc.line << ":" << loc.col << ": ";
949 ostream &XmlParser::parser_error( int tokId, Token &token )
952 assert( fileName != 0 );
953 cerr << fileName << ":" << token.loc.line << ":" << token.loc.col;
954 if ( token.tag != 0 ) {
955 if ( token.tag->tagId == 0 )
956 cerr << ": at unknown tag";
958 cerr << ": at tag <" << token.tag->tagId->name << ">";
965 ostream &XmlParser::source_error( const InputLoc &loc )
968 assert( sourceFileName != 0 );
969 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
974 int XmlParser::token( int tokenId, Token &tok )
976 int res = parseLangEl( tokenId, &tok );
978 parser_error( tokenId, tok ) << "parse error" << endp;
982 int XmlParser::token( int tokenId, int col, int line )
988 return token( tokenId, tok );
991 int XmlParser::token( XMLTag *tag, int col, int line )
998 if ( tag->type == XMLTag::Close ) {
999 int res = token( '/', tok );
1005 return token( tag->tagId != 0 ? tag->tagId->id : TAG_unknown, tok );