00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <cstdio>
00017 #include <kglobal.h>
00018 #include <klocale.h>
00019 #include <limits.h>
00020 #include <vector>
00021 #include "mealMasterCompiler.hpp"
00022 #include "unitMap.hpp"
00023 #include "utils.hpp"
00024
00025 using namespace boost;
00026 using namespace std;
00027
00028 int mealMasterlex(void);
00029 int mealMasterrestart( FILE * );
00030
00031 long position;
00032 int lineNo;
00033 int errorLine;
00034 int recipeStartPos;
00035 int recipeEndPos;
00036 int recipeStartLine;
00037 int recipeEndLine;
00038 const char *errorMessage;
00039
00040 MealMasterCompiler *MealMasterCompiler::current = NULL;
00041 static vector< string > outputBuffer( 5 );
00042 static istream *currentInput;
00043
00044
00045
00046
00047
00048
00049
00050 void writeData( int index, const char *buffer, int size )
00051 {
00052 assert( MealMasterCompiler::current != NULL );
00053 assert( index >= 0 );
00054 assert( index < (signed)outputBuffer.size() );
00055 outputBuffer[ index ] += string( buffer, size );
00056 }
00057
00058 void writeUnit( int index, const char *buffer, int size )
00059 {
00060 string unit( buffer, size );
00061 assert( MealMasterCompiler::current != NULL );
00062 string inverseUnit( MealMasterCompiler::current->
00063 inverseUnitMap[ unit.c_str() ] );
00064 assert( !inverseUnit.empty() );
00065 #ifndef NDEBUG
00066
00067
00068
00069
00070
00071 #endif
00072 outputBuffer[ index ] += (const char *)i18n( inverseUnit.c_str() );
00073 }
00074
00075 void moveData( int index )
00076 {
00077 assert( index >= 1 );
00078 assert( index < (signed)outputBuffer.size() );
00079 outputBuffer[ 0 ] += outputBuffer[ index ];
00080 outputBuffer[ index ].clear();
00081 }
00082
00083 int readData( char *buffer, int max_size )
00084 {
00085 int result;
00086 assert( MealMasterCompiler::current != NULL );
00087 if ( currentInput == NULL ) {
00088 result = 0;
00089 } else {
00090 currentInput->read( buffer, max_size );
00091 if ( currentInput->eof() ) {
00092
00093 result = currentInput->gcount();
00094 currentInput = NULL;
00095 } else {
00096
00097 result = max_size;
00098 };
00099 };
00100
00101 return result;
00102 }
00103
00104 MealMasterCompiler::MealMasterCompiler
00105 ( int _maxRecipes, MealMasterParseErrorHandlerPtr _parseErrorHandler ):
00106 inverseUnitMap( createInverseUnitMap() ), maxRecipes(_maxRecipes),
00107 parseErrorHandler(_parseErrorHandler)
00108 {
00109 assert( current == NULL );
00110 current = this;
00111
00112
00113 lineNo = 1;
00114 }
00115
00116 MealMasterCompiler::~MealMasterCompiler(void)
00117 {
00118 current = NULL;
00119 }
00120
00121 void MealMasterCompiler::translate( istream &inputStream,
00122 ostream &outputStream ) const
00123 throw (Error)
00124 {
00125 currentInput = &inputStream;
00126
00127 position = inputStream.tellg();
00128
00129 mealMasterrestart( NULL );
00130 outputStream << "<?xml version='1.0' encoding='UTF-8'?>"
00131 << endl << "<insert xml:lang='"
00132 << anyMealLanguage() << "'>" << endl;
00133 int counter = maxRecipes;
00134 while ( counter != 0 ) {
00135 try {
00136 for ( int i=0; i<(signed)outputBuffer.size(); i++ )
00137 outputBuffer[ i ].clear();
00138 int x = mealMasterlex();
00139 if ( x == 0 ) break;
00140 ERRORMACRO( x < +2, MealMasterParseError,
00141 ( recipeStartLine, recipeEndLine, errorLine, &inputStream,
00142 recipeStartPos, recipeEndPos ), errorMessage );
00143 assert( x == 1 );
00144 outputStream << outputBuffer[ 0 ];
00145 } catch ( MealMasterParseError &e ) {
00146 #ifndef NDEBUG
00147 cerr << e.what() << endl;
00148 #endif
00149 assert( parseErrorHandler );
00150 parseErrorHandler->error( e );
00151 };
00152 if ( counter > 0 ) counter--;
00153 };
00154 outputStream << "</insert>\n";
00155
00156 inputStream.seekg( position, ios::beg );
00157 }