diff options
author | Adrian Thurston <thurston@colm.net> | 2019-09-09 10:19:58 -0600 |
---|---|---|
committer | Adrian Thurston <thurston@colm.net> | 2019-09-09 10:19:58 -0600 |
commit | fff52cd5a567ec541cd487b9fee2d89bf9b6f6eb (patch) | |
tree | 046a3f0f457343f7c99bf096863daf023a085051 /test/rlparse.d/inputdata.cc | |
parent | 2d8e9c3f5c0417d6237c945c50f92bf8d28b32d5 (diff) | |
download | colm-fff52cd5a567ec541cd487b9fee2d89bf9b6f6eb.tar.gz |
base (aapl, colm, ragel) test cases building
Diffstat (limited to 'test/rlparse.d/inputdata.cc')
-rw-r--r-- | test/rlparse.d/inputdata.cc | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/test/rlparse.d/inputdata.cc b/test/rlparse.d/inputdata.cc new file mode 100644 index 00000000..5a68facf --- /dev/null +++ b/test/rlparse.d/inputdata.cc @@ -0,0 +1,497 @@ +/* + * Copyright 2008-2016 Adrian Thurston <thurston@complang.org> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ragel.h" +#include "common.h" +#include "inputdata.h" +#include "parsedata.h" +#include "load.h" +#include "reducer.h" + +#include <iostream> +#include <unistd.h> + +using std::istream; +using std::cout; +using std::ifstream; +using std::stringstream; +using std::ostream; +using std::endl; +using std::ios; + +InputData::~InputData() +{ + includeDict.empty(); + inputItems.empty(); + parseDataList.empty(); + sectionList.empty(); + + for ( Vector<const char**>::Iter fns = streamFileNames; fns.lte(); fns++ ) { + const char **ptr = *fns; + while ( *ptr != 0 ) { + ::free( (void*)*ptr ); + ptr += 1; + } + free( (void*) *fns ); + } + + if ( outputFileName != 0 ) + delete[] outputFileName; + + if ( histogramFn != 0 ) + ::free( (void*)histogramFn ); + + if ( histogram != 0 ) + delete[] histogram; + + for ( ArgsVector::Iter bl = breadthLabels; bl.lte(); bl++ ) + free( (void*) *bl ); +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::cdDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) { + const char *ext = findFileExtension( inputFile ); + if ( ext != 0 && strcmp( ext, ".rh" ) == 0 ) + outputFileName = fileNameFromStem( inputFile, ".h" ); + else { + const char *defExtension = 0; + switch ( hostLang->lang ) { + case HostLang::C: defExtension = ".c"; break; + case HostLang::D: defExtension = ".d"; break; + default: break; + } + outputFileName = fileNameFromStem( inputFile, defExtension ); + } + } +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::goDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".go" ); +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::javaDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".java" ); +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::rubyDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".rb" ); +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::csharpDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) { + const char *ext = findFileExtension( inputFile ); + if ( ext != 0 && strcmp( ext, ".rh" ) == 0 ) + outputFileName = fileNameFromStem( inputFile, ".h" ); + else + outputFileName = fileNameFromStem( inputFile, ".cs" ); + } +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::ocamlDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".ml" ); +} + +/* Invoked by the parser when the root element is opened. */ +void InputData::crackDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".crk" ); +} + +void InputData::asmDefaultFileName( const char *inputFile ) +{ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".s" ); +} + +void InputData::rustDefaultFileName( const char *inputFile ) +{ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".rs" ); +} + +void InputData::juliaDefaultFileName( const char *inputFile ) +{ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".jl" ); +} + +void InputData::jsDefaultFileName( const char *inputFile ) +{ + /* If the output format is code and no output file name is given, then + * make a default. */ + if ( outputFileName == 0 ) + outputFileName = fileNameFromStem( inputFile, ".js" ); +} + +void InputData::makeDefaultFileName() +{ + switch ( hostLang->lang ) { + case HostLang::C: + case HostLang::D: + cdDefaultFileName( inputFileName ); + break; + case HostLang::Java: + javaDefaultFileName( inputFileName ); + break; + case HostLang::Go: + goDefaultFileName( inputFileName ); + break; + case HostLang::Ruby: + rubyDefaultFileName( inputFileName ); + break; + case HostLang::CSharp: + csharpDefaultFileName( inputFileName ); + break; + case HostLang::OCaml: + ocamlDefaultFileName( inputFileName ); + break; + case HostLang::Crack: + crackDefaultFileName( inputFileName ); + break; + case HostLang::Asm: + asmDefaultFileName( inputFileName ); + break; + case HostLang::Rust: + rustDefaultFileName( inputFileName ); + break; + case HostLang::Julia: + juliaDefaultFileName( inputFileName ); + break; + case HostLang::JS: + jsDefaultFileName( inputFileName ); + break; + } +} + +bool InputData::isBreadthLabel( const string &label ) +{ + for ( ArgsVector::Iter bl = breadthLabels; bl.lte(); bl++ ) { + if ( label == *bl ) + return true; + } + return false; +} + +void InputData::createOutputStream() +{ + /* Make sure we are not writing to the same file as the input file. */ + if ( outputFileName != 0 ) { + if ( strcmp( inputFileName, outputFileName ) == 0 ) { + error() << "output file \"" << outputFileName << + "\" is the same as the input file" << endl; + } + + /* Create the filter on the output and open it. */ + outFilter = new output_filter( outputFileName ); + + /* Open the output stream, attaching it to the filter. */ + outStream = new ostream( outFilter ); + } + else { + /* Writing out to std out. */ + outStream = &std::cout; + } +} + +void InputData::openOutput() +{ + if ( outFilter != 0 ) { + outFilter->open( outputFileName, ios::out|ios::trunc ); + if ( !outFilter->is_open() ) { + error() << "error opening " << outputFileName << " for writing" << endl; + abortCompile( 1 ); + } + } +} + +void InputData::verifyWriteHasData( InputItem *ii ) +{ +} + +void InputData::verifyWritesHaveData() +{ + for ( InputItemList::Iter ii = inputItems; ii.lte(); ii++ ) + verifyWriteHasData( ii ); +} + + +void InputData::closeOutput() +{ + /* If writing to a file, delete the ostream, causing it to flush. + * Standard out is flushed automatically. */ + if ( outputFileName != 0 ) { + delete outStream; + delete outFilter; + } +} + +bool InputData::checkLastRef( InputItem *ii ) +{ + if ( generateDot ) + return true; + + if ( errorCount > 0 ) + return false; + + /* + * 1. Go forward to next last reference. + * 2. Fully process that machine, mark as processed. + * 3. Move forward through input items until no longer + */ + if ( ii->section != 0 && ii->section->lastReference == ii ) { + /* Fully Process. */ + ParseData *pd = ii->pd; + + if ( pd->instanceList.length() > 0 ) { + + } + + /* Mark all input items referencing the machine as processed. */ + InputItem *toMark = lastFlush; + while ( true ) { + toMark->processed = true; + + if ( toMark == ii ) + break; + + toMark = toMark->next; + } + + /* Move forward, flushing input items until we get to an unprocessed + * input item. */ + while ( lastFlush != 0 && lastFlush->processed ) { + verifyWriteHasData( lastFlush ); + + if ( errorCount > 0 ) + return false; + + writeOutput( lastFlush ); + + lastFlush = lastFlush->next; + } + } + return true; +} + +void InputData::makeFirstInputItem() +{ + /* Make the first input item. */ + InputItem *firstInputItem = new InputItem; + firstInputItem->type = InputItem::HostData; + firstInputItem->loc.fileName = inputFileName; + firstInputItem->loc.line = 1; + firstInputItem->loc.col = 1; + inputItems.append( firstInputItem ); +} + +void InputData::writeOutput( InputItem *ii ) +{ + switch ( ii->type ) { + case InputItem::Write: { + cout << "write:"; + for ( size_t i = 0; i < ii->writeArgs.size(); i++ ) + cout << " " << ii->writeArgs[i]; + cout << endl; + break; + } + case InputItem::HostData: { + cout << ii->data.str() << endl; + break; + } + case InputItem::EndSection: { + break; + } + } +} + +/* Send eof to all parsers. */ +void InputData::terminateAllParsers( ) +{ +} + +void InputData::flushRemaining() +{ + /* Flush remaining items. */ + while ( lastFlush != 0 ) { + /* Flush out. */ + writeOutput( lastFlush ); + lastFlush = lastFlush->next; + } +} + +void InputData::makeTranslateOutputFileName() +{ + if ( backend == Translated ) { + origOutputFileName = outputFileName; + outputFileName = fileNameFromStem( inputFileName, ".ri" ); + genOutputFileName = outputFileName; + } +} + +void InputData::writeOutput() +{ + for ( InputItemList::Iter ii = inputItems; ii.lte(); ii++ ) + writeOutput( ii ); +} + +void InputData::processColm() +{ + /* + * Colm-based parser introduced in ragel 7. Uses more memory. + */ + + /* Check input file. */ + ifstream *inFile = new ifstream( inputFileName ); + if ( ! inFile->is_open() ) + error() << "could not open " << inputFileName << " for reading" << endp; + delete inFile; + + makeFirstInputItem(); + + LoadRagel *lr = newLoadRagel( *this, hostLang, minimizeLevel, minimizeOpt ); + loadRagel( lr, inputFileName ); + deleteLoadRagel( lr ); + + /* Bail on above error. */ + if ( errorCount > 0 ) + abortCompile( 1 ); + + assert( errorCount == 0 ); + + writeOutput(); + + for ( ParseDataList::Iter pd = parseDataList; pd.lte(); pd++ ) + pd->dump(); +} + +bool InputData::parseReduce() +{ + /* + * Colm-based reduction parser introduced in ragel 7. + */ + + SectionPass *sectionPass = new SectionPass( this ); + TopLevel *topLevel = new TopLevel( this, sectionPass, hostLang, + minimizeLevel, minimizeOpt ); + + if ( ! inLibRagel ) { + /* Check input file. File is actually opened by colm code. We don't + * need to perform the check if in libragel since it comes in via a + * string. */ + if ( input == 0 ) { + ifstream *inFile = new ifstream( inputFileName ); + if ( ! inFile->is_open() ) + error() << "could not open " << inputFileName << " for reading" << endp; + delete inFile; + } + } + + makeFirstInputItem(); + + if ( inLibRagel ) + sectionPass->reduceStr( inputFileName, input ); + else + sectionPass->reduceFile( inputFileName ); + + if ( errorCount ) + return false; + + curItem = inputItems.head; + lastFlush = inputItems.head; + + if ( inLibRagel ) + topLevel->reduceStr( inputFileName, input ); + else + topLevel->reduceFile( inputFileName ); + + if ( errorCount ) + return false; + + bool success = topLevel->success; + + delete topLevel; + delete sectionPass; + + return success; +} + +bool InputData::processReduce() +{ + makeDefaultFileName(); + makeTranslateOutputFileName(); + createOutputStream(); + + bool success = parseReduce(); + if ( success ) + flushRemaining(); + + for ( ParseDataList::Iter pd = parseDataList; pd.lte(); pd++ ) + pd->dump(); + + return success; +} + +bool InputData::process() +{ + switch ( frontend ) { + case ColmBased: { + processColm(); + return true; + } + case ReduceBased: { + return processReduce(); + } + } + + + return false; +} |