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 );
45 CodeGenData *makeCodeGen( const char *sourceFileName, const char *fsmName,
46 ostream &out, bool wantComplete )
50 cgd = dotMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
51 else if ( hostLang == &hostLangC )
52 cgd = cdMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
53 else if ( hostLang == &hostLangD )
54 cgd = cdMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
55 else if ( hostLang == &hostLangJava )
56 cgd = javaMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
57 else if ( hostLang == &hostLangRuby )
58 cgd = rubyMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
59 else if ( hostLang == &hostLangCSharp )
60 cgd = csharpMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
64 void lineDirective( ostream &out, const char *fileName, int line )
67 if ( hostLang == &hostLangC )
68 cdLineDirective( out, fileName, line );
69 else if ( hostLang == &hostLangD )
70 cdLineDirective( out, fileName, line );
71 else if ( hostLang == &hostLangJava )
72 javaLineDirective( out, fileName, line );
73 else if ( hostLang == &hostLangRuby )
74 rubyLineDirective( out, fileName, line );
75 else if ( hostLang == &hostLangCSharp )
76 csharpLineDirective( out, fileName, line );
80 void genLineDirective( ostream &out )
82 std::streambuf *sbuf = out.rdbuf();
83 output_filter *filter = static_cast<output_filter*>(sbuf);
84 lineDirective( out, filter->fileName, filter->line + 1 );
87 void XmlParser::ragel( const char *fileName )
89 /* Check for file name attribute. */
90 sourceFileName = fileName;
93 outStream = dotOpenOutput( sourceFileName );
94 else if ( hostLang->lang == HostLang::C ) {
95 hostLang = &hostLangC;
96 outStream = cdOpenOutput( sourceFileName );
98 else if ( hostLang->lang == HostLang::D ) {
99 hostLang = &hostLangD;
100 outStream = cdOpenOutput( sourceFileName );
102 else if ( hostLang->lang == HostLang::Java ) {
103 hostLang = &hostLangJava;
104 outStream = javaOpenOutput( sourceFileName );
106 else if ( hostLang->lang == HostLang::Ruby ) {
107 hostLang = &hostLangRuby;
108 outStream = rubyOpenOutput( sourceFileName );
110 else if ( hostLang->lang == HostLang::CSharp ) {
111 hostLang = &hostLangCSharp;
112 outStream = csharpOpenOutput( sourceFileName );
122 include "xmlparse.kh";
124 start: ragel_def_list host_or_write_list;
126 ragel_def_list: ragel_def_list ragel_def;
129 host_or_write_list: host_or_write_list host_or_write;
130 host_or_write_list: ;
132 host_or_write: tag_host;
133 host_or_write: tag_write;
136 TAG_host '/' TAG_host
138 Attribute *lineAttr = $1->tag->findAttr( "line" );
140 error($1->loc) << "tag <host> requires a line attribute" << endp;
142 int line = atoi( lineAttr->value );
144 lineDirective( *outStream, sourceFileName, line );
148 *outStream << $3->tag->content;
152 tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def
154 /* Do this before distributing transitions out to singles and defaults
155 * makes life easier. */
156 cgd->redFsm->maxKey = cgd->findMaxKey();
158 cgd->redFsm->assignActionLocs();
160 /* Find the first final state (The final state with the lowest id). */
161 cgd->redFsm->findFirstFinState();
163 /* Call the user's callback. */
164 cgd->finishRagelDef();
167 tag_ragel_def_head: TAG_ragel_def
170 Attribute *nameAttr = $1->tag->findAttr( "name" );
171 if ( nameAttr != 0 ) {
172 fsmName = nameAttr->value;
174 CodeGenMapEl *mapEl = codeGenMap.find( fsmName );
178 cgd = makeCodeGen( sourceFileName, fsmName, *outStream, wantComplete );
179 codeGenMap.insert( fsmName, cgd );
183 cgd = makeCodeGen( sourceFileName, fsmName,
184 *outStream, wantComplete );
187 ::keyOps = &cgd->thisKeyOps;
190 ragel_def_item_list: ragel_def_item_list ragel_def_item;
191 ragel_def_item_list: ;
193 ragel_def_item: tag_alph_type;
194 ragel_def_item: tag_getkey_expr;
195 ragel_def_item: tag_access_expr;
196 ragel_def_item: tag_prepush_expr;
197 ragel_def_item: tag_postpop_expr;
198 ragel_def_item: tag_export_list;
199 ragel_def_item: tag_machine;
200 ragel_def_item: tag_p_expr;
201 ragel_def_item: tag_pe_expr;
202 ragel_def_item: tag_eof_expr;
203 ragel_def_item: tag_cs_expr;
204 ragel_def_item: tag_top_expr;
205 ragel_def_item: tag_stack_expr;
206 ragel_def_item: tag_act_expr;
207 ragel_def_item: tag_tokstart_expr;
208 ragel_def_item: tag_tokend_expr;
209 ragel_def_item: tag_data_expr;
211 tag_export_list: TAG_exports export_list '/' TAG_exports;
213 export_list: export_list tag_export;
216 tag_export: TAG_ex '/' TAG_ex
218 Attribute *nameAttr = $1->tag->findAttr( "name" );
220 error($1->loc) << "tag <ex> requires a name attribute" << endp;
222 char *td = $3->tag->content;
223 Key exportKey = readKey( td, &td );
224 cgd->exportList.append( new Export( nameAttr->value, exportKey ) );
228 tag_alph_type: TAG_alphtype '/' TAG_alphtype
230 if ( ! cgd->setAlphType( $3->tag->content ) )
231 error($1->loc) << "tag <alphtype> specifies unknown alphabet type" << endp;
234 tag_getkey_expr: TAG_getkey inline_list '/' TAG_getkey
236 cgd->getKeyExpr = $2->inlineList;
239 tag_access_expr: TAG_access inline_list '/' TAG_access
241 cgd->accessExpr = $2->inlineList;
244 tag_prepush_expr: TAG_prepush inline_list '/' TAG_prepush
246 cgd->prePushExpr = $2->inlineList;
249 tag_postpop_expr: TAG_postpop inline_list '/' TAG_postpop
251 cgd->postPopExpr = $2->inlineList;
254 tag_p_expr: TAG_p_expr inline_list '/' TAG_p_expr
255 final { cgd->pExpr = $2->inlineList; };
256 tag_pe_expr: TAG_pe_expr inline_list '/' TAG_pe_expr
257 final { cgd->peExpr = $2->inlineList; };
258 tag_eof_expr: TAG_eof_expr inline_list '/' TAG_eof_expr
259 final { cgd->eofExpr = $2->inlineList; };
260 tag_cs_expr: TAG_cs_expr inline_list '/' TAG_cs_expr
261 final { cgd->csExpr = $2->inlineList; };
262 tag_top_expr: TAG_top_expr inline_list '/' TAG_top_expr
263 final { cgd->topExpr = $2->inlineList; };
264 tag_stack_expr: TAG_stack_expr inline_list '/' TAG_stack_expr
265 final { cgd->stackExpr = $2->inlineList; };
266 tag_act_expr: TAG_act_expr inline_list '/' TAG_act_expr
267 final { cgd->actExpr = $2->inlineList; };
268 tag_tokstart_expr: TAG_tokstart_expr inline_list '/' TAG_tokstart_expr
269 final { cgd->tokstartExpr = $2->inlineList; };
270 tag_tokend_expr: TAG_tokend_expr inline_list '/' TAG_tokend_expr
271 final { cgd->tokendExpr = $2->inlineList; };
272 tag_data_expr: TAG_data_expr inline_list '/' TAG_data_expr
273 final { cgd->dataExpr = $2->inlineList; };
276 tag_write: tag_write_head write_option_list '/' TAG_write
278 /* Terminate the options list and call the write statement handler. */
279 writeOptions.append(0);
280 cgd->writeStatement( $1->loc, writeOptions.length()-1, writeOptions.data );
282 /* Clear the options in prep for the next write statement. */
283 writeOptions.empty();
286 nonterm tag_write_head
291 tag_write_head: TAG_write
293 Attribute *nameAttr = $1->tag->findAttr( "def_name" );
294 Attribute *lineAttr = $1->tag->findAttr( "line" );
295 Attribute *colAttr = $1->tag->findAttr( "col" );
298 error($1->loc) << "tag <write> requires a def_name attribute" << endp;
300 error($1->loc) << "tag <write> requires a line attribute" << endp;
302 error($1->loc) << "tag <write> requires a col attribute" << endp;
304 if ( nameAttr != 0 && lineAttr != 0 && colAttr != 0 ) {
305 $$->loc.line = atoi(lineAttr->value);
306 $$->loc.col = atoi(colAttr->value);
308 CodeGenMapEl *mapEl = codeGenMap.find( nameAttr->value );
310 source_error($$->loc) << "write statement given "
311 "but there are no machine instantiations" << endp;
315 ::keyOps = &cgd->thisKeyOps;
321 write_option_list: write_option_list tag_arg;
329 tag_arg: TAG_arg '/' TAG_arg
331 writeOptions.append( $3->tag->content );
334 tag_machine: tag_machine_head machine_item_list '/' TAG_machine
339 tag_machine_head: TAG_machine
341 cgd->createMachine();
344 machine_item_list: machine_item_list machine_item;
347 machine_item: tag_start_state;
348 machine_item: tag_error_state;
349 machine_item: tag_entry_points;
350 machine_item: tag_state_list;
351 machine_item: tag_action_list;
352 machine_item: tag_action_table_list;
353 machine_item: tag_cond_space_list;
359 tag_start_state: TAG_start_state '/' TAG_start_state
361 unsigned long startState = strtoul( $3->tag->content, 0, 10 );
362 cgd->setStartState( startState );
365 tag_error_state: TAG_error_state '/' TAG_error_state
367 unsigned long errorState = strtoul( $3->tag->content, 0, 10 );
368 cgd->setErrorState( errorState );
371 tag_entry_points: TAG_entry_points entry_point_list '/' TAG_entry_points
373 Attribute *errorAttr = $1->tag->findAttr( "error" );
374 if ( errorAttr != 0 )
375 cgd->setForcedErrorState();
378 entry_point_list: entry_point_list tag_entry;
381 tag_entry: TAG_entry '/' TAG_entry
383 Attribute *nameAttr = $1->tag->findAttr( "name" );
384 if ( nameAttr == 0 ) {
385 error($1->loc) << "tag <entry_points>::<entry> "
386 "requires a name attribute" << endp;
389 char *data = $3->tag->content;
390 unsigned long entry = strtoul( data, &data, 10 );
391 cgd->addEntryPoint( nameAttr->value, entry );
395 tag_state_list: tag_state_list_head state_list '/' TAG_state_list;
397 tag_state_list_head: TAG_state_list
399 Attribute *lengthAttr = $1->tag->findAttr( "length" );
400 if ( lengthAttr == 0 )
401 error($1->loc) << "tag <state_list> requires a length attribute" << endp;
403 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
404 cgd->initStateList( length );
409 state_list: state_list tag_state;
412 tag_state: TAG_state state_item_list '/' TAG_state
414 Attribute *idAttr = $1->tag->findAttr( "id" );
416 error($1->loc) << "tag <state> requires an id attribute" << endp;
418 int id = atoi( idAttr->value );
419 cgd->setId( curState, id );
422 Attribute *lengthAttr = $1->tag->findAttr( "final" );
423 if ( lengthAttr != 0 )
424 cgd->setFinal( curState );
428 state_item_list: state_item_list state_item;
431 state_item: tag_state_actions;
432 state_item: tag_eof_t;
433 state_item: tag_state_cond_list;
434 state_item: tag_trans_list;
436 tag_state_actions: TAG_state_actions '/' TAG_state_actions
438 char *ad = $3->tag->content;
440 long toStateAction = readOffsetPtr( ad, &ad );
441 long fromStateAction = readOffsetPtr( ad, &ad );
442 long eofAction = readOffsetPtr( ad, &ad );
444 cgd->setStateActions( curState, toStateAction,
445 fromStateAction, eofAction );
448 tag_eof_t: TAG_eof_t '/' TAG_eof_t
450 char *et = $3->tag->content;
451 long targ = readOffsetPtr( et, &et );
452 long eofAction = readOffsetPtr( et, &et );
454 cgd->setEofTrans( curState, targ, eofAction );
457 tag_state_cond_list: tag_state_cond_list_head state_cond_list '/' TAG_cond_list;
459 tag_state_cond_list_head: TAG_cond_list
461 Attribute *lengthAttr = $1->tag->findAttr( "length" );
462 if ( lengthAttr == 0 )
463 error($1->loc) << "tag <cond_list> requires a length attribute" << endp;
465 ulong length = readLength( lengthAttr->value );
466 cgd->initStateCondList( curState, length );
471 state_cond_list: state_cond_list state_cond;
474 state_cond: TAG_c '/' TAG_c
476 char *td = $3->tag->content;
477 Key lowKey = readKey( td, &td );
478 Key highKey = readKey( td, &td );
479 long condId = readOffsetPtr( td, &td );
480 cgd->addStateCond( curState, lowKey, highKey, condId );
483 tag_trans_list: tag_trans_list_head trans_list '/' TAG_trans_list
485 cgd->finishTransList( curState );
488 tag_trans_list_head: TAG_trans_list
490 Attribute *lengthAttr = $1->tag->findAttr( "length" );
491 if ( lengthAttr == 0 )
492 error($1->loc) << "tag <trans_list> requires a length attribute" << endp;
494 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
495 cgd->initTransList( curState, length );
500 trans_list: trans_list tag_trans;
503 tag_trans: TAG_t '/' TAG_t
505 char *td = $3->tag->content;
506 Key lowKey = readKey( td, &td );
507 Key highKey = readKey( td, &td );
508 long targ = readOffsetPtr( td, &td );
509 long action = readOffsetPtr( td, &td );
511 cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
518 tag_action_list: tag_action_list_head action_list '/' TAG_action_list;
520 tag_action_list_head: TAG_action_list
522 Attribute *lengthAttr = $1->tag->findAttr( "length" );
523 if ( lengthAttr == 0 )
524 error($1->loc) << "tag <action_list> requires a length attribute" << endp;
526 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
527 cgd->initActionList( length );
532 action_list: action_list tag_action;
539 tag_action: TAG_action inline_list '/' TAG_action
541 Attribute *lineAttr = $1->tag->findAttr( "line" );
542 Attribute *colAttr = $1->tag->findAttr( "col" );
543 Attribute *nameAttr = $1->tag->findAttr( "name" );
544 if ( lineAttr == 0 || colAttr == 0)
545 error($1->loc) << "tag <action> requires a line and col attributes" << endp;
547 unsigned long line = strtoul( lineAttr->value, 0, 10 );
548 unsigned long col = strtoul( colAttr->value, 0, 10 );
552 name = nameAttr->value;
554 cgd->newAction( curAction++, name, line, col, $2->inlineList );
560 GenInlineList *inlineList;
564 inline_list: inline_list inline_item
566 /* Append the item to the list, return the list. */
567 $1->inlineList->append( $2->inlineItem );
568 $$->inlineList = $1->inlineList;
573 /* Start with empty list. */
574 $$->inlineList = new GenInlineList;
577 nonterm inline_item_type
579 GenInlineItem *inlineItem;
582 nonterm inline_item uses inline_item_type;
584 inline_item: tag_text final { $$->inlineItem = $1->inlineItem; };
585 inline_item: tag_goto final { $$->inlineItem = $1->inlineItem; };
586 inline_item: tag_call final { $$->inlineItem = $1->inlineItem; };
587 inline_item: tag_next final { $$->inlineItem = $1->inlineItem; };
588 inline_item: tag_goto_expr final { $$->inlineItem = $1->inlineItem; };
589 inline_item: tag_call_expr final { $$->inlineItem = $1->inlineItem; };
590 inline_item: tag_next_expr final { $$->inlineItem = $1->inlineItem; };
591 inline_item: tag_ret final { $$->inlineItem = $1->inlineItem; };
592 inline_item: tag_break final { $$->inlineItem = $1->inlineItem; };
593 inline_item: tag_pchar final { $$->inlineItem = $1->inlineItem; };
594 inline_item: tag_char final { $$->inlineItem = $1->inlineItem; };
595 inline_item: tag_hold final { $$->inlineItem = $1->inlineItem; };
596 inline_item: tag_exec final { $$->inlineItem = $1->inlineItem; };
597 inline_item: tag_curs final { $$->inlineItem = $1->inlineItem; };
598 inline_item: tag_targs final { $$->inlineItem = $1->inlineItem; };
599 inline_item: tag_il_entry final { $$->inlineItem = $1->inlineItem; };
600 inline_item: tag_init_tokstart final { $$->inlineItem = $1->inlineItem; };
601 inline_item: tag_init_act final { $$->inlineItem = $1->inlineItem; };
602 inline_item: tag_get_tokend final { $$->inlineItem = $1->inlineItem; };
603 inline_item: tag_set_tokstart final { $$->inlineItem = $1->inlineItem; };
604 inline_item: tag_set_tokend final { $$->inlineItem = $1->inlineItem; };
605 inline_item: tag_set_act final { $$->inlineItem = $1->inlineItem; };
606 inline_item: tag_sub_action final { $$->inlineItem = $1->inlineItem; };
607 inline_item: tag_lm_switch final { $$->inlineItem = $1->inlineItem; };
609 nonterm tag_text uses inline_item_type;
610 nonterm tag_goto uses inline_item_type;
611 nonterm tag_call uses inline_item_type;
612 nonterm tag_next uses inline_item_type;
613 nonterm tag_goto_expr uses inline_item_type;
614 nonterm tag_call_expr uses inline_item_type;
615 nonterm tag_next_expr uses inline_item_type;
616 nonterm tag_ret uses inline_item_type;
617 nonterm tag_break uses inline_item_type;
618 nonterm tag_pchar uses inline_item_type;
619 nonterm tag_char uses inline_item_type;
620 nonterm tag_hold uses inline_item_type;
621 nonterm tag_exec uses inline_item_type;
622 nonterm tag_curs uses inline_item_type;
623 nonterm tag_targs uses inline_item_type;
624 nonterm tag_il_entry uses inline_item_type;
625 nonterm tag_init_tokstart uses inline_item_type;
626 nonterm tag_init_act uses inline_item_type;
627 nonterm tag_get_tokend uses inline_item_type;
628 nonterm tag_set_tokstart uses inline_item_type;
629 nonterm tag_set_tokend uses inline_item_type;
630 nonterm tag_set_act uses inline_item_type;
631 nonterm tag_sub_action uses inline_item_type;
632 nonterm tag_lm_switch uses inline_item_type;
634 tag_text: TAG_text '/' TAG_text
636 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Text );
637 $$->inlineItem->data = $3->tag->content;
640 tag_goto: TAG_goto '/' TAG_goto
642 int targ = strtol( $3->tag->content, 0, 10 );
643 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Goto );
644 $$->inlineItem->targId = targ;
647 tag_call: TAG_call '/' TAG_call
649 int targ = strtol( $3->tag->content, 0, 10 );
650 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Call );
651 $$->inlineItem->targId = targ;
654 tag_next: TAG_next '/' TAG_next
656 int targ = strtol( $3->tag->content, 0, 10 );
657 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Next );
658 $$->inlineItem->targId = targ;
661 tag_goto_expr: TAG_goto_expr inline_list '/' TAG_goto_expr
663 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::GotoExpr );
664 $$->inlineItem->children = $2->inlineList;
667 tag_call_expr: TAG_call_expr inline_list '/' TAG_call_expr
669 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::CallExpr );
670 $$->inlineItem->children = $2->inlineList;
673 tag_next_expr: TAG_next_expr inline_list '/' TAG_next_expr
675 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::NextExpr );
676 $$->inlineItem->children = $2->inlineList;
679 tag_ret: TAG_ret '/' TAG_ret
681 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Ret );
684 tag_break: TAG_break '/' TAG_break
686 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Break );
689 tag_pchar: TAG_pchar '/' TAG_pchar
691 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::PChar );
694 tag_char: TAG_char '/' TAG_char
696 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Char );
699 tag_hold: TAG_hold '/' TAG_hold
701 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Hold );
704 tag_exec: TAG_exec inline_list '/' TAG_exec
706 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Exec );
707 $$->inlineItem->children = $2->inlineList;
710 tag_curs: TAG_curs '/' TAG_curs
712 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Curs );
715 tag_targs: TAG_targs '/' TAG_targs
717 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Targs );
720 tag_il_entry: TAG_entry '/' TAG_entry
722 int targ = strtol( $3->tag->content, 0, 10 );
723 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Entry );
724 $$->inlineItem->targId = targ;
727 tag_init_tokstart: TAG_init_tokstart '/' TAG_init_tokstart
729 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitTokStart );
732 tag_init_act: TAG_init_act '/' TAG_init_act
734 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitAct );
737 tag_get_tokend: TAG_get_tokend '/' TAG_get_tokend
739 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmGetTokEnd );
742 tag_set_tokstart: TAG_set_tokstart '/' TAG_set_tokstart
744 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokStart );
745 cgd->hasLongestMatch = true;
748 tag_set_tokend: TAG_set_tokend '/' TAG_set_tokend
750 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokEnd );
751 $$->inlineItem->offset = strtol( $3->tag->content, 0, 10 );
754 tag_set_act: TAG_set_act '/' TAG_set_act
756 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetActId );
757 $$->inlineItem->lmId = strtol( $3->tag->content, 0, 10 );
760 tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action
762 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
763 $$->inlineItem->children = $2->inlineList;
767 tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch
769 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSwitch );
770 $$->inlineItem->children = $2->inlineList;
773 nonterm lm_action_list
775 GenInlineList *inlineList;
778 lm_action_list: lm_action_list tag_inline_action
780 $$->inlineList = $1->inlineList;
781 $$->inlineList->append( $2->inlineItem );
785 $$->inlineList = new GenInlineList;
788 nonterm tag_inline_action uses inline_item_type;
790 tag_inline_action: TAG_sub_action inline_list '/' TAG_sub_action
792 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
793 $$->inlineItem->children = $2->inlineList;
795 Attribute *idAttr = $1->tag->findAttr( "id" );
797 unsigned long id = strtoul( idAttr->value, 0, 10 );
798 $$->inlineItem->lmId = id;
806 tag_action_table_list:
807 tag_action_table_list_head action_table_list '/' TAG_action_table_list;
809 tag_action_table_list_head: TAG_action_table_list
811 Attribute *lengthAttr = $1->tag->findAttr( "length" );
812 if ( lengthAttr == 0 ) {
813 error($1->loc) << "tag <action_table_list> requires "
814 "a length attribute" << endp;
817 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
818 cgd->initActionTableList( length );
823 action_table_list: action_table_list tag_action_table;
826 tag_action_table: TAG_action_table '/' TAG_action_table
828 /* Find the length of the action table. */
829 Attribute *lengthAttr = $1->tag->findAttr( "length" );
830 if ( lengthAttr == 0 )
831 error($1->loc) << "tag <at> requires a length attribute" << endp;
833 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
835 /* Collect the action table. */
836 RedAction *redAct = cgd->allActionTables + curActionTable;
837 redAct->actListId = curActionTable;
838 redAct->key.setAsNew( length );
839 char *ptr = $3->tag->content;
841 while ( *ptr != 0 ) {
842 unsigned long actionId = strtoul( ptr, &ptr, 10 );
843 redAct->key[pos].key = 0;
844 redAct->key[pos].value = cgd->allActions+actionId;
848 /* Insert into the action table map. */
849 cgd->redFsm->actionMap.insert( redAct );
859 tag_cond_space_list: tag_cond_space_list_head cond_space_list '/' TAG_cond_space_list;
861 tag_cond_space_list_head: TAG_cond_space_list
863 Attribute *lengthAttr = $1->tag->findAttr( "length" );
864 if ( lengthAttr == 0 ) {
865 error($1->loc) << "tag <cond_space_list> "
866 "requires a length attribute" << endp;
869 ulong length = readLength( lengthAttr->value );
870 cgd->initCondSpaceList( length );
875 cond_space_list: cond_space_list tag_cond_space;
876 cond_space_list: tag_cond_space;
878 tag_cond_space: TAG_cond_space '/' TAG_cond_space
880 Attribute *lengthAttr = $1->tag->findAttr( "length" );
881 Attribute *idAttr = $1->tag->findAttr( "id" );
882 if ( lengthAttr == 0 )
883 error($1->loc) << "tag <cond_space> requires a length attribute" << endp;
885 if ( lengthAttr == 0 )
886 error($1->loc) << "tag <cond_space> requires an id attribute" << endp;
888 unsigned long condSpaceId = strtoul( idAttr->value, 0, 10 );
889 ulong length = readLength( lengthAttr->value );
891 char *td = $3->tag->content;
892 Key baseKey = readKey( td, &td );
894 cgd->newCondSpace( curCondSpace, condSpaceId, baseKey );
895 for ( ulong a = 0; a < length; a++ ) {
896 long actionOffset = readOffsetPtr( td, &td );
897 cgd->condSpaceItem( curCondSpace, actionOffset );
911 void XmlParser::init()
916 int XmlParser::parseLangEl( int type, const Token *token )
919 return errCount == 0 ? 0 : -1;
923 unsigned long readLength( char *td )
925 return strtoul( td, 0, 10 );
928 Key readKey( char *td, char **end )
930 if ( keyOps->isSigned )
931 return Key( strtol( td, end, 10 ) );
933 return Key( strtoul( td, end, 10 ) );
936 long readOffsetPtr( char *td, char **end )
938 while ( *td == ' ' || *td == '\t' )
947 return strtol( td, end, 10 );
950 ostream &XmlParser::warning( const GenInputLoc &loc )
952 cerr << fileName << ":" << loc.line << ":" << loc.col << ": warning: ";
956 ostream &XmlParser::error( const GenInputLoc &loc )
959 assert( fileName != 0 );
960 cerr << fileName << ":" << loc.line << ":" << loc.col << ": ";
965 ostream &XmlParser::parser_error( int tokId, Token &token )
968 assert( fileName != 0 );
969 cerr << fileName << ":" << token.loc.line << ":" << token.loc.col;
970 if ( token.tag != 0 ) {
971 if ( token.tag->tagId == 0 )
972 cerr << ": at unknown tag";
974 cerr << ": at tag <" << token.tag->tagId->name << ">";
981 ostream &XmlParser::source_error( const GenInputLoc &loc )
984 assert( sourceFileName != 0 );
985 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
990 int XmlParser::token( int tokenId, Token &tok )
992 int res = parseLangEl( tokenId, &tok );
994 parser_error( tokenId, tok ) << "parse error" << endp;
998 int XmlParser::token( int tokenId, int col, int line )
1002 tok.loc.line = line;
1004 return token( tokenId, tok );
1007 int XmlParser::token( XMLTag *tag, int col, int line )
1011 tok.loc.line = line;
1014 if ( tag->type == XMLTag::Close ) {
1015 int res = token( '/', tok );
1021 return token( tag->tagId != 0 ? tag->tagId->id : TAG_unknown, tok );