reducer.cc (ragel-7.0.0.9) | : | reducer.cc (ragel-7.0.0.10) | ||
---|---|---|---|---|
/* | /* | |||
* Copyright 2015 Adrian Thurston <thurston@complang.org> | * Copyright 2015 Adrian Thurston <thurston@colm.net> | |||
*/ | ||||
/* This file is part of Ragel. | ||||
* | * | |||
* Ragel is free software; you can redistribute it and/or modify | * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* it under the terms of the GNU General Public License as published by | * of this software and associated documentation files (the "Software"), to | |||
* the Free Software Foundation; either version 2 of the License, or | * deal in the Software without restriction, including without limitation the | |||
* (at your option) any later version. | * 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: | ||||
* | * | |||
* Ragel is distributed in the hope that it will be useful, | * The above copyright notice and this permission notice shall be included in al | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | l | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * copies or substantial portions of the Software. | |||
* GNU General Public License for more details. | ||||
* | * | |||
* You should have received a copy of the GNU General Public License | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* along with Ragel; if not, write to the Free Software | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | * 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 "reducer.h" | #include "reducer.h" | |||
#include "if.h" | ||||
#include <colm/colm.h> | #include <colm/colm.h> | |||
#include <colm/tree.h> | #include <colm/tree.h> | |||
#include <errno.h> | #include <errno.h> | |||
using std::endl; | using std::endl; | |||
using std::ifstream; | using std::ifstream; | |||
extern colm_sections rlparse_object; | extern colm_sections rlparse_object; | |||
skipping to change at line 50 | skipping to change at line 50 | |||
pd->fsmCtx->nextPriorKey += 1; | pd->fsmCtx->nextPriorKey += 1; | |||
pd->curDefPriorKey = priorDictEl->value; | pd->curDefPriorKey = priorDictEl->value; | |||
/* Make/get the local error key. */ | /* Make/get the local error key. */ | |||
LocalErrDictEl *localErrDictEl; | LocalErrDictEl *localErrDictEl; | |||
if ( pd->localErrDict.insert( data, pd->nextLocalErrKey, &localErrDictEl ) ) | if ( pd->localErrDict.insert( data, pd->nextLocalErrKey, &localErrDictEl ) ) | |||
pd->nextLocalErrKey += 1; | pd->nextLocalErrKey += 1; | |||
pd->curDefLocalErrKey = localErrDictEl->value; | pd->curDefLocalErrKey = localErrDictEl->value; | |||
} | } | |||
void TopLevel::tryMachineDef( InputLoc &loc, std::string name, | void TopLevel::tryMachineDef( const InputLoc &loc, std::string name, | |||
MachineDef *machineDef, bool isInstance ) | MachineDef *machineDef, bool isInstance ) | |||
{ | { | |||
GraphDictEl *newEl = pd->graphDict.insert( name ); | GraphDictEl *newEl = pd->graphDict.insert( name ); | |||
if ( newEl != 0 ) { | if ( newEl != 0 ) { | |||
/* New element in the dict, all good. */ | /* New element in the dict, all good. */ | |||
newEl->value = new VarDef( name, machineDef ); | newEl->value = new VarDef( name, machineDef ); | |||
newEl->isInstance = isInstance; | newEl->isInstance = isInstance; | |||
newEl->loc = loc; | newEl->loc = loc; | |||
newEl->value->isExport = exportContext[exportContext.length()-1]; | newEl->value->isExport = exportContext[exportContext.length()-1]; | |||
skipping to change at line 98 | skipping to change at line 98 | |||
priorityNum = 0; | priorityNum = 0; | |||
} | } | |||
else { | else { | |||
/* No overflow or underflow. */ | /* No overflow or underflow. */ | |||
priorityNum = aug; | priorityNum = aug; | |||
} | } | |||
return priorityNum; | return priorityNum; | |||
} | } | |||
void TopLevel::loadIncludeData( IncludeRec *el, IncludePass &includePass, const | ||||
string &fileName ) | ||||
{ | ||||
/* Count bytes. */ | ||||
size_t len = 0; | ||||
for ( IncItem *ii = includePass.incItems.head; ii != 0; ii = ii->next ) | ||||
len += ii->length; | ||||
/* Store bytes. */ | ||||
el->data = new char[len+1]; | ||||
len = 0; | ||||
if ( id->inLibRagel ) { | ||||
for ( IncItem *ii = includePass.incItems.head; ii != 0; ii = ii-> | ||||
next ) { | ||||
memcpy( el->data + len, id->input + ii->start, ii->length | ||||
); | ||||
len += ii->length; | ||||
} | ||||
} | ||||
else { | ||||
for ( IncItem *ii = includePass.incItems.head; ii != 0; ii = ii-> | ||||
next ) { | ||||
std::ifstream f( fileName.c_str() ); | ||||
f.seekg( ii->start, std::ios::beg ); | ||||
f.read( el->data + len, ii->length ); | ||||
size_t read = f.gcount(); | ||||
if ( read != ii->length ) { | ||||
pd->id->error(ii->loc) << "unexpected length in r | ||||
ead of included file: " | ||||
"possible change to file" << endp | ||||
; | ||||
} | ||||
len += read; | ||||
} | ||||
} | ||||
el->data[len] = 0; | ||||
el->len = len; | ||||
} | ||||
void TopLevel::include( const InputLoc &incLoc, bool fileSpecified, string fileN ame, string machine ) | void TopLevel::include( const InputLoc &incLoc, bool fileSpecified, string fileN ame, string machine ) | |||
{ | { | |||
/* Stash the current section name and pd. */ | /* Stash the current section name and pd. */ | |||
string sectionName = pd->sectionName; | string sectionName = pd->sectionName; | |||
ParseData *pd0 = pd; | ParseData *pd0 = pd; | |||
IncludeRec *el = id->includeDict.find( FnMachine( fileName, machine ) ); | const char **includeChecks = 0; | |||
if ( el == 0 ) { | long found = 0; | |||
el = new IncludeRec( fileName, machine ); | ||||
const char *inclSectionName = machine.c_str(); | ||||
const char **includeChecks = 0; | ||||
long found = 0; | /* Implement defaults for the input file and section name. */ | |||
if ( inclSectionName == 0 ) | ||||
/* First collect the locations of the text using an include pass. | inclSectionName = sectionName.c_str(); | |||
*/ | ||||
IncludePass includePass( id, machine ); | /* Build the include checks. */ | |||
if ( id->inLibRagel && !fileSpecified ) { | if ( fileSpecified ) | |||
el->foundFileName = curFileName; | includeChecks = pd->id->makeIncludePathChecks( curFileName, fileN | |||
ame.c_str() ); | ||||
/* In LibRagel and no file was specified in the include s | else { | |||
tatement. | char *test = new char[strlen(curFileName)+1]; | |||
* In this case we run the include pass on the input text | strcpy( test, curFileName ); | |||
supplied. */ | ||||
includePass.reduceStr( fileName.c_str(), id->hostLang, id | includeChecks = new const char*[2]; | |||
->input ); | ||||
} | includeChecks[0] = test; | |||
else { | includeChecks[1] = 0; | |||
const char *inclSectionName = machine.c_str(); | ||||
/* Implement defaults for the input file and section name | ||||
. */ | ||||
if ( inclSectionName == 0 ) | ||||
inclSectionName = sectionName.c_str(); | ||||
if ( fileSpecified ) | ||||
includeChecks = pd->id->makeIncludePathChecks( cu | ||||
rFileName, fileName.c_str() ); | ||||
else { | ||||
char *test = new char[strlen(curFileName)+1]; | ||||
strcpy( test, curFileName ); | ||||
includeChecks = new const char*[2]; | ||||
includeChecks[0] = test; | ||||
includeChecks[1] = 0; | ||||
} | ||||
ifstream *inFile = pd->id->tryOpenInclude( includeChecks, | ||||
found ); | ||||
if ( inFile == 0 ) { | ||||
id->error(incLoc) << "include: failed to locate f | ||||
ile" << endl; | ||||
const char **tried = includeChecks; | ||||
while ( *tried != 0 ) | ||||
id->error(incLoc) << "include: attempted: | ||||
\"" << *tried++ << '\"' << endl; | ||||
} | ||||
else { | ||||
delete inFile; | ||||
el->foundFileName = curFileName; | ||||
/* Don't include anything that's already been inc | ||||
luded. */ | ||||
if ( !pd->duplicateInclude( includeChecks[found], | ||||
inclSectionName ) ) { | ||||
pd->includeHistory.push_back( IncludeHist | ||||
oryItem( | ||||
includeChecks[found], inc | ||||
lSectionName ) ); | ||||
/* Either we are not in the lib, or a fil | ||||
e was specifed, use the | ||||
* file-based include pass. */ | ||||
includePass.reduceFile( includeChecks[fou | ||||
nd], id->hostLang ); | ||||
} | ||||
} | ||||
} | ||||
if ( includePass.incItems.length() == 0 ) { | ||||
pd->id->error(incLoc) << "could not find machine " << mac | ||||
hine << | ||||
" in " << fileName << endp; | ||||
} | ||||
else { | ||||
/* Load the data into include el. Save in the dict. */ | ||||
loadIncludeData( el, includePass, includeChecks[found] ); | ||||
id->includeDict.insert( el ); | ||||
includePass.incItems.empty(); | ||||
} | ||||
} | } | |||
/* Try to find the file. */ | ||||
ifstream *inFile = pd->id->tryOpenInclude( includeChecks, found ); | ||||
if ( inFile == 0 ) { | ||||
id->error(incLoc) << "include: failed to locate file" << endl; | ||||
const char **tried = includeChecks; | ||||
while ( *tried != 0 ) | ||||
id->error(incLoc) << "include: attempted: \"" << *tried++ | ||||
<< '\"' << endl; | ||||
return; | ||||
} | ||||
delete inFile; | ||||
// /* Don't include anything that's already been included. */ | ||||
// if ( !pd->duplicateInclude( includeChecks[found], inclSectionName ) ) { | ||||
// pd->includeHistory.push_back( IncludeHistoryItem( | ||||
// includeChecks[found], inclSectionName ) ); | ||||
// | ||||
// /* Either we are not in the lib, or a file was specifed, use the | ||||
// * file-based include pass. */ | ||||
// includePass.reduceFile( includeChecks[found], id->hostLang ); | ||||
// } | ||||
const char *targetMachine0 = targetMachine; | const char *targetMachine0 = targetMachine; | |||
const char *searchMachine0 = searchMachine; | const char *searchMachine0 = searchMachine; | |||
includeDepth += 1; | includeDepth += 1; | |||
pd = 0; | pd = 0; | |||
targetMachine = sectionName.c_str(); | targetMachine = sectionName.c_str(); | |||
searchMachine = machine.c_str(); | searchMachine = machine.c_str(); | |||
reduceStr( el->foundFileName.c_str(), el->data ); | reduceFile( includeChecks[found], false ); | |||
// if ( includePass.incItems.length() == 0 ) { | ||||
// pd->id->error(incLoc) << "could not find machine " << machine << | ||||
// " in " << fileName << endp; | ||||
// } | ||||
// else { | ||||
// /* Load the data into include el. Save in the dict. */ | ||||
// loadIncludeData( el, includePass, includeChecks[found] ); | ||||
// id->includeDict.insert( el ); | ||||
// includePass.incItems.empty(); | ||||
// } | ||||
pd = pd0; | pd = pd0; | |||
includeDepth -= 1; | includeDepth -= 1; | |||
targetMachine = targetMachine0; | targetMachine = targetMachine0; | |||
searchMachine = searchMachine0; | searchMachine = searchMachine0; | |||
} | } | |||
void TopLevel::loadImport( std::string fileName ) | void TopLevel::importFile( std::string file ) | |||
{ | { | |||
const char *argv[5]; | isImport = true; | |||
argv[0] = "rlparse"; | reduceFile( file.c_str(), true ); | |||
argv[1] = "import-file"; | isImport = false; | |||
argv[2] = fileName.c_str(); | } | |||
argv[3] = id->hostLang->rlhcArg; | ||||
argv[4] = 0; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_run_program( program, 4, argv ); | ||||
/* Extract the parse tree. */ | ||||
start Start = RagelTree( program ); | ||||
str Error = RagelError( program ); | ||||
_repeat_import ImportList = RagelImport( program ); | ||||
if ( Start == 0 ) { | ||||
pd->id->error(Error.loc()) << fileName << ": parse error: " << Er | ||||
ror.text() << std::endl; | ||||
return; | ||||
} | ||||
while ( !ImportList.end() ) { | ||||
import Import = ImportList.value(); | ||||
InputLoc loc = Import.loc(); | ||||
string name = Import.Name().text(); | ||||
loadMachineName( name ); | ||||
Literal *literal = 0; | ||||
switch ( Import.Val().prodName() ) { | ||||
case import_val::String: { | ||||
string s = Import.Val().string().text(); | ||||
Token tok; | ||||
tok.set( s.c_str(), s.size(), loc ); | ||||
literal = new Literal( loc, false, tok.data, tok. | ||||
length, Literal::LitString ); | ||||
break; | ||||
} | ||||
case import_val::Number: { | ||||
string s = Import.Val().number().text(); | ||||
Token tok; | ||||
tok.set( s.c_str(), s.size(), loc ); | ||||
literal = new Literal( loc, false, tok.data, tok. | ||||
length, Literal::Number ); | ||||
break; | ||||
} | ||||
} | ||||
MachineDef *machineDef = new MachineDef( | void TopLevel::import( const InputLoc &loc, std::string name, Literal *literal ) | |||
{ | ||||
MachineDef *machineDef = new MachineDef( | ||||
new Join( | new Join( | |||
new Expression( | new Expression( | |||
new Term( | new Term( | |||
new FactorWithAug( | new FactorWithAug( | |||
new FactorWithRep( | new FactorWithRep( | |||
new FactorWithNeg ( new Factor( literal ) ) | new FactorWithNeg ( new Factor( literal ) ) | |||
) | ||||
) | ) | |||
) | ) | |||
) | ) | |||
) | ) | |||
) | ); | |||
); | ||||
/* Generic creation of machine for instantiation and assignment. | ||||
*/ | ||||
tryMachineDef( loc, name, machineDef, false ); | ||||
machineDef->join->loc = loc; | ||||
ImportList = ImportList.next(); | ||||
} | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | /* Generic creation of machine for instantiation and assignment. */ | |||
colm_delete_program( program ); | tryMachineDef( loc, name, machineDef, false ); | |||
machineDef->join->loc = loc; | ||||
} | } | |||
void TopLevel::reduceFile( const char *inputFileName ) | void TopLevel::reduceFile( const char *inputFileName, bool import ) | |||
{ | { | |||
const char *argv[5]; | char idstr[64], imstr[64]; | |||
argv[0] = "rlparse"; | sprintf( idstr, "%d", includeDepth ); | |||
argv[1] = "toplevel-reduce-file"; | sprintf( imstr, "%d", import ); | |||
argv[2] = inputFileName; | ||||
argv[3] = id->hostLang->rlhcArg; | ||||
argv[4] = 0; | ||||
const char *prevCurFileName = curFileName; | ||||
curFileName = inputFileName; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_set_reduce_ctx( program, this ); | ||||
colm_run_program( program, 4, argv ); | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | ||||
str Error = RagelError( program ); | ||||
if ( Error != 0 ) | ||||
id->error(Error.loc()) << Error.text() << std::endl; | ||||
colm_delete_program( program ); | ||||
curFileName = prevCurFileName; | ||||
} | ||||
void TopLevel::reduceStr( const char *inputFileName, const char *input ) | const char *argv[7]; | |||
{ | ||||
const char *argv[6]; | ||||
argv[0] = "rlparse"; | argv[0] = "rlparse"; | |||
argv[1] = "toplevel-reduce-str"; | argv[1] = inputFileName; | |||
argv[2] = inputFileName; | argv[2] = imstr; // Import | |||
argv[3] = id->hostLang->rlhcArg; | argv[3] = idstr; // IncludeDepth | |||
argv[4] = input; | argv[4] = targetMachine == 0 ? "" : targetMachine; | |||
argv[5] = 0; | argv[5] = searchMachine == 0 ? "" : searchMachine; | |||
argv[6] = 0; | ||||
const char *prevCurFileName = curFileName; | const char *prevCurFileName = curFileName; | |||
curFileName = inputFileName; | curFileName = inputFileName; | |||
colm_program *program = colm_new_program( &rlparse_object ); | colm_program *program = colm_new_program( &rlparse_object ); | |||
colm_set_debug( program, 0 ); | colm_set_debug( program, 0 ); | |||
colm_set_reduce_ctx( program, this ); | colm_set_reduce_ctx( program, this ); | |||
colm_run_program( program, 5, argv ); | colm_run_program( program, 6, argv ); | |||
id->streamFileNames.append( colm_extract_fns( program ) ); | id->streamFileNames.append( colm_extract_fns( program ) ); | |||
str Error = RagelError( program ); | int length = 0; | |||
if ( Error != 0 ) | const char *err = colm_error( program, &length ); | |||
id->error(Error.loc()) << "trs: " << Error.text() << std::endl; | if ( err != 0 ) { | |||
// std::cout << "error" << std::endl; | ||||
id->error_plain() << string( err, length ) << std::endl; | ||||
} | ||||
colm_delete_program( program ); | colm_delete_program( program ); | |||
curFileName = prevCurFileName; | curFileName = prevCurFileName; | |||
} | } | |||
void SectionPass::reduceFile( const char *inputFileName ) | ||||
{ | ||||
const char *argv[5]; | ||||
argv[0] = "rlparse"; | ||||
argv[1] = "section-reduce-file"; | ||||
argv[2] = inputFileName; | ||||
argv[3] = id->hostLang->rlhcArg; | ||||
argv[4] = 0; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_set_reduce_ctx( program, this ); | ||||
colm_run_program( program, 4, argv ); | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | ||||
str Error = RagelError( program ); | ||||
if ( Error != 0 ) | ||||
id->error(Error.loc()) << Error.text() << std::endl; | ||||
colm_delete_program( program ); | ||||
} | ||||
void SectionPass::reduceStr( const char *inputFileName, const char *input ) | ||||
{ | ||||
const char *argv[6]; | ||||
argv[0] = "rlparse"; | ||||
argv[1] = "section-reduce-str"; | ||||
argv[2] = inputFileName; | ||||
argv[3] = id->hostLang->rlhcArg; | ||||
argv[4] = input; | ||||
argv[5] = 0; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_set_reduce_ctx( program, this ); | ||||
colm_run_program( program, 5, argv ); | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | ||||
str Error = RagelError( program ); | ||||
if ( Error != 0 ) | ||||
id->error(Error.loc()) << "srs: " << Error.text() << std::endl; | ||||
colm_delete_program( program ); | ||||
} | ||||
void IncludePass::reduceFile( const char *inputFileName, const HostLang *hostLan | ||||
g ) | ||||
{ | ||||
const char *argv[5]; | ||||
argv[0] = "rlparse"; | ||||
argv[1] = "include-reduce-file"; | ||||
argv[2] = inputFileName; | ||||
argv[3] = hostLang->rlhcArg; | ||||
argv[4] = 0; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_set_reduce_ctx( program, this ); | ||||
colm_run_program( program, 4, argv ); | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | ||||
str Error = RagelError( program ); | ||||
if ( Error != 0 ) | ||||
id->error(Error.loc()) << Error.text() << std::endl; | ||||
colm_delete_program( program ); | ||||
} | ||||
void IncludePass::reduceStr( const char *inputFileName, const HostLang *hostLang | ||||
, const char *input ) | ||||
{ | ||||
const char *argv[6]; | ||||
argv[0] = "rlparse"; | ||||
argv[1] = "include-reduce-str"; | ||||
argv[2] = inputFileName; | ||||
argv[3] = hostLang->rlhcArg; | ||||
argv[4] = input; | ||||
argv[5] = 0; | ||||
colm_program *program = colm_new_program( &rlparse_object ); | ||||
colm_set_debug( program, 0 ); | ||||
colm_set_reduce_ctx( program, this ); | ||||
colm_run_program( program, 5, argv ); | ||||
id->streamFileNames.append( colm_extract_fns( program ) ); | ||||
str Error = RagelError( program ); | ||||
if ( Error != 0 ) | ||||
id->error(Error.loc()) << Error.text() << std::endl; | ||||
colm_delete_program( program ); | ||||
} | ||||
End of changes. 23 change blocks. | ||||
244 lines changed or deleted | 106 lines changed or added |