2 * Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
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( char *sourceFileName, 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 )
68 if ( hostLang == &hostLangC )
69 cdLineDirective( out, fileName, line );
70 else if ( hostLang == &hostLangD )
71 cdLineDirective( out, fileName, line );
72 else if ( hostLang == &hostLangJava )
73 javaLineDirective( out, fileName, line );
74 else if ( hostLang == &hostLangRuby )
75 rubyLineDirective( out, fileName, line );
76 else if ( hostLang == &hostLangCSharp )
77 csharpLineDirective( out, fileName, line );
81 void genLineDirective( ostream &out )
83 std::streambuf *sbuf = out.rdbuf();
84 output_filter *filter = static_cast<output_filter*>(sbuf);
85 lineDirective( out, filter->fileName, filter->line + 1 );
92 include "xmlparse.kh";
97 /* If we get no input the assumption is that the frontend died and
98 * emitted an error. This forces the backend to return a non-zero
99 * exit status, but does not print an error. */
103 tag_ragel: tag_ragel_head ragel_def_list host_or_write_list '/' TAG_ragel;
105 tag_ragel_head: TAG_ragel
107 /* Check version used to generated the intermediate file. */
108 Attribute *versionAttr = $1->tag->findAttr( "version" );
109 if ( versionAttr == 0 )
110 error($1->loc) << "tag <ragel> requires a version attribute" << endp;
111 if ( strcmp( versionAttr->value, VERSION ) != 0 )
112 error($1->loc) << "version mismatch between frontend and backend" << endp;
114 /* Check for file name attribute. */
115 Attribute *fileNameAttr = $1->tag->findAttr( "filename" );
116 if ( fileNameAttr == 0 )
117 error($1->loc) << "tag <ragel> requires a filename attribute" << endp;
118 sourceFileName = fileNameAttr->value;
120 /* Check for language attribute. */
121 Attribute *langAttr = $1->tag->findAttr( "lang" );
123 error($1->loc) << "tag <ragel> requires a lang attribute" << endp;
126 outStream = dotOpenOutput( sourceFileName );
127 else if ( strcmp( langAttr->value, "C" ) == 0 ) {
128 hostLang = &hostLangC;
129 outStream = cdOpenOutput( sourceFileName );
131 else if ( strcmp( langAttr->value, "D" ) == 0 ) {
132 hostLang = &hostLangD;
133 outStream = cdOpenOutput( sourceFileName );
135 else if ( strcmp( langAttr->value, "Java" ) == 0 ) {
136 hostLang = &hostLangJava;
137 outStream = javaOpenOutput( sourceFileName );
139 else if ( strcmp( langAttr->value, "Ruby" ) == 0 ) {
140 hostLang = &hostLangRuby;
141 outStream = rubyOpenOutput( sourceFileName );
143 else if ( strcmp( langAttr->value, "C#" ) == 0 ) {
144 hostLang = &hostLangCSharp;
145 outStream = csharpOpenOutput( sourceFileName );
148 error($1->loc) << "expecting lang attribute to be "
149 "one of C, D, Java, Ruby or C#" << endp;
153 ragel_def_list: ragel_def_list ragel_def;
156 host_or_write_list: host_or_write_list host_or_write;
157 host_or_write_list: ;
159 host_or_write: tag_host;
160 host_or_write: tag_write;
163 TAG_host '/' TAG_host
165 Attribute *lineAttr = $1->tag->findAttr( "line" );
167 error($1->loc) << "tag <host> requires a line attribute" << endp;
169 int line = atoi( lineAttr->value );
171 lineDirective( *outStream, sourceFileName, line );
175 *outStream << $3->tag->content;
179 tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def
181 /* Do this before distributing transitions out to singles and defaults
182 * makes life easier. */
183 cgd->redFsm->maxKey = cgd->findMaxKey();
185 cgd->redFsm->assignActionLocs();
187 /* Find the first final state (The final state with the lowest id). */
188 cgd->redFsm->findFirstFinState();
190 /* Call the user's callback. */
191 cgd->finishRagelDef();
194 tag_ragel_def_head: TAG_ragel_def
197 Attribute *nameAttr = $1->tag->findAttr( "name" );
198 if ( nameAttr != 0 ) {
199 fsmName = nameAttr->value;
201 CodeGenMapEl *mapEl = codeGenMap.find( fsmName );
205 cgd = makeCodeGen( sourceFileName, fsmName, *outStream, wantComplete );
206 codeGenMap.insert( fsmName, cgd );
210 cgd = makeCodeGen( sourceFileName, fsmName,
211 *outStream, wantComplete );
214 ::keyOps = &cgd->thisKeyOps;
217 ragel_def_item_list: ragel_def_item_list ragel_def_item;
218 ragel_def_item_list: ;
220 ragel_def_item: tag_alph_type;
221 ragel_def_item: tag_getkey_expr;
222 ragel_def_item: tag_access_expr;
223 ragel_def_item: tag_prepush_expr;
224 ragel_def_item: tag_postpop_expr;
225 ragel_def_item: tag_export_list;
226 ragel_def_item: tag_machine;
227 ragel_def_item: tag_p_expr;
228 ragel_def_item: tag_pe_expr;
229 ragel_def_item: tag_eof_expr;
230 ragel_def_item: tag_cs_expr;
231 ragel_def_item: tag_top_expr;
232 ragel_def_item: tag_stack_expr;
233 ragel_def_item: tag_act_expr;
234 ragel_def_item: tag_tokstart_expr;
235 ragel_def_item: tag_tokend_expr;
236 ragel_def_item: tag_data_expr;
238 tag_export_list: TAG_exports export_list '/' TAG_exports;
240 export_list: export_list tag_export;
243 tag_export: TAG_ex '/' TAG_ex
245 Attribute *nameAttr = $1->tag->findAttr( "name" );
247 error($1->loc) << "tag <ex> requires a name attribute" << endp;
249 char *td = $3->tag->content;
250 Key exportKey = readKey( td, &td );
251 cgd->exportList.append( new Export( nameAttr->value, exportKey ) );
255 tag_alph_type: TAG_alphtype '/' TAG_alphtype
257 if ( ! cgd->setAlphType( $3->tag->content ) )
258 error($1->loc) << "tag <alphtype> specifies unknown alphabet type" << endp;
261 tag_getkey_expr: TAG_getkey inline_list '/' TAG_getkey
263 cgd->getKeyExpr = $2->inlineList;
266 tag_access_expr: TAG_access inline_list '/' TAG_access
268 cgd->accessExpr = $2->inlineList;
271 tag_prepush_expr: TAG_prepush inline_list '/' TAG_prepush
273 cgd->prePushExpr = $2->inlineList;
276 tag_postpop_expr: TAG_postpop inline_list '/' TAG_postpop
278 cgd->postPopExpr = $2->inlineList;
281 tag_p_expr: TAG_p_expr inline_list '/' TAG_p_expr
282 final { cgd->pExpr = $2->inlineList; };
283 tag_pe_expr: TAG_pe_expr inline_list '/' TAG_pe_expr
284 final { cgd->peExpr = $2->inlineList; };
285 tag_eof_expr: TAG_eof_expr inline_list '/' TAG_eof_expr
286 final { cgd->eofExpr = $2->inlineList; };
287 tag_cs_expr: TAG_cs_expr inline_list '/' TAG_cs_expr
288 final { cgd->csExpr = $2->inlineList; };
289 tag_top_expr: TAG_top_expr inline_list '/' TAG_top_expr
290 final { cgd->topExpr = $2->inlineList; };
291 tag_stack_expr: TAG_stack_expr inline_list '/' TAG_stack_expr
292 final { cgd->stackExpr = $2->inlineList; };
293 tag_act_expr: TAG_act_expr inline_list '/' TAG_act_expr
294 final { cgd->actExpr = $2->inlineList; };
295 tag_tokstart_expr: TAG_tokstart_expr inline_list '/' TAG_tokstart_expr
296 final { cgd->tokstartExpr = $2->inlineList; };
297 tag_tokend_expr: TAG_tokend_expr inline_list '/' TAG_tokend_expr
298 final { cgd->tokendExpr = $2->inlineList; };
299 tag_data_expr: TAG_data_expr inline_list '/' TAG_data_expr
300 final { cgd->dataExpr = $2->inlineList; };
303 tag_write: tag_write_head write_option_list '/' TAG_write
305 /* Terminate the options list and call the write statement handler. */
306 writeOptions.append(0);
307 cgd->writeStatement( $1->loc, writeOptions.length()-1, writeOptions.data );
309 /* Clear the options in prep for the next write statement. */
310 writeOptions.empty();
313 nonterm tag_write_head
318 tag_write_head: TAG_write
320 Attribute *nameAttr = $1->tag->findAttr( "def_name" );
321 Attribute *lineAttr = $1->tag->findAttr( "line" );
322 Attribute *colAttr = $1->tag->findAttr( "col" );
325 error($1->loc) << "tag <write> requires a def_name attribute" << endp;
327 error($1->loc) << "tag <write> requires a line attribute" << endp;
329 error($1->loc) << "tag <write> requires a col attribute" << endp;
331 if ( nameAttr != 0 && lineAttr != 0 && colAttr != 0 ) {
332 $$->loc.line = atoi(lineAttr->value);
333 $$->loc.col = atoi(colAttr->value);
335 CodeGenMapEl *mapEl = codeGenMap.find( nameAttr->value );
337 source_error($$->loc) << "write statement given "
338 "but there are no machine instantiations" << endp;
342 ::keyOps = &cgd->thisKeyOps;
348 write_option_list: write_option_list tag_arg;
356 tag_arg: TAG_arg '/' TAG_arg
358 writeOptions.append( $3->tag->content );
361 tag_machine: tag_machine_head machine_item_list '/' TAG_machine
366 tag_machine_head: TAG_machine
368 cgd->createMachine();
371 machine_item_list: machine_item_list machine_item;
374 machine_item: tag_start_state;
375 machine_item: tag_error_state;
376 machine_item: tag_entry_points;
377 machine_item: tag_state_list;
378 machine_item: tag_action_list;
379 machine_item: tag_action_table_list;
380 machine_item: tag_cond_space_list;
386 tag_start_state: TAG_start_state '/' TAG_start_state
388 unsigned long startState = strtoul( $3->tag->content, 0, 10 );
389 cgd->setStartState( startState );
392 tag_error_state: TAG_error_state '/' TAG_error_state
394 unsigned long errorState = strtoul( $3->tag->content, 0, 10 );
395 cgd->setErrorState( errorState );
398 tag_entry_points: TAG_entry_points entry_point_list '/' TAG_entry_points
400 Attribute *errorAttr = $1->tag->findAttr( "error" );
401 if ( errorAttr != 0 )
402 cgd->setForcedErrorState();
405 entry_point_list: entry_point_list tag_entry;
408 tag_entry: TAG_entry '/' TAG_entry
410 Attribute *nameAttr = $1->tag->findAttr( "name" );
411 if ( nameAttr == 0 ) {
412 error($1->loc) << "tag <entry_points>::<entry> "
413 "requires a name attribute" << endp;
416 char *data = $3->tag->content;
417 unsigned long entry = strtoul( data, &data, 10 );
418 cgd->addEntryPoint( nameAttr->value, entry );
422 tag_state_list: tag_state_list_head state_list '/' TAG_state_list;
424 tag_state_list_head: TAG_state_list
426 Attribute *lengthAttr = $1->tag->findAttr( "length" );
427 if ( lengthAttr == 0 )
428 error($1->loc) << "tag <state_list> requires a length attribute" << endp;
430 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
431 cgd->initStateList( length );
436 state_list: state_list tag_state;
439 tag_state: TAG_state state_item_list '/' TAG_state
441 Attribute *idAttr = $1->tag->findAttr( "id" );
443 error($1->loc) << "tag <state> requires an id attribute" << endp;
445 int id = atoi( idAttr->value );
446 cgd->setId( curState, id );
449 Attribute *lengthAttr = $1->tag->findAttr( "final" );
450 if ( lengthAttr != 0 )
451 cgd->setFinal( curState );
455 state_item_list: state_item_list state_item;
458 state_item: tag_state_actions;
459 state_item: tag_eof_t;
460 state_item: tag_state_cond_list;
461 state_item: tag_trans_list;
463 tag_state_actions: TAG_state_actions '/' TAG_state_actions
465 char *ad = $3->tag->content;
467 long toStateAction = readOffsetPtr( ad, &ad );
468 long fromStateAction = readOffsetPtr( ad, &ad );
469 long eofAction = readOffsetPtr( ad, &ad );
471 cgd->setStateActions( curState, toStateAction,
472 fromStateAction, eofAction );
475 tag_eof_t: TAG_eof_t '/' TAG_eof_t
477 char *et = $3->tag->content;
478 long targ = readOffsetPtr( et, &et );
479 long eofAction = readOffsetPtr( et, &et );
481 cgd->setEofTrans( curState, targ, eofAction );
484 tag_state_cond_list: tag_state_cond_list_head state_cond_list '/' TAG_cond_list;
486 tag_state_cond_list_head: TAG_cond_list
488 Attribute *lengthAttr = $1->tag->findAttr( "length" );
489 if ( lengthAttr == 0 )
490 error($1->loc) << "tag <cond_list> requires a length attribute" << endp;
492 ulong length = readLength( lengthAttr->value );
493 cgd->initStateCondList( curState, length );
498 state_cond_list: state_cond_list state_cond;
501 state_cond: TAG_c '/' TAG_c
503 char *td = $3->tag->content;
504 Key lowKey = readKey( td, &td );
505 Key highKey = readKey( td, &td );
506 long condId = readOffsetPtr( td, &td );
507 cgd->addStateCond( curState, lowKey, highKey, condId );
510 tag_trans_list: tag_trans_list_head trans_list '/' TAG_trans_list
512 cgd->finishTransList( curState );
515 tag_trans_list_head: TAG_trans_list
517 Attribute *lengthAttr = $1->tag->findAttr( "length" );
518 if ( lengthAttr == 0 )
519 error($1->loc) << "tag <trans_list> requires a length attribute" << endp;
521 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
522 cgd->initTransList( curState, length );
527 trans_list: trans_list tag_trans;
530 tag_trans: TAG_t '/' TAG_t
532 char *td = $3->tag->content;
533 Key lowKey = readKey( td, &td );
534 Key highKey = readKey( td, &td );
535 long targ = readOffsetPtr( td, &td );
536 long action = readOffsetPtr( td, &td );
538 cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action );
545 tag_action_list: tag_action_list_head action_list '/' TAG_action_list;
547 tag_action_list_head: TAG_action_list
549 Attribute *lengthAttr = $1->tag->findAttr( "length" );
550 if ( lengthAttr == 0 )
551 error($1->loc) << "tag <action_list> requires a length attribute" << endp;
553 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
554 cgd->initActionList( length );
559 action_list: action_list tag_action;
566 tag_action: TAG_action inline_list '/' TAG_action
568 Attribute *lineAttr = $1->tag->findAttr( "line" );
569 Attribute *colAttr = $1->tag->findAttr( "col" );
570 Attribute *nameAttr = $1->tag->findAttr( "name" );
571 if ( lineAttr == 0 || colAttr == 0)
572 error($1->loc) << "tag <action> requires a line and col attributes" << endp;
574 unsigned long line = strtoul( lineAttr->value, 0, 10 );
575 unsigned long col = strtoul( colAttr->value, 0, 10 );
579 name = nameAttr->value;
581 cgd->newAction( curAction++, name, line, col, $2->inlineList );
587 GenInlineList *inlineList;
591 inline_list: inline_list inline_item
593 /* Append the item to the list, return the list. */
594 $1->inlineList->append( $2->inlineItem );
595 $$->inlineList = $1->inlineList;
600 /* Start with empty list. */
601 $$->inlineList = new GenInlineList;
604 nonterm inline_item_type
606 GenInlineItem *inlineItem;
609 nonterm inline_item uses inline_item_type;
611 inline_item: tag_text final { $$->inlineItem = $1->inlineItem; };
612 inline_item: tag_goto final { $$->inlineItem = $1->inlineItem; };
613 inline_item: tag_call final { $$->inlineItem = $1->inlineItem; };
614 inline_item: tag_next final { $$->inlineItem = $1->inlineItem; };
615 inline_item: tag_goto_expr final { $$->inlineItem = $1->inlineItem; };
616 inline_item: tag_call_expr final { $$->inlineItem = $1->inlineItem; };
617 inline_item: tag_next_expr final { $$->inlineItem = $1->inlineItem; };
618 inline_item: tag_ret final { $$->inlineItem = $1->inlineItem; };
619 inline_item: tag_break final { $$->inlineItem = $1->inlineItem; };
620 inline_item: tag_pchar final { $$->inlineItem = $1->inlineItem; };
621 inline_item: tag_char final { $$->inlineItem = $1->inlineItem; };
622 inline_item: tag_hold final { $$->inlineItem = $1->inlineItem; };
623 inline_item: tag_exec final { $$->inlineItem = $1->inlineItem; };
624 inline_item: tag_curs final { $$->inlineItem = $1->inlineItem; };
625 inline_item: tag_targs final { $$->inlineItem = $1->inlineItem; };
626 inline_item: tag_il_entry final { $$->inlineItem = $1->inlineItem; };
627 inline_item: tag_init_tokstart final { $$->inlineItem = $1->inlineItem; };
628 inline_item: tag_init_act final { $$->inlineItem = $1->inlineItem; };
629 inline_item: tag_get_tokend final { $$->inlineItem = $1->inlineItem; };
630 inline_item: tag_set_tokstart final { $$->inlineItem = $1->inlineItem; };
631 inline_item: tag_set_tokend final { $$->inlineItem = $1->inlineItem; };
632 inline_item: tag_set_act final { $$->inlineItem = $1->inlineItem; };
633 inline_item: tag_sub_action final { $$->inlineItem = $1->inlineItem; };
634 inline_item: tag_lm_switch final { $$->inlineItem = $1->inlineItem; };
636 nonterm tag_text uses inline_item_type;
637 nonterm tag_goto uses inline_item_type;
638 nonterm tag_call uses inline_item_type;
639 nonterm tag_next uses inline_item_type;
640 nonterm tag_goto_expr uses inline_item_type;
641 nonterm tag_call_expr uses inline_item_type;
642 nonterm tag_next_expr uses inline_item_type;
643 nonterm tag_ret uses inline_item_type;
644 nonterm tag_break uses inline_item_type;
645 nonterm tag_pchar uses inline_item_type;
646 nonterm tag_char uses inline_item_type;
647 nonterm tag_hold uses inline_item_type;
648 nonterm tag_exec uses inline_item_type;
649 nonterm tag_curs uses inline_item_type;
650 nonterm tag_targs uses inline_item_type;
651 nonterm tag_il_entry uses inline_item_type;
652 nonterm tag_init_tokstart uses inline_item_type;
653 nonterm tag_init_act uses inline_item_type;
654 nonterm tag_get_tokend uses inline_item_type;
655 nonterm tag_set_tokstart uses inline_item_type;
656 nonterm tag_set_tokend uses inline_item_type;
657 nonterm tag_set_act uses inline_item_type;
658 nonterm tag_sub_action uses inline_item_type;
659 nonterm tag_lm_switch uses inline_item_type;
661 tag_text: TAG_text '/' TAG_text
663 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Text );
664 $$->inlineItem->data = $3->tag->content;
667 tag_goto: TAG_goto '/' TAG_goto
669 int targ = strtol( $3->tag->content, 0, 10 );
670 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Goto );
671 $$->inlineItem->targId = targ;
674 tag_call: TAG_call '/' TAG_call
676 int targ = strtol( $3->tag->content, 0, 10 );
677 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Call );
678 $$->inlineItem->targId = targ;
681 tag_next: TAG_next '/' TAG_next
683 int targ = strtol( $3->tag->content, 0, 10 );
684 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Next );
685 $$->inlineItem->targId = targ;
688 tag_goto_expr: TAG_goto_expr inline_list '/' TAG_goto_expr
690 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::GotoExpr );
691 $$->inlineItem->children = $2->inlineList;
694 tag_call_expr: TAG_call_expr inline_list '/' TAG_call_expr
696 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::CallExpr );
697 $$->inlineItem->children = $2->inlineList;
700 tag_next_expr: TAG_next_expr inline_list '/' TAG_next_expr
702 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::NextExpr );
703 $$->inlineItem->children = $2->inlineList;
706 tag_ret: TAG_ret '/' TAG_ret
708 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Ret );
711 tag_break: TAG_break '/' TAG_break
713 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Break );
716 tag_pchar: TAG_pchar '/' TAG_pchar
718 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::PChar );
721 tag_char: TAG_char '/' TAG_char
723 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Char );
726 tag_hold: TAG_hold '/' TAG_hold
728 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Hold );
731 tag_exec: TAG_exec inline_list '/' TAG_exec
733 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Exec );
734 $$->inlineItem->children = $2->inlineList;
737 tag_curs: TAG_curs '/' TAG_curs
739 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Curs );
742 tag_targs: TAG_targs '/' TAG_targs
744 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Targs );
747 tag_il_entry: TAG_entry '/' TAG_entry
749 int targ = strtol( $3->tag->content, 0, 10 );
750 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Entry );
751 $$->inlineItem->targId = targ;
754 tag_init_tokstart: TAG_init_tokstart '/' TAG_init_tokstart
756 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitTokStart );
759 tag_init_act: TAG_init_act '/' TAG_init_act
761 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitAct );
764 tag_get_tokend: TAG_get_tokend '/' TAG_get_tokend
766 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmGetTokEnd );
769 tag_set_tokstart: TAG_set_tokstart '/' TAG_set_tokstart
771 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokStart );
772 cgd->hasLongestMatch = true;
775 tag_set_tokend: TAG_set_tokend '/' TAG_set_tokend
777 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokEnd );
778 $$->inlineItem->offset = strtol( $3->tag->content, 0, 10 );
781 tag_set_act: TAG_set_act '/' TAG_set_act
783 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetActId );
784 $$->inlineItem->lmId = strtol( $3->tag->content, 0, 10 );
787 tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action
789 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
790 $$->inlineItem->children = $2->inlineList;
794 tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch
796 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSwitch );
797 $$->inlineItem->children = $2->inlineList;
800 nonterm lm_action_list
802 GenInlineList *inlineList;
805 lm_action_list: lm_action_list tag_inline_action
807 $$->inlineList = $1->inlineList;
808 $$->inlineList->append( $2->inlineItem );
812 $$->inlineList = new GenInlineList;
815 nonterm tag_inline_action uses inline_item_type;
817 tag_inline_action: TAG_sub_action inline_list '/' TAG_sub_action
819 $$->inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
820 $$->inlineItem->children = $2->inlineList;
822 Attribute *idAttr = $1->tag->findAttr( "id" );
824 unsigned long id = strtoul( idAttr->value, 0, 10 );
825 $$->inlineItem->lmId = id;
833 tag_action_table_list:
834 tag_action_table_list_head action_table_list '/' TAG_action_table_list;
836 tag_action_table_list_head: TAG_action_table_list
838 Attribute *lengthAttr = $1->tag->findAttr( "length" );
839 if ( lengthAttr == 0 ) {
840 error($1->loc) << "tag <action_table_list> requires "
841 "a length attribute" << endp;
844 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
845 cgd->initActionTableList( length );
850 action_table_list: action_table_list tag_action_table;
853 tag_action_table: TAG_action_table '/' TAG_action_table
855 /* Find the length of the action table. */
856 Attribute *lengthAttr = $1->tag->findAttr( "length" );
857 if ( lengthAttr == 0 )
858 error($1->loc) << "tag <at> requires a length attribute" << endp;
860 unsigned long length = strtoul( lengthAttr->value, 0, 10 );
862 /* Collect the action table. */
863 RedAction *redAct = cgd->allActionTables + curActionTable;
864 redAct->actListId = curActionTable;
865 redAct->key.setAsNew( length );
866 char *ptr = $3->tag->content;
868 while ( *ptr != 0 ) {
869 unsigned long actionId = strtoul( ptr, &ptr, 10 );
870 redAct->key[pos].key = 0;
871 redAct->key[pos].value = cgd->allActions+actionId;
875 /* Insert into the action table map. */
876 cgd->redFsm->actionMap.insert( redAct );
886 tag_cond_space_list: tag_cond_space_list_head cond_space_list '/' TAG_cond_space_list;
888 tag_cond_space_list_head: TAG_cond_space_list
890 Attribute *lengthAttr = $1->tag->findAttr( "length" );
891 if ( lengthAttr == 0 ) {
892 error($1->loc) << "tag <cond_space_list> "
893 "requires a length attribute" << endp;
896 ulong length = readLength( lengthAttr->value );
897 cgd->initCondSpaceList( length );
902 cond_space_list: cond_space_list tag_cond_space;
903 cond_space_list: tag_cond_space;
905 tag_cond_space: TAG_cond_space '/' TAG_cond_space
907 Attribute *lengthAttr = $1->tag->findAttr( "length" );
908 Attribute *idAttr = $1->tag->findAttr( "id" );
909 if ( lengthAttr == 0 )
910 error($1->loc) << "tag <cond_space> requires a length attribute" << endp;
912 if ( lengthAttr == 0 )
913 error($1->loc) << "tag <cond_space> requires an id attribute" << endp;
915 unsigned long condSpaceId = strtoul( idAttr->value, 0, 10 );
916 ulong length = readLength( lengthAttr->value );
918 char *td = $3->tag->content;
919 Key baseKey = readKey( td, &td );
921 cgd->newCondSpace( curCondSpace, condSpaceId, baseKey );
922 for ( ulong a = 0; a < length; a++ ) {
923 long actionOffset = readOffsetPtr( td, &td );
924 cgd->condSpaceItem( curCondSpace, actionOffset );
938 void XmlParser::init()
943 int XmlParser::parseLangEl( int type, const Token *token )
946 return errCount == 0 ? 0 : -1;
950 unsigned long readLength( char *td )
952 return strtoul( td, 0, 10 );
955 Key readKey( char *td, char **end )
957 if ( keyOps->isSigned )
958 return Key( strtol( td, end, 10 ) );
960 return Key( strtoul( td, end, 10 ) );
963 long readOffsetPtr( char *td, char **end )
965 while ( *td == ' ' || *td == '\t' )
974 return strtol( td, end, 10 );
977 ostream &XmlParser::warning( const GenInputLoc &loc )
979 cerr << fileName << ":" << loc.line << ":" << loc.col << ": warning: ";
983 ostream &XmlParser::error( const GenInputLoc &loc )
986 assert( fileName != 0 );
987 cerr << fileName << ":" << loc.line << ":" << loc.col << ": ";
992 ostream &XmlParser::parser_error( int tokId, Token &token )
995 assert( fileName != 0 );
996 cerr << fileName << ":" << token.loc.line << ":" << token.loc.col;
997 if ( token.tag != 0 ) {
998 if ( token.tag->tagId == 0 )
999 cerr << ": at unknown tag";
1001 cerr << ": at tag <" << token.tag->tagId->name << ">";
1008 ostream &XmlParser::source_error( const GenInputLoc &loc )
1011 assert( sourceFileName != 0 );
1012 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
1017 int XmlParser::token( int tokenId, Token &tok )
1019 int res = parseLangEl( tokenId, &tok );
1021 parser_error( tokenId, tok ) << "parse error" << endp;
1025 int XmlParser::token( int tokenId, int col, int line )
1029 tok.loc.line = line;
1031 return token( tokenId, tok );
1034 int XmlParser::token( XMLTag *tag, int col, int line )
1038 tok.loc.line = line;
1041 if ( tag->type == XMLTag::Close ) {
1042 int res = token( '/', tok );
1048 return token( tag->tagId != 0 ? tag->tagId->id : TAG_unknown, tok );