diff options
Diffstat (limited to 'ragel/inputdata.cc')
-rw-r--r-- | ragel/inputdata.cc | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/ragel/inputdata.cc b/ragel/inputdata.cc new file mode 100644 index 00000000..e734538d --- /dev/null +++ b/ragel/inputdata.cc @@ -0,0 +1,270 @@ +/* + * Copyright 2008 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 "rlparse.h" +#include <iostream> +#include "dotcodegen.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::ios; + +/* 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; + case HostLang::D2: 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" ); +} + +void InputData::makeOutputStream() +{ + if ( ! generateDot && ! generateXML ) { + switch ( hostLang->lang ) { + case HostLang::C: + case HostLang::D: + case HostLang::D2: + 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; + } + } + + /* 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 ot std out. */ + outStream = &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; + exit(1); + } + } +} + +void InputData::prepareMachineGen() +{ + if ( generateDot ) { + /* Locate a machine spec to generate dot output for. We can only emit. + * Dot takes one graph at a time. */ + if ( machineSpec != 0 ) { + /* Machine specified. */ + ParserDictEl *pdEl = parserDict.find( machineSpec ); + if ( pdEl == 0 ) + error() << "could not locate machine specified with -S and/or -M" << endp; + dotGenParser = pdEl->value; + } + else { + /* No machine spec given, just use the first one. */ + if ( parserList.length() == 0 ) + error() << "no machine specification to generate graphviz output" << endp; + + dotGenParser = parserList.head; + } + + GraphDictEl *gdEl = 0; + + if ( machineName != 0 ) { + gdEl = dotGenParser->pd->graphDict.find( machineName ); + if ( gdEl == 0 ) + error() << "machine definition/instantiation not found" << endp; + } + else { + /* We are using the whole machine spec. Need to make sure there + * are instances in the spec. */ + if ( dotGenParser->pd->instanceList.length() == 0 ) + error() << "no machine instantiations to generate graphviz output" << endp; + } + + dotGenParser->pd->prepareMachineGen( gdEl ); + } + else { + /* No machine spec or machine name given. Generate everything. */ + for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) { + ParseData *pd = parser->value->pd; + if ( pd->instanceList.length() > 0 ) + pd->prepareMachineGen( 0 ); + } + } +} + +void InputData::generateReduced() +{ + if ( generateDot ) + dotGenParser->pd->generateReduced( *this ); + else { + for ( ParserDict::Iter parser = parserDict; parser.lte(); parser++ ) { + ParseData *pd = parser->value->pd; + if ( pd->instanceList.length() > 0 ) + pd->generateReduced( *this ); + } + } +} + +/* Send eof to all parsers. */ +void InputData::terminateAllParsers( ) +{ + /* FIXME: a proper token is needed here. Suppose we should use the + * location of EOF in the last file that the parser was referenced in. */ + InputLoc loc; + loc.fileName = "<EOF>"; + loc.line = 0; + loc.col = 0; + for ( ParserDict::Iter pdel = parserDict; pdel.lte(); pdel++ ) + pdel->value->token( loc, Parser_tk_eof, 0, 0 ); +} + +void InputData::verifyWritesHaveData() +{ + if ( !generateXML && !generateDot ) { + for ( InputItemList::Iter ii = inputItems; ii.lte(); ii++ ) { + if ( ii->type == InputItem::Write ) { + if ( ii->pd->cgd == 0 ) + error( ii->loc ) << "no machine instantiations to write" << endl; + } + } + } +} + +void InputData::writeOutput() +{ + if ( generateXML ) + writeXML( *outStream ); + else if ( generateDot ) + static_cast<GraphvizDotGen*>(dotGenParser->pd->cgd)->writeDotFile(); + else { + for ( InputItemList::Iter ii = inputItems; ii.lte(); ii++ ) { + if ( ii->type == InputItem::Write ) { + CodeGenData *cgd = ii->pd->cgd; + ::keyOps = &cgd->thisKeyOps; + + cgd->writeStatement( ii->loc, ii->writeArgs.length()-1, ii->writeArgs.data ); + } + else { + *outStream << '\n'; + lineDirective( *outStream, inputFileName, ii->loc.line ); + *outStream << ii->data.str(); + } + } + } +} + |