libeval_compiler: wxString()-ification WIP
This commit is contained in:
parent
f6ea753968
commit
29a01e5515
|
@ -60,20 +60,20 @@ expr(A) ::= G_VALUE(B). { A.op = TR_NUMBER; A.value =
|
|||
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(); }
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <cstdarg>
|
||||
#endif
|
||||
|
||||
#include <reporter.h>
|
||||
#include <libeval_compiler/libeval_compiler.h>
|
||||
|
||||
/* 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<VALUE*>( 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<bool( int )> cond ) const
|
||||
wxString TOKENIZER::GetChars( std::function<bool( wxUniChar )> 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<bool( int )> cond ) const
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool TOKENIZER::MatchAhead( const std::string& match, std::function<bool( int )> stopCond ) const
|
||||
bool TOKENIZER::MatchAhead( const wxString& match, std::function<bool( wxUniChar )> 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<bool( int )>
|
|||
}
|
||||
|
||||
|
||||
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<UNIT_RESOLVER>();
|
||||
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: <a href='%d:%d'>%s</a>%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;
|
||||
}
|
||||
|
|
|
@ -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<std::string>& GetSupportedUnits() const
|
||||
virtual const std::vector<wxString>& GetSupportedUnits() const
|
||||
{
|
||||
static const std::vector<std::string> nullUnits;
|
||||
static const std::vector<wxString> 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<void(const ERROR_STATUS&)> aCallback );
|
||||
void ReportError( const wxString& aErrorMsg );
|
||||
bool IsErrorPending() const { return m_errorStatus.pendingError; }
|
||||
const ERROR_STATUS& GetError() const { return m_errorStatus; }
|
||||
|
||||
private:
|
||||
std::vector<VALUE*> m_ownedValues;
|
||||
std::stack<VALUE*> m_stack;
|
||||
wxString m_errorMessage;
|
||||
ERROR_STATUS m_errorStatus;
|
||||
std::function<void(const ERROR_STATUS&)> 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<bool( int )> cond ) const;
|
||||
wxString GetChars( std::function<bool( wxUniChar )> cond ) const;
|
||||
|
||||
bool MatchAhead( const std::string& match, std::function<bool( int )> stopCond ) const;
|
||||
bool MatchAhead( const wxString& match, std::function<bool( wxUniChar )> 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<void(const ERROR_STATUS&)> 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<void(const ERROR_STATUS&)> m_errorCallback;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue