/* * Copyright 2015-2018 Adrian Thurston * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include "fsmcodegen.h" void Compiler::writeCommitStub() { *outStream << "void " << objectName << "_commit_reduce_forward( program_t *prg, tree_t **root,\n" " struct pda_run *pda_run, parse_tree_t *pt )\n" "{\n" " commit_clear_parse_tree( prg, root, pda_run, pt->child );\n" "}\n" "\n" "long " << objectName << "_commit_union_sz( int reducer ) { return 0; }\n" "void " << objectName << "_init_need() {}\n" "int " << objectName << "_reducer_need_tok( program_t *prg, " "struct pda_run *pda_run, int id ) { return COLM_RN_BOTH; }\n" "int " << objectName << "_reducer_need_ign( program_t *prg, " "struct pda_run *pda_run ) { return COLM_RN_BOTH; }\n" "\n" "void " << objectName << "_read_reduce( program_t *prg, int reducer, input_t *stream ) {}\n" ; } void Compiler::findRhsRefs( bool &lhsUsed, Vector &rhsUsed, Vector &treeUsed, Vector &locUsed, Reduction *reduction, Production *production, const ReduceTextItemList &list ) { ObjectDef *objectDef = production->prodName->objectDef; rhsUsed.setAsNew( production->prodElList->length() ); treeUsed.setAsNew( production->prodElList->length() ); locUsed.setAsNew( production->prodElList->length() ); for ( ReduceTextItemList::Iter i = list; i.lte(); i++ ) { if ( i->type == ReduceTextItem::LhsRef ) { lhsUsed = true; } if ( i->type == ReduceTextItem::RhsRef || i->type == ReduceTextItem::RhsLoc || i->type == ReduceTextItem::TreeRef ) { if ( i->n > 0 ) { /* Numbered. */ ProdEl *prodEl = production->prodElList->head; int adv = i->n - 1; while ( adv > 0 ) { prodEl = prodEl->next; adv -= 1; } if ( i->type == ReduceTextItem::RhsLoc ) locUsed[i->n-1] = prodEl; else if ( i->type == ReduceTextItem::TreeRef ) treeUsed[i->n-1] = prodEl; else rhsUsed[i->n-1] = prodEl; } else { /* Named. */ String name( i->txt.data + 1, i->txt.length() - 1 ); ObjectField *field = objectDef->rootScope->findField( name ); if ( field != 0 ) { for ( Vector::Iter r = field->rhsVal; r.lte(); r++ ) { if ( r->prodEl->production == production ) { if ( i->type == ReduceTextItem::RhsLoc ) locUsed[r->prodEl->pos] = r->prodEl; else rhsUsed[r->prodEl->pos] = r->prodEl; } } } } } } } void Compiler::computeNeeded( Reduction *reduction, Production *production, const ReduceTextItemList &list ) { bool lhsUsed = false; Vector rhsUsed; Vector treeUsed; Vector locUsed; findRhsRefs( lhsUsed, rhsUsed, treeUsed, locUsed, reduction, production, list ); /* Same length, can concurrently walk with one test. */ Vector::Iter rhs = rhsUsed; Vector::Iter loc = locUsed; for ( ; rhs.lte(); rhs++, loc++ ) { ProdEl *prodEl = *rhs; if ( prodEl != 0 ) { if ( prodEl->production == production && prodEl->langEl->type == LangEl::Term ) reduction->needData[prodEl->langEl->id] = true; } ProdEl *locEl = *loc; if ( locEl != 0 && locEl->production == production ) reduction->needLoc[locEl->langEl->id] = true; } } void Compiler::loadRefs( Reduction *reduction, Production *production, const ReduceTextItemList &list, bool read ) { bool lhsUsed = false; Vector rhsUsed; Vector treeUsed; Vector locUsed; findRhsRefs( lhsUsed, rhsUsed, treeUsed, locUsed, reduction, production, list ); if ( lhsUsed ) { *outStream << " lel_" << production->prodName->fullName << " *_lhs = "; if ( read ) { *outStream << "&node->u." << production->prodName->fullName << ";\n"; } else { *outStream << "&((commit_reduce_union*)(lel+1))->" << production->prodName->fullName << ";\n"; } } /* * In the first pass we load using a parse tree cursor. This is for * nonterms. */ bool useCursor = false; for ( Vector::Iter rhs = rhsUsed; rhs.lte(); rhs++ ) { if ( *rhs != 0 && (*rhs)->production == production && (*rhs)->langEl->type != LangEl::Term ) { useCursor = true; break; } } if ( useCursor ) { int cursorPos = 0; if ( read ) { *outStream << " struct read_reduce_node *_pt_cursor = node->child;\n"; } else { *outStream << " struct colm_parse_tree *_pt_cursor = lel->child;\n"; } /* Same length, can concurrently walk with one test. */ Vector::Iter rhs = rhsUsed; Vector::Iter loc = locUsed; for ( ; rhs.lte(); rhs++, loc++ ) { ProdEl *prodEl = *rhs; if ( prodEl != 0 ) { while ( cursorPos < rhs.pos() ) { *outStream << " _pt_cursor = _pt_cursor->next;\n"; cursorPos += 1; } if ( prodEl->production == production ) { if ( prodEl->langEl->type != LangEl::Term ) { *outStream << "lel_" << prodEl->langEl->fullName << " *" "_rhs" << rhs.pos() << " = "; if ( read ) { *outStream << "&_pt_cursor->u." << prodEl->langEl->fullName << ";\n"; } else { *outStream << "&((commit_reduce_union*)(_pt_cursor+1))->" << prodEl->langEl->fullName << ";\n"; } } } } } } /* In the second pass we load using a tree cursor. This is for token/tree * data and locations. */ useCursor = false; for ( Vector::Iter rhs = rhsUsed; rhs.lte(); rhs++ ) { if ( *rhs != 0 && (*rhs)->production == production && (*rhs)->langEl->type == LangEl::Term ) { useCursor = true; break; } } for ( Vector::Iter rhs = treeUsed; rhs.lte(); rhs++ ) { if ( *rhs != 0 ) { useCursor = true; break; } } for ( Vector::Iter loc = locUsed; loc.lte(); loc++ ) { if ( *loc != 0 ) { useCursor = true; break; } } if ( useCursor ) { int cursorPos = 0; if ( read ) { *outStream << " read_reduce_node *_tree_cursor = node->child;\n"; } else { *outStream << " kid_t *_tree_cursor = kid->tree->child;\n"; } /* Same length, can concurrently walk with one test. */ Vector::Iter rhs = rhsUsed; Vector::Iter tree = treeUsed; Vector::Iter loc = locUsed; for ( ; rhs.lte(); rhs++, loc++ ) { ProdEl *prodEl = *rhs; if ( prodEl != 0 ) { if ( prodEl->production == production ) { if ( prodEl->langEl->type == LangEl::Term ) { while ( cursorPos < rhs.pos() ) { *outStream << " _tree_cursor = _tree_cursor->next;\n"; cursorPos += 1; } *outStream << " colm_data *_rhs" << rhs.pos() << " = "; if ( read ) { *outStream << "&_tree_cursor->data;\n"; } else { *outStream << "_tree_cursor->tree->tokdata;\n"; } } } } ProdEl *treeEl = *tree; if ( treeEl != 0 ) { if ( treeEl->production == production ) { while ( cursorPos < rhs.pos() ) { *outStream << " _tree_cursor = _tree_cursor->next;\n"; cursorPos += 1; } *outStream << " colm_tree *_tree" << rhs.pos() << " = "; *outStream << "_tree_cursor->tree;\n"; } } ProdEl *locEl = *loc; if ( locEl != 0 ) { if ( locEl->production == production ) { while ( cursorPos < rhs.pos() ) { *outStream << " _tree_cursor = _tree_cursor->next;\n"; cursorPos += 1; } *outStream << " colm_location *_loc" << loc.pos() << " = "; if ( read ) { *outStream << "&_tree_cursor->loc;\n"; } else { *outStream << "colm_find_location( prg, _tree_cursor->tree );\n"; } } } } } } void Compiler::writeRhsRef( Production *production, ReduceTextItem *i ) { if ( i->n > 0 ) { *outStream << "_rhs" << ( i->n - 1 ); } else { ObjectDef *objectDef = production->prodName->objectDef; String name( i->txt.data + 1, i->txt.length() - 1 ); /* Find the field in the rhsVal using capture field. */ ObjectField *field = objectDef->rootScope->findField( name ); if ( field != 0 ) { for ( Vector::Iter r = field->rhsVal; r.lte(); r++ ) { if ( r->prodEl->production == production ) *outStream << "_rhs" << r->prodEl->pos; } } } } void Compiler::writeTreeRef( Production *production, ReduceTextItem *i ) { if ( i->n > 0 ) { *outStream << "_tree" << ( i->n - 1 ); } else { ObjectDef *objectDef = production->prodName->objectDef; String name( i->txt.data + 1, i->txt.length() - 1 ); /* Find the field in the rhsVal using capture field. */ ObjectField *field = objectDef->rootScope->findField( name ); if ( field != 0 ) { for ( Vector::Iter r = field->rhsVal; r.lte(); r++ ) { if ( r->prodEl->production == production ) *outStream << "_tree" << r->prodEl->pos; } } } } void Compiler::writeRhsLoc( Production *production, ReduceTextItem *i ) { if ( i->n > 0 ) { *outStream << "_loc" << ( i->n - 1 ); } else { ObjectDef *objectDef = production->prodName->objectDef; String name( i->txt.data + 1, i->txt.length() - 1 ); /* Find the field in the rhsVal using capture field. */ ObjectField *field = objectDef->rootScope->findField( name ); if ( field != 0 ) { for ( Vector::Iter r = field->rhsVal; r.lte(); r++ ) { if ( r->prodEl->production == production ) *outStream << "_loc" << r->prodEl->pos; } } } } void Compiler::writeLhsRef( Production *production, ReduceTextItem *i ) { *outStream << "_lhs"; } void Compiler::writeHostItemList( Production *production, const ReduceTextItemList &list ) { for ( ReduceTextItemList::Iter i = list; i.lte(); i++ ) { switch ( i->type ) { case ReduceTextItem::LhsRef: writeLhsRef( production, i ); break; case ReduceTextItem::RhsRef: writeRhsRef( production, i ); break; case ReduceTextItem::TreeRef: writeTreeRef( production, i ); break; case ReduceTextItem::RhsLoc: writeRhsLoc( production, i ); break; case ReduceTextItem::Txt: *outStream << i->txt; break; } } } /* For sorting according to prod name id, then by prod num. */ struct CmpReduceAction { static int compare( const ReduceAction *ra1 , const ReduceAction *ra2 ) { if ( ra1->production->prodName->id < ra2->production->prodName->id ) return -1; else if ( ra1->production->prodName->id > ra2->production->prodName->id ) return 1; else { if ( ra1->production->prodNum < ra2->production->prodNum ) return -1; else if ( ra1->production->prodNum > ra2->production->prodNum ) return 1; } return 0; } }; void Compiler::initReductionNeeds( Reduction *reduction ) { reduction->needData = new bool[nextLelId]; reduction->needLoc = new bool[nextLelId]; memset( reduction->needData, 0, sizeof(bool)*nextLelId ); memset( reduction->needLoc, 0, sizeof(bool)*nextLelId ); } void Compiler::writeNeeds() { *outStream << "struct reduction_info\n" "{\n" " unsigned char need_data[" << nextLelId << "];\n" " unsigned char need_loc[" << nextLelId << "];\n" "};\n" "\n"; *outStream << "static struct reduction_info ri[" << rootNamespace->reductions.length() + 1 << "];\n" "\n"; *outStream << "extern \"C\" void " << objectName << "_init_need()\n" "{\n"; for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; *outStream << " memset( ri[" << reduction->id << "]" ".need_data, 0, sizeof(unsigned char) * " << nextLelId << " );\n" " memset( ri[" << reduction->id << "]" ".need_loc, 0, sizeof(unsigned char) * " << nextLelId << " );\n"; for ( int i = 0; i < nextLelId; i++ ) { if ( reduction->needData[i] ) { *outStream << " ri[" << reduction->id << "].need_data[" << i << "] = COLM_RN_DATA;\n"; } if ( reduction->needLoc[i] ) { *outStream << " ri[" << reduction->id << "].need_loc[" << i << "] = COLM_RN_LOC;\n"; } } } *outStream << "}\n"; *outStream << "extern \"C\" int " << objectName << "_reducer_need_tok( program_t *prg, " "struct pda_run *pda_run, int id )\n" "{\n" " if ( prg->reduce_clean && pda_run->reducer > 0 ) {\n" /* Note we are forcing the reducer need for data. Enabling requires finding * a solution for backtracking push. */ " return COLM_RN_DATA | ri[pda_run->reducer].need_data[id] | \n" " ri[pda_run->reducer].need_loc[id];\n" " }\n" " return COLM_RN_BOTH;\n" "}\n" "\n" "extern \"C\" int " << objectName << "_reducer_need_ign( program_t *prg, struct pda_run *pda_run )\n" "{\n" // Using this requires finding a solution for backtracking push back. //" if ( pda_run->reducer > 0 )\n" //" return COLM_RN_NEITHER;\n" " return COLM_RN_BOTH;\n" "}\n"; } void Compiler::writeReduceStructs() { for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { for ( ReduceNonTermList::Iter rdi = (*r)->reduceNonTerms; rdi.lte(); rdi++ ) { *outStream << "struct lel_" << rdi->nonTerm->uniqueType->langEl->fullName << "\n" "{\n"; *outStream << "#line " << rdi->loc.line << "\"" << rdi->loc.fileName << "\"\n"; writeHostItemList( 0, rdi->itemList ); *outStream << "};\n"; } } *outStream << "union commit_reduce_union\n" "{\n"; for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { for ( ReduceNonTermList::Iter rdi = (*r)->reduceNonTerms; rdi.lte(); rdi++ ) { LangEl *langEl = rdi->nonTerm->uniqueType->langEl; *outStream << " lel_" << langEl->fullName << " " << langEl->fullName << ";\n"; } } *outStream << "};\n" "\n"; *outStream << "extern \"C\" long " << objectName << "_commit_union_sz( int reducer )\n" "{\n" " return sizeof( commit_reduce_union );\n" "}\n"; *outStream << "struct read_reduce_node\n" "{\n" " std::string name;\n" " int id;\n" " int prod_num;\n" " colm_location loc;\n" " colm_data data;\n" " commit_reduce_union u;\n" " read_reduce_node *next;\n" " read_reduce_node *child;\n" "};\n" "\n"; } void Compiler::writeUnescape() { *outStream << "static void unescape( colm_data *tokdata )\n" "{\n" " unsigned char *src = (unsigned char*)tokdata->data, *dest = (unsigned char*)tokdata->data;\n" " while ( *src != 0 ) {\n" " if ( *src == '\\\\' ) {\n" " unsigned int i;\n" " char buf[3];\n" "\n" " src += 1;\n" " buf[0] = *src++;\n" " buf[1] = *src++;\n" " buf[2] = 0;\n" "\n" " sscanf( buf, \"%x\", &i );\n" " *dest++ = (unsigned char)i;\n" "\n" " tokdata->length -= 2;\n" " }\n" " else {\n" " *dest++ = *src++;\n" " }\n" " }\n" " *dest = 0;\n" "}\n" "\n"; } void Compiler::writeReduceDispatchers() { *outStream << "\n" "extern \"C\" void " << objectName << "_commit_reduce_forward( program_t *prg, tree_t **root,\n" " struct pda_run *pda_run, parse_tree_t *pt )\n" "{\n" " switch ( pda_run->reducer ) {\n"; for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; if ( reduction->parserBased ) { *outStream << " case " << reduction->id << ":\n" " ((" << reduction->name << "*)prg->red_ctx)->commit_reduce_forward( " "prg, root, pda_run, pt );\n" " break;\n"; } } *outStream << " }\n" "}\n" "\n"; *outStream << "extern \"C\" void " << objectName << "_read_reduce( program_t *prg, int reducer, stream_t *stream )\n" "{\n" " switch ( reducer ) {\n"; for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; if ( reduction->postfixBased ) { *outStream << " case " << reduction->id << ":\n" " ((" << reduction->name << "*)prg->red_ctx)->read_reduce_forward( prg, stream->impl->file );\n" " break;\n"; } } *outStream << " }\n" "}\n" "\n"; } void Compiler::computeNeeded() { for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; initReductionNeeds( reduction ); for ( ReduceActionList::Iter rdi = reduction->reduceActions; rdi.lte(); rdi++ ) computeNeeded( reduction, rdi->production, rdi->itemList ); } } void Compiler::writeParseReduce( Reduction *reduction ) { *outStream << "void " << reduction->name << "::commit_reduce_forward( program_t *prg, \n" " tree_t **root, struct pda_run *pda_run, parse_tree_t *pt )\n" "{\n" " tree_t **sp = root;\n" "\n" " parse_tree_t *lel = pt;\n" " kid_t *kid = pt->shadow;\n" "\n" "recurse:\n" "\n" " if ( lel->child != 0 ) {\n" " /* There are children. Must process all children first. */\n" " vm_push_ptree( lel );\n" " vm_push_kid( kid );\n" "\n" " lel = lel->child;\n" " kid = tree_child( prg, kid->tree );\n" " while ( lel != 0 ) {\n" " goto recurse;\n" " resume:\n" " lel = lel->next;\n" " kid = kid->next;\n" " }\n" "\n" " kid = vm_pop_kid();\n" " lel = vm_pop_ptree();\n" " }\n" "\n" " if ( !( lel->flags & PF_COMMITTED ) ) {\n" " /* Now can execute the reduction action. */\n" " {\n"; *outStream << " { switch ( kid->tree->id ) {\n"; /* Populate a vector with the reduce actions. */ Vector actions; actions.setAsNew( reduction->reduceActions.length() ); long pos = 0; for ( ReduceActionList::Iter rdi = reduction->reduceActions; rdi.lte(); rdi++ ) actions[pos++] = rdi; /* Sort it by lhs id, then prod num. */ MergeSort sortActions; sortActions.sort( actions.data, actions.length() ); ReduceAction *last = 0; for ( Vector::Iter rdi = actions; rdi.lte(); rdi++ ) { ReduceAction *action = *rdi; int lelId = action->production->prodName->id; int prodNum = action->production->prodNum; /* Maybe close off the last prod. */ if ( last != 0 && last->production->prodName != action->production->prodName ) { *outStream << " break;\n" " }\n"; } /* Maybe open a new prod. */ if ( last == 0 || last->production->prodName != action->production->prodName ) { *outStream << " case " << lelId << ": {\n"; } *outStream << " if ( kid->tree->prod_num == " << prodNum << " ) {\n"; loadRefs( reduction, action->production, action->itemList, false ); *outStream << "#line " << action->loc.line << " \"" << action->loc.fileName << "\"\n"; writeHostItemList( action->production, action->itemList ); *outStream << " }\n"; last = action; } if ( last != 0 ) { *outStream << " break;\n" " }\n"; } *outStream << " } }\n" " }\n" " }\n" "\n" " commit_clear_parse_tree( prg, sp, pda_run, lel->child );\n" " if ( prg->reduce_clean ) {\n" " commit_clear_kid_list( prg, sp, kid->tree->child );\n" " kid->tree->child = 0;\n" " kid->tree->flags &= ~( AF_LEFT_IGNORE | AF_RIGHT_IGNORE );\n" " }\n" " lel->child = 0;\n" "\n" " if ( sp != root )\n" " goto resume;\n" " pt->flags |= PF_COMMITTED;\n" "}\n" "\n"; } void Compiler::writeParseReduce() { for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; if ( reduction->parserBased ) writeParseReduce( reduction ); } } void Compiler::writePostfixReduce( Reduction *reduction ) { *outStream << "void " << reduction->name << "::read_reduce_forward( program_t *prg, FILE *file )\n" "{\n" " __gnu_cxx::stdio_filebuf fbuf( file, std::ios::in|std::ios::out|std::ios::app );\n" " std::iostream in( &fbuf );\n" " std::string type, tok, text;\n" " long _id, line, column, byte, prod_num, children;\n" " read_reduce_node sentinal;\n" " sentinal.next = 0;\n" " read_reduce_node *stack = &sentinal, *last = 0;\n" " while ( in >> type ) {\n" " /* read. */\n" " if ( type == \"t\" ) {\n" " in >> tok >> _id >> line >> column >> byte >> text;\n" " read_reduce_node *node = new read_reduce_node;\n" " node->name = tok;\n" " node->id = _id;\n" " node->loc.name = \"<>\";\n" " node->loc.line = line;\n" " node->loc.column = column;\n" " node->loc.byte = byte;\n" " node->data.data = strdup( text.c_str() );\n" " node->data.length = text.size();\n" " unescape( &node->data );\n" "\n" " node->next = stack;\n" " node->child = 0;\n" " stack = node;\n" " }\n" " else if ( type == \"r\" ) {\n" " in >> tok >> _id >> prod_num >> children;\n" " read_reduce_node *node = new read_reduce_node;\n" " memset( &node->loc, 0, sizeof(colm_location) );\n" " memset( &node->data, 0, sizeof(colm_data) );\n" " node->name = tok;\n" " node->id = _id;\n" " node->prod_num = prod_num;\n" " node->child = 0;\n" " while ( children-- > 0 ) {\n" " last = stack;\n" " stack = stack->next;\n" " last->next = node->child;\n" " node->child = last;\n" " }\n" "\n" " node->next = stack;\n" " stack = node;\n" "\n" " { switch ( node->id ) {\n"; /* Populate a vector with the reduce actions. */ Vector actions; actions.setAsNew( reduction->reduceActions.length() ); long pos = 0; for ( ReduceActionList::Iter rdi = reduction->reduceActions; rdi.lte(); rdi++ ) actions[pos++] = rdi; /* Sort it by lhs id, then prod num. */ MergeSort sortActions; sortActions.sort( actions.data, actions.length() ); ReduceAction *last = 0; for ( Vector::Iter rdi = actions; rdi.lte(); rdi++ ) { ReduceAction *action = *rdi; int lelId = action->production->prodName->id; int prodNum = action->production->prodNum; /* Maybe close off the last prod. */ if ( last != 0 && last->production->prodName != action->production->prodName ) { *outStream << " break;\n" " }\n"; } /* Maybe open a new prod. */ if ( last == 0 || last->production->prodName != action->production->prodName ) { *outStream << " case " << lelId << ": {\n"; } *outStream << " if ( node->prod_num == " << prodNum << " ) {\n"; loadRefs( reduction, action->production, action->itemList, true ); *outStream << "#line " << action->loc.line << "\"" << action->loc.fileName << "\"\n"; writeHostItemList( action->production, action->itemList ); *outStream << " }\n"; last = action; } if ( last != 0 ) { *outStream << " break;\n" " }\n"; } *outStream << " } }\n" " /* delete the children */\n" " last = node->child;\n" " while ( last != 0 ) {\n" " read_reduce_node *next = last->next;\n" " delete last;\n" " last = next;\n" " }\n" " }\n" " }\n" "}\n" "\n"; } void Compiler::writePostfixReduce() { bool unescape = false; for ( ReductionVect::Iter r = rootNamespace->reductions; r.lte(); r++ ) { Reduction *reduction = *r; if ( reduction->postfixBased ) { if ( !unescape ) writeUnescape(); writePostfixReduce( reduction ); } } } void Compiler::writeCommit() { *outStream << "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "\n" "#include \n" /* Not available on MAC OS. */ // "#include \n" "#include \n" "\n" "using std::endl;\n" "\n" "#include \"reducer.h\"\n" "\n"; computeNeeded(); writeReduceStructs(); writeReduceDispatchers(); //writePostfixReduce(); writeParseReduce(); writeNeeds(); }