From 29a01e55158b8f83081bcaec4c08e8839c63f015 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Sun, 9 Aug 2020 00:39:05 +0200 Subject: [PATCH] libeval_compiler: wxString()-ification WIP --- common/libeval_compiler/grammar.lemon | 30 +-- common/libeval_compiler/libeval_compiler.cpp | 227 ++++++++++++------- include/libeval_compiler/libeval_compiler.h | 106 ++++----- 3 files changed, 208 insertions(+), 155 deletions(-) diff --git a/common/libeval_compiler/grammar.lemon b/common/libeval_compiler/grammar.lemon index 8ba07802f8..ada6951462 100644 --- a/common/libeval_compiler/grammar.lemon +++ b/common/libeval_compiler/grammar.lemon @@ -54,26 +54,26 @@ in ::= in stmt. /* A statement can be empty, an expr or an expr followed by ';' */ stmt ::= G_ENDS. stmt ::= expr(A) G_ENDS. { pEval->setRoot(A); } -//stmt ::= expr G_SEMCOL. { pEval->setRoot(NULL); } +//stmt ::= expr G_SEMCOL. { pEval->setRoot(NULL); } expr(A) ::= G_VALUE(B). { A.op = TR_NUMBER; A.value = B.value; A.leaf[0] = A.leaf[1] = NULL; A.valid = true; A.srcPos = pEval->GetSourcePos(); } expr(A) ::= G_VALUE(B) G_UNIT(C). { A.op = TR_NUMBER; A.value = B.value; A.leaf[0] = newNode(TR_UNIT, C.value.type, ""); A.leaf[1] = NULL; A.valid = true; A.srcPos = pEval->GetSourcePos(); } expr(A) ::= G_STRING(B). { A.op = TR_STRING; A.value = B.value; A.leaf[0] = A.leaf[1] = NULL; A.valid = true; A.srcPos = pEval->GetSourcePos(); } expr(A) ::= G_IDENTIFIER(B). { A.op = TR_IDENTIFIER; A.value = B.value; A.leaf[0] = A.leaf[1] = NULL; A.valid = true; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_LESS_THAN expr(C). { A.op = TR_OP_LESS; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_GREATER_THAN expr(C). { A.op = TR_OP_GREATER; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_LESS_EQUAL_THAN expr(C). { A.op = TR_OP_LESS_EQUAL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_GREATER_EQUAL_THAN expr(C). { A.op = TR_OP_GREATER_EQUAL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_NOT_EQUAL expr(C). { A.op = TR_OP_NOT_EQUAL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_BOOL_AND expr(C). { A.op = TR_OP_BOOL_AND; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_BOOL_OR expr(C). { A.op = TR_OP_BOOL_OR; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_PLUS expr(C). { A.op = TR_OP_ADD; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_MINUS expr(C). { A.op = TR_OP_SUB; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_MULT expr(C). { A.op = TR_OP_MUL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_DIVIDE expr(C). { A.op = TR_OP_DIV; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_EQUAL expr(C). { A.op = TR_OP_EQUAL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_LESS_THAN expr(C). { A.op = TR_OP_LESS; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_GREATER_THAN expr(C). { A.op = TR_OP_GREATER; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_LESS_EQUAL_THAN expr(C). { A.op = TR_OP_LESS_EQUAL; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_GREATER_EQUAL_THAN expr(C). { A.op = TR_OP_GREATER_EQUAL; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_NOT_EQUAL expr(C). { A.op = TR_OP_NOT_EQUAL; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_BOOL_AND expr(C). { A.op = TR_OP_BOOL_AND; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_BOOL_OR expr(C). { A.op = TR_OP_BOOL_OR; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_PLUS expr(C). { A.op = TR_OP_ADD; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_MINUS expr(C). { A.op = TR_OP_SUB; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_MULT expr(C). { A.op = TR_OP_MUL; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_DIVIDE expr(C). { A.op = TR_OP_DIV; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_EQUAL expr(C). { A.op = TR_OP_EQUAL; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid = B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= expr(B) G_STRUCT_REF expr(C). { A.op = TR_STRUCT_REF; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid=B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= expr(B) G_STRUCT_REF expr(C). { A.op = TR_STRUCT_REF; A.value.wstr = NULL; A.leaf[0] = copyNode(B); A.leaf[1] = copyNode(C); A.valid=B.valid && C.valid; A.srcPos = pEval->GetSourcePos(); } expr(A) ::= G_PARENL expr(B) G_PARENR. { A.op = B.op; A.value = B.value; A.valid=B.valid; A.leaf[0] = B.leaf[0]; A.leaf[1] = B.leaf[1]; A.srcPos = pEval->GetSourcePos(); } -expr(A) ::= G_IDENTIFIER(F) G_PARENL expr(B) G_PARENR. { A.op = TR_OP_FUNC_CALL; A.leaf[0] = copyNode(F); A.leaf[1] = copyNode(B); A.valid = true; A.srcPos = pEval->GetSourcePos(); } +expr(A) ::= G_IDENTIFIER(F) G_PARENL expr(B) G_PARENR. { A.op = TR_OP_FUNC_CALL; A.value.wstr = NULL; A.leaf[0] = copyNode(F); A.leaf[1] = copyNode(B); A.valid = true; A.srcPos = pEval->GetSourcePos(); } diff --git a/common/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp index c322ef7416..dbd69e2bc9 100644 --- a/common/libeval_compiler/libeval_compiler.cpp +++ b/common/libeval_compiler/libeval_compiler.cpp @@ -26,7 +26,6 @@ #include #endif -#include #include /* The (generated) lemon parser is written in C. @@ -49,27 +48,56 @@ namespace LIBEVAL #pragma GCC diagnostic pop #endif -static void libeval_dbg( int level, const char* fmt, ... ) + +#define libeval_dbg(level, fmt, ...) \ + wxLogTrace( "libeval_compiler", fmt, __VA_ARGS__ ) + +TREE_NODE* copyNode( TREE_NODE& t ) { -#ifdef DEBUG - if(level < -10) // fixme: tom's debugging. + auto t2 = new TREE_NODE(); + t2->valid = t.valid; + + if( t.value.wstr ) { - va_list ap; - va_start( ap, fmt ); - fprintf( stderr, "libeval: " ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); + t2->value.wstr = new wxString(*t.value.wstr); } -#endif + else + { + t2->value.wstr = nullptr; + } + t2->value.type = t.value.type; + t2->op = t.op; + t2->leaf[0] = t.leaf[0]; + t2->leaf[1] = t.leaf[1]; + t2->isTerminal = false; + t2->srcPos = t.srcPos; + t2->uop = nullptr; + return t2; } -static const std::string formatOpName( int op ) +TREE_NODE* newNode( int op, int type, const wxString& value ) +{ + auto t2 = new TREE_NODE(); + t2->valid = true; + t2->value.wstr = new wxString( value ); + t2->op = op; + t2->value.type = type; + t2->leaf[0] = nullptr; + t2->leaf[1] = nullptr; + t2->isTerminal = false; + t2->srcPos = -1; + t2->uop = nullptr; + return t2; +} + + +static const wxString formatOpName( int op ) { static const struct { int op; - std::string mnemonic; + wxString mnemonic; } simpleOps[] = { @@ -90,14 +118,14 @@ static const std::string formatOpName( int op ) } -std::string UOP::Format() const +wxString UOP::Format() const { - char str[LIBEVAL_MAX_LITERAL_LENGTH]; + wxString str; switch( m_op ) { case TR_UOP_PUSH_VAR: - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH VAR [%p]", m_arg ); + str = wxString::Format( "PUSH VAR [%p]", m_arg ); break; case TR_UOP_PUSH_VALUE: @@ -105,24 +133,24 @@ std::string UOP::Format() const VALUE* val = reinterpret_cast( m_arg ); if( !val ) - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH nullptr" ); + str = wxString::Format( "PUSH nullptr" ); else if( val->GetType() == VT_NUMERIC ) - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH NUM [%.10f]", val->AsDouble() ); + str = wxString::Format( "PUSH NUM [%.10f]", val->AsDouble() ); else - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "PUSH STR [%ls]", GetChars( val->AsString() ) ); + str = wxString::Format( "PUSH STR [%ls]", GetChars( val->AsString() ) ); } break; case TR_OP_METHOD_CALL: - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "MCALL" ); + str = wxString::Format( "MCALL" ); break; case TR_OP_FUNC_CALL: - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "FCALL" ); + str = wxString::Format( "FCALL" ); break; default: - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "%s %d", formatOpName( m_op ).c_str(), m_op ); + str = wxString::Format( "%s %d", formatOpName( m_op ).c_str(), m_op ); break; } @@ -137,9 +165,9 @@ UCODE::~UCODE() } -std::string UCODE::Dump() const +wxString UCODE::Dump() const { - std::string rv; + wxString rv; for( auto op : m_ucode ) { @@ -151,9 +179,9 @@ std::string UCODE::Dump() const }; -std::string TOKENIZER::GetChars( std::function cond ) const +wxString TOKENIZER::GetChars( std::function cond ) const { - std::string rv; + wxString rv; size_t p = m_pos; // printf("p %d len %d\n", p, str.length() ); @@ -166,9 +194,9 @@ std::string TOKENIZER::GetChars( std::function cond ) const return rv; } -bool TOKENIZER::MatchAhead( const std::string& match, std::function stopCond ) const +bool TOKENIZER::MatchAhead( const wxString& match, std::function stopCond ) const { - int remaining = m_str.length() - m_pos; + int remaining = m_str.Length() - m_pos; if( remaining < (int) match.length() ) return false; @@ -180,11 +208,8 @@ bool TOKENIZER::MatchAhead( const std::string& match, std::function } -COMPILER::COMPILER( REPORTER* aReporter, int aSourceLine, int aSourceOffset ) : - m_lexerState( COMPILER::LS_DEFAULT ), - m_reporter( aReporter ), - m_originLine( aSourceLine ), - m_originOffset( aSourceOffset ) +COMPILER::COMPILER() : + m_lexerState( COMPILER::LS_DEFAULT ) { m_localeDecimalSeparator = '.'; m_sourcePos = 0; @@ -192,6 +217,7 @@ COMPILER::COMPILER( REPORTER* aReporter, int aSourceLine, int aSourceOffset ) : m_unitResolver = std::make_unique(); m_parser = LIBEVAL::ParseAlloc( malloc ); m_tree = nullptr; + m_errorStatus.pendingError = false; } @@ -222,7 +248,7 @@ void COMPILER::Clear() void COMPILER::parseError( const char* s ) { - reportError( s ); + reportError( CST_PARSE, s ); } @@ -232,7 +258,7 @@ void COMPILER::parseOk() } -bool COMPILER::Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPreflightContext ) +bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext ) { // Feed parser token after token until end of input. @@ -263,6 +289,9 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPref libeval_dbg(10, "parse: tok %d\n", tok.token ); Parse( m_parser, tok.token, tok.value, this ); + if ( m_errorStatus.pendingError ) + return false; + if( m_parseFinished || tok.token == G_ENDS ) { // Reset parser by passing zero as token ID, value is ignored. @@ -275,7 +304,7 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPref } -void COMPILER::newString( const std::string& aString ) +void COMPILER::newString( const wxString& aString ) { Clear(); @@ -309,11 +338,11 @@ COMPILER::T_TOKEN COMPILER::getToken() bool COMPILER::lexString( COMPILER::T_TOKEN& aToken ) { - std::string str = m_tokenizer.GetChars( []( int c ) -> bool { return c != '\''; } ); + wxString str = m_tokenizer.GetChars( []( int c ) -> bool { return c != '\''; } ); //printf("STR LIT '%s'\n", (const char *)str.c_str() ); aToken.token = G_STRING; - snprintf( aToken.value.value.str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", str.c_str() ); + aToken.value.value.wstr = new wxString( str ); m_tokenizer.NextChar( str.length() + 1 ); m_lexerState = LS_DEFAULT; @@ -325,7 +354,7 @@ int COMPILER::resolveUnits() { int unitId = 0; - for( const std::string& unitName : m_unitResolver->GetSupportedUnits() ) + for( const wxString& unitName : m_unitResolver->GetSupportedUnits() ) { if( m_tokenizer.MatchAhead( unitName, []( int c ) -> bool { return !isalnum( c ); } ) ) { @@ -344,7 +373,7 @@ int COMPILER::resolveUnits() bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) { T_TOKEN retval; - std::string current; + wxString current; int convertFrom; wxString msg; @@ -358,7 +387,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) } auto isDecimalSeparator = - [&]( char ch ) -> bool + [&]( wxUniChar ch ) -> bool { return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' ); }; @@ -368,7 +397,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) [&]() { bool haveSeparator = false; - int ch = m_tokenizer.GetChar(); + wxUniChar ch = m_tokenizer.GetChar(); do { @@ -419,7 +448,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) // VALUE extractNumber(); retval.token = G_VALUE; - snprintf( retval.value.value.str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", current.c_str() ); + retval.value.value.wstr = new wxString( current ); } else if( ( convertFrom = resolveUnits() ) >= 0 ) { @@ -448,7 +477,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) //printf("id '%s'\n", (const char *) current.c_str() ); //fflush( stdout ); retval.token = G_IDENTIFIER; - snprintf( retval.value.value.str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", current.c_str() ); + retval.value.value.wstr = new wxString( current ); m_tokenizer.NextChar( current.length() ); } else if( m_tokenizer.MatchAhead( "==", []( int c ) -> bool { return c != '='; } ) ) @@ -499,7 +528,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) case '.': retval.token = G_STRUCT_REF; break; default: - reportError( wxString::Format( _( "Unrecognized character '%c'" ), (char) ch ) ); + reportError( CST_PARSE, wxString::Format( _( "Unrecognized character '%c'" ), (char) ch ) ); break; } @@ -511,24 +540,17 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) } -const std::string formatNode( TREE_NODE* tok ) +const wxString formatNode( TREE_NODE* tok ) { - // printf("fmt tok %p v %p ", tok, tok->value.v ); - // fflush( stdout ); - - char str[LIBEVAL_MAX_LITERAL_LENGTH]; - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", (const char*) tok->value.str ); - return str; + return *(tok->value.wstr); } -void dumpNode( std::string& buf, TREE_NODE* tok, int depth = 0 ) +void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 ) { - char str[LIBEVAL_MAX_LITERAL_LENGTH]; - snprintf( str, LIBEVAL_MAX_LITERAL_LENGTH, "\n[%p L0:%-20p L1:%-20p] ", - tok, - tok->leaf[0], - tok->leaf[1] ); + wxString str; + + str.Printf( "\n[%p L0:%-20p L1:%-20p] ", tok, tok->leaf[0], tok->leaf[1] ); buf += str; for( int i = 0; i < 2 * depth; i++ ) @@ -570,24 +592,39 @@ void dumpNode( std::string& buf, TREE_NODE* tok, int depth = 0 ) case TR_OP_FUNC_CALL: buf += "CALL '"; - buf += tok->leaf[0]->value.str; + buf += *tok->leaf[0]->value.wstr; buf += "': "; dumpNode( buf, tok->leaf[1], depth + 1 ); break; case TR_UNIT: - sprintf( str, "UNIT: %d ", tok->value.type ); + str.Printf( "UNIT: %d ", tok->value.type ); buf += str; break; } } -void COMPILER::reportError( const wxString& aErrorMsg, int aPos ) +void CONTEXT::ReportError( const wxString& aErrorMsg ) +{ + m_errorStatus.pendingError = true; + m_errorStatus.message = aErrorMsg; + m_errorStatus.srcPos = -1; + m_errorStatus.stage = CST_RUNTIME; + + if( m_errorCallback ) + m_errorCallback( m_errorStatus ); +} + + +void COMPILER::reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, int aPos ) { if( aPos == -1 ) aPos = m_sourcePos; +// fixme: no HTML or anything UI-related here. + +#if 0 wxString rest; wxString first = aErrorMsg.BeforeFirst( '|', &rest ); wxString msg = wxString::Format( _( "ERROR: %s%s" ), @@ -595,8 +632,15 @@ void COMPILER::reportError( const wxString& aErrorMsg, int aPos ) m_originOffset + aPos, first, rest ); +#endif - m_reporter->Report( msg, RPT_SEVERITY_ERROR ); + m_errorStatus.pendingError = true; + m_errorStatus.stage = stage; + m_errorStatus.message = aErrorMsg; + m_errorStatus.srcPos = aPos; + + if( m_errorCallback ) + m_errorCallback( m_errorStatus ); } @@ -635,10 +679,10 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) stack.push_back( m_tree ); - std::string dump; + wxString dump; dumpNode( dump, m_tree, 0 ); - libeval_dbg(3,"Tree dump:\n%s\n\n", dump.c_str() ); + libeval_dbg(3,"Tree dump:\n%s\n\n", (const char*) dump.c_str() ); while( !stack.empty() ) { @@ -662,21 +706,21 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) { case TR_IDENTIFIER: { - char* itemName = node->leaf[0]->value.str; - char* propName = node->leaf[1]->value.str; + wxString itemName = *node->leaf[0]->value.wstr; + wxString propName = *node->leaf[1]->value.wstr; VAR_REF* vref = aCode->CreateVarRef( itemName, propName ); if( !vref ) { msg.Printf( _( "Unrecognized item '%s'" ), itemName ); - reportError( msg, node->leaf[0]->srcPos - (int) strlen( itemName ) ); + reportError( CST_CODEGEN, msg, node->leaf[0]->srcPos - (int) strlen( itemName ) ); return false; } if( vref->GetType() == VT_PARSE_ERROR ) { msg.Printf( _( "Unrecognized property '%s'" ), propName ); - reportError( msg, node->leaf[1]->srcPos - (int) strlen( propName ) ); + reportError( CST_CODEGEN, msg, node->leaf[1]->srcPos - (int) strlen( propName ) ); return false; } @@ -686,29 +730,38 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) } case TR_OP_FUNC_CALL: { - char* itemName = node->leaf[0]->value.str; + wxString itemName = *node->leaf[0]->value.wstr; VAR_REF* vref = aCode->CreateVarRef( itemName, "" ); if( !vref ) { msg.Printf( _( "Unrecognized item '%s'" ), itemName ); - reportError( msg, node->leaf[0]->srcPos - (int) strlen( itemName ) ); + reportError( CST_CODEGEN, msg, node->leaf[0]->srcPos - (int) strlen( itemName ) ); return false; } - char* functionName = node->leaf[1]->leaf[0]->value.str; + wxString functionName = *node->leaf[1]->leaf[0]->value.wstr; auto func = aCode->CreateFuncCall( functionName ); + libeval_dbg(10, "emit func call: %s\n", (const char*) functionName.c_str() ); + if( !func ) { msg.Printf( _( "Unrecognized function '%s'" ), functionName ); - reportError( msg, node->leaf[1]->leaf[0]->srcPos + 1 ); + reportError( CST_CODEGEN, msg, node->leaf[1]->leaf[0]->srcPos + 1 ); return false; } // Preflight the function call + // fixme - this won't really work because of dynamic typing... + + #if 0 + wxString paramStr; + if( node->value.wstr ) + paramStr = *node->value.wstr; + VALUE* param = aPreflightContext->AllocValue(); - param->Set( node->value.str ); + param->Set( paramStr ); aPreflightContext->Push( param ); try @@ -719,18 +772,21 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) catch( ... ) { } + #endif /* SREF -> FUNC_CALL -> leaf0/1 */ node->leaf[1]->leaf[0]->leaf[0] = nullptr; node->leaf[1]->leaf[0]->leaf[1] = nullptr; - if( !aPreflightContext->GetError().IsEmpty() ) + #if 0 + if( aPreflightContext->IsErrorPending() ) { - reportError( aPreflightContext->GetError(), + reportError( CST_CODEGEN, aPreflightContext->GetError().message, node->leaf[1]->leaf[1]->srcPos - - (int) strlen( node->value.str ) - 1 ); + - (int) paramStr.length() - 1 ); return false; } + #endif visitedNodes.insert( node->leaf[0] ); visitedNodes.insert( node->leaf[1]->leaf[0] ); @@ -745,17 +801,20 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) case TR_NUMBER: { - int units = 1; TREE_NODE* son = node->leaf[0]; + double value; if( son && son->op == TR_UNIT ) { //printf( "HandleUnit: %s unit %d\n", node->value.str, son->value.type ); - units = son->value.type; + int units = son->value.type; + value = m_unitResolver->Convert( *node->value.wstr, units ); visitedNodes.insert( son ); } - - double value = m_unitResolver->Convert( node->value.str, units ); + else + { + value = wxAtof( *node->value.wstr ); + } node->uop = makeUop( TR_UOP_PUSH_VALUE, value ); node->isTerminal = true; @@ -765,19 +824,19 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) case TR_STRING: { - node->uop = makeUop( TR_UOP_PUSH_VALUE, node->value.str ); + node->uop = makeUop( TR_UOP_PUSH_VALUE, *node->value.wstr ); node->isTerminal = true; break; } case TR_IDENTIFIER: { - VAR_REF* vref = aCode->CreateVarRef( node->value.str, "" ); + VAR_REF* vref = aCode->CreateVarRef( *node->value.wstr, "" ); if( !vref ) { - msg.Printf( _( "Unrecognized item '%s'" ), node->value.str ); - reportError( msg, node->srcPos - (int) strlen( node->value.str ) ); + msg.Printf( _( "Unrecognized item '%s'" ), *node->value.wstr ); + reportError( CST_CODEGEN, msg, node->srcPos - (int) strlen( *node->value.wstr ) ); return false; } @@ -811,7 +870,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) stack.pop_back(); } - libeval_dbg(2,"DUMp: \n%s\n", aCode->Dump().c_str() ); + libeval_dbg(2,"dump: \n%s\n", aCode->Dump().c_str() ); return true; } diff --git a/include/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h index 232fb4f4da..a33fdf856d 100644 --- a/include/libeval_compiler/libeval_compiler.h +++ b/include/libeval_compiler/libeval_compiler.h @@ -56,6 +56,24 @@ namespace LIBEVAL class COMPILER; +enum COMPILATION_STAGE +{ + CST_PARSE = 0, + CST_CODEGEN, + CST_RUNTIME +}; + +struct ERROR_STATUS +{ + bool pendingError = false; + + + COMPILATION_STAGE stage; + wxString message; // Note: use wxString for GUI-related strings + int srcPos; +}; + + enum VAR_TYPE_T { VT_STRING = 1, @@ -82,7 +100,8 @@ struct TREE_NODE { struct value_s { - char str[LIBEVAL_MAX_LITERAL_LENGTH]; + wxString *wstr; + //char str[LIBEVAL_MAX_LITERAL_LENGTH]; int type; } value; @@ -94,38 +113,8 @@ struct TREE_NODE int srcPos; }; - -static inline TREE_NODE* copyNode( TREE_NODE& t ) -{ - auto t2 = new TREE_NODE(); - t2->valid = t.valid; - snprintf( t2->value.str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", t.value.str ); - t2->op = t.op; - t2->value.type = t.value.type; - t2->leaf[0] = t.leaf[0]; - t2->leaf[1] = t.leaf[1]; - t2->isTerminal = false; - t2->srcPos = t.srcPos; - t2->uop = nullptr; - return t2; -} - - -static inline TREE_NODE* newNode( int op, int type, const std::string& value ) -{ - auto t2 = new TREE_NODE(); - t2->valid = true; - snprintf( t2->value.str, LIBEVAL_MAX_LITERAL_LENGTH, "%s", value.c_str() ); - t2->op = op; - t2->value.type = type; - t2->leaf[0] = nullptr; - t2->leaf[1] = nullptr; - t2->isTerminal = false; - t2->srcPos = -1; - t2->uop = nullptr; - return t2; -} - +TREE_NODE* copyNode( TREE_NODE& t ); +TREE_NODE* newNode( int op, int type, const wxString& value ); class UNIT_RESOLVER { @@ -138,14 +127,14 @@ public: { } - virtual const std::vector& GetSupportedUnits() const + virtual const std::vector& GetSupportedUnits() const { - static const std::vector nullUnits; + static const std::vector nullUnits; return nullUnits; } - virtual double Convert( const std::string& aString, int unitType ) const + virtual double Convert( const wxString& aString, int unitType ) const { return 0.0; }; @@ -269,15 +258,18 @@ public: int SP() const { return m_stack.size(); - } + }; - void ReportError( const wxString& aErrorMsg ) { m_errorMessage = aErrorMsg; } - const wxString& GetError() const { return m_errorMessage; } + void SetErrorCallback( std::function aCallback ); + void ReportError( const wxString& aErrorMsg ); + bool IsErrorPending() const { return m_errorStatus.pendingError; } + const ERROR_STATUS& GetError() const { return m_errorStatus; } private: std::vector m_ownedValues; std::stack m_stack; - wxString m_errorMessage; + ERROR_STATUS m_errorStatus; + std::function m_errorCallback; }; @@ -294,14 +286,14 @@ public: } VALUE* Run( CONTEXT* ctx ); - std::string Dump() const; + wxString Dump() const; - virtual VAR_REF* CreateVarRef( const char* var, const char* field ) + virtual VAR_REF* CreateVarRef( const wxString& var, const wxString& field ) { return nullptr; }; - virtual FUNC_PTR CreateFuncCall( const char* name ) + virtual FUNC_PTR CreateFuncCall( const wxString& name ) { return nullptr; }; @@ -327,7 +319,7 @@ public: void Exec( CONTEXT* ctx ); - std::string Format() const; + wxString Format() const; private: int m_op; @@ -338,7 +330,7 @@ private: class TOKENIZER { public: - void Restart( const std::string& aStr ) + void Restart( const wxString& aStr ) { m_str = aStr; m_pos = 0; @@ -373,12 +365,12 @@ public: return m_pos; } - std::string GetChars( std::function cond ) const; + wxString GetChars( std::function cond ) const; - bool MatchAhead( const std::string& match, std::function stopCond ) const; + bool MatchAhead( const wxString& match, std::function stopCond ) const; private: - std::string m_str; + wxString m_str; size_t m_pos; }; @@ -386,7 +378,7 @@ private: class COMPILER { public: - COMPILER( REPORTER* aReporter, int aSourceLine, int aSourceOffset ); + COMPILER(); virtual ~COMPILER(); /* @@ -404,7 +396,11 @@ public: void setRoot( LIBEVAL::TREE_NODE root ); void freeTree( LIBEVAL::TREE_NODE *tree ); - bool Compile( const std::string& aString, UCODE* aCode, CONTEXT* aPreflightContext ); + bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext ); + + void SetErrorCallback( std::function aCallback ); + bool IsErrorPending() const { return m_errorStatus.pendingError; } + const ERROR_STATUS& GetError() const { return m_errorStatus; } protected: enum LEXER_STATE @@ -417,7 +413,7 @@ protected: bool generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ); - void reportError( const wxString& aErrorMsg, int aPos = -1 ); + void reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, int aPos = -1 ); /* Token type used by the tokenizer */ struct T_TOKEN @@ -427,7 +423,7 @@ protected: }; /* Begin processing of a new input string */ - void newString( const std::string& aString ); + void newString( const wxString& aString ); /* Tokenizer: Next token/value taken from input string. */ T_TOKEN getToken(); @@ -471,11 +467,9 @@ protected: int m_sourcePos; bool m_parseFinished; - REPORTER* m_reporter; - int m_originLine; // Location in the file of the start of the expression - int m_originOffset; - TREE_NODE* m_tree; + ERROR_STATUS m_errorStatus; + std::function m_errorCallback; };