From f653735830d537715f2885bd832cf04851d35401 Mon Sep 17 00:00:00 2001 From: Adrian Thurston Date: Sat, 14 Mar 2020 15:29:52 +0200 Subject: moved source files into commit repository --- src/reduce.cc | 954 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 954 insertions(+) create mode 100644 src/reduce.cc (limited to 'src/reduce.cc') diff --git a/src/reduce.cc b/src/reduce.cc new file mode 100644 index 00000000..89a95015 --- /dev/null +++ b/src/reduce.cc @@ -0,0 +1,954 @@ +/* + * 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(); +} -- cgit v1.2.1