libeval_compiler: integrated in common/

This commit is contained in:
Tomasz Wlostowski 2020-06-14 01:19:22 +02:00
parent 539984229d
commit aaa91655aa
6 changed files with 79 additions and 51 deletions

View File

@ -4,7 +4,7 @@ if( COMPILER_SUPPORTS_WARNINGS )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}")
endif() endif()
add_subdirectory( libeval ) add_subdirectory( libeval libeval_compiler )
include_directories( BEFORE ${INC_BEFORE} ) include_directories( BEFORE ${INC_BEFORE} )
include_directories( include_directories(
@ -409,6 +409,7 @@ set( COMMON_SRCS
project/project_local_settings.cpp project/project_local_settings.cpp
libeval/numeric_evaluator.cpp libeval/numeric_evaluator.cpp
libeval_compiler/libeval_compiler.cpp
) )
add_library( common STATIC add_library( common STATIC

View File

@ -28,7 +28,7 @@
#line 33 "grammar.lemon" #line 33 "grammar.lemon"
#include <assert.h> #include <assert.h>
#include "libeval_compiler.h" #include <libeval_compiler/libeval_compiler.h>
#line 33 "grammar.c" #line 33 "grammar.c"
/**************** End of %include directives **********************************/ /**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols /* These constants specify the various numeric values for terminal symbols

View File

@ -32,7 +32,7 @@
%include { %include {
#include <assert.h> #include <assert.h>
#include "libeval_compiler.h" #include <libeval_compiler/libeval_compiler.h>
} }
%syntax_error { %syntax_error {

View File

@ -24,7 +24,7 @@
#include <stdarg.h> #include <stdarg.h>
#endif #endif
#include "libeval_compiler.h" #include <libeval_compiler/libeval_compiler.h>
/* The (generated) lemon parser is written in C. /* The (generated) lemon parser is written in C.
* In order to keep its symbol from the global namespace include the parser code with * In order to keep its symbol from the global namespace include the parser code with
@ -46,14 +46,17 @@ namespace LIBEVAL
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
static void libeval_dbg( const char* fmt, ... ) static void libeval_dbg( int level, const char* fmt, ... )
{ {
#ifdef DEBUG #ifdef DEBUG
if(level <= 10) // fixme: tom's debugging.
{
va_list ap; va_list ap;
va_start( ap, fmt ); va_start( ap, fmt );
fprintf( stderr, "libeval: " ); fprintf( stderr, "libeval: " );
vfprintf( stderr, fmt, ap ); vfprintf( stderr, fmt, ap );
va_end( ap ); va_end( ap );
}
#endif #endif
} }
@ -146,8 +149,8 @@ bool TOKENIZER::MatchAhead( std::string match, std::function<bool( int )> stopCo
COMPILER::COMPILER() COMPILER::COMPILER()
{ {
m_errorStatus.pendingError = false;
m_localeDecimalSeparator = '.'; m_localeDecimalSeparator = '.';
m_parseError = false;
m_parseFinished = false; m_parseFinished = false;
m_unitResolver.reset( new UNIT_RESOLVER ); m_unitResolver.reset( new UNIT_RESOLVER );
m_parser = LIBEVAL::ParseAlloc( malloc ); m_parser = LIBEVAL::ParseAlloc( malloc );
@ -169,13 +172,15 @@ void COMPILER::Clear()
{ {
//free( current.token ); //free( current.token );
m_tokenizer.Clear(); m_tokenizer.Clear();
m_parseError = true;
} }
void COMPILER::parseError( const char* s ) void COMPILER::parseError( const char* s )
{ {
m_parseError = true; libeval_dbg(0, "PARSE ERROR: %s\n", s );
m_errorStatus.pendingError = true;
m_errorStatus.message = s;
} }
@ -189,13 +194,14 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode )
{ {
// Feed parser token after token until end of input. // Feed parser token after token until end of input.
newString( aString ); newString( aString );
m_errorStatus.pendingError = false;
m_tree = nullptr; m_tree = nullptr;
m_parseError = false;
m_parseFinished = false; m_parseFinished = false;
T_TOKEN tok; T_TOKEN tok;
libeval_dbg( "str: '%s' empty: %d\n", aString.c_str(), !!aString.empty() ); libeval_dbg(0, "str: '%s' empty: %d\n", aString.c_str(), !!aString.empty() );
if( aString.empty() ) if( aString.empty() )
{ {
@ -206,14 +212,15 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode )
do do
{ {
tok = getToken(); tok = getToken();
libeval_dbg( "parse: tok %d\n", tok.token ); libeval_dbg(10, "parse: tok %d\n", tok.token );
Parse( m_parser, tok.token, tok.value, this ); Parse( m_parser, tok.token, tok.value, this );
//printf('error')
if( m_parseError ) if( m_errorStatus.pendingError )
{ {
//printf( "PARSE ERR\n" ); m_errorStatus.stage = ERROR_STATUS::CST_PARSE;
m_parseErrorToken = ""; m_errorStatus.failingPosition = m_tokenizer.GetPos();
m_parseErrorPos = m_tokenizer.GetPos(); m_errorStatus.failingObject = tok.value.value.str;
m_errorStatus.message = "Parse error";
return false; return false;
} }
@ -282,7 +289,7 @@ int COMPILER::resolveUnits()
{ {
if( m_tokenizer.MatchAhead( unitName, []( int c ) -> bool { return !isalnum( c ); } ) ) if( m_tokenizer.MatchAhead( unitName, []( int c ) -> bool { return !isalnum( c ); } ) )
{ {
libeval_dbg( "Match unit '%s'\n", unitName.c_str() ); libeval_dbg(10, "Match unit '%s'\n", unitName.c_str() );
m_tokenizer.NextChar( unitName.length() ); m_tokenizer.NextChar( unitName.length() );
return unitId; return unitId;
} }
@ -356,7 +363,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
break; break;
} }
libeval_dbg( "LEX ch '%c' pos %d\n", ch, m_tokenizer.GetPos() ); libeval_dbg(10, "LEX ch '%c' pos %d\n", ch, m_tokenizer.GetPos() );
if( ch == 0 ) if( ch == 0 )
{ {
@ -466,7 +473,10 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
retval.token = G_STRUCT_REF; retval.token = G_STRUCT_REF;
break; break;
default: default:
m_parseError = true; m_errorStatus.stage = ERROR_STATUS::CST_PARSE;
m_errorStatus.failingPosition = m_tokenizer.GetPos();
m_errorStatus.failingObject = ch;
m_errorStatus.message = "Syntax error";
break; /* invalid character */ break; /* invalid character */
} }
@ -538,6 +548,12 @@ void dumpNode( std::string& buf, TREE_NODE* tok, int depth = 0 )
} }
} }
ERROR_STATUS COMPILER::GetErrorStatus()
{
ERROR_STATUS dummy;
return dummy;
}
void COMPILER::setRoot( TREE_NODE root ) void COMPILER::setRoot( TREE_NODE root )
{ {
m_tree = copyNode( root ); m_tree = copyNode( root );
@ -576,7 +592,7 @@ bool COMPILER::generateUCode( UCODE* aCode )
assert( node->leaf[0]->op == TR_IDENTIFIER ); assert( node->leaf[0]->op == TR_IDENTIFIER );
assert( node->leaf[1]->op == TR_IDENTIFIER ); assert( node->leaf[1]->op == TR_IDENTIFIER );
auto vref = aCode->createVarRef( node->leaf[0]->value.str, node->leaf[1]->value.str ); auto vref = aCode->createVarRef( this, node->leaf[0]->value.str, node->leaf[1]->value.str );
aCode->AddOp( TR_UOP_PUSH_VAR, vref ); aCode->AddOp( TR_UOP_PUSH_VAR, vref );
break; break;
} }
@ -732,4 +748,20 @@ VALUE* UCODE::Run()
return ctx.Pop(); return ctx.Pop();
} }
void UCODE::RuntimeError( const std::string aErrorMsg )
{
}
std::string ERROR_STATUS::Format() const
{
if( !pendingError )
return "";
char str[1024];
sprintf(str,"%s (pos: %d, near: '%s')", message.c_str(), failingPosition, failingObject.c_str() );
return str;
}
} // namespace LIBEVAL } // namespace LIBEVAL

View File

@ -52,6 +52,8 @@
namespace LIBEVAL namespace LIBEVAL
{ {
class COMPILER;
struct ERROR_STATUS struct ERROR_STATUS
{ {
bool pendingError; bool pendingError;
@ -62,9 +64,12 @@ struct ERROR_STATUS
CST_RUNTIME CST_RUNTIME
}; };
STAGE stage;
std::string message; std::string message;
std::string failingObject; std::string failingObject;
int failingPosition; int failingPosition;
std::string Format() const;
}; };
@ -230,6 +235,15 @@ private:
std::string m_valueStr; std::string m_valueStr;
}; };
class UCODE;
class VAR_REF
{
public:
virtual VAR_TYPE_T GetType( UCODE* aUcode ) = 0;
virtual VALUE GetValue( UCODE* aUcode ) = 0;
};
class UCODE class UCODE
{ {
public: public:
@ -289,14 +303,6 @@ public:
void *m_arg; void *m_arg;
}; };
class VAR_REF
{
public:
virtual VAR_TYPE_T GetType( const UCODE* aUcode ) const = 0;
virtual VALUE GetValue( const UCODE* aUcode ) const = 0;
};
void AddOp( int op, double value ) void AddOp( int op, double value )
{ {
auto uop = new UOP( op, new VALUE( value ) ); auto uop = new UOP( op, new VALUE( value ) );
@ -317,10 +323,11 @@ public:
VALUE* Run(); VALUE* Run();
std::string Dump() const; std::string Dump() const;
void RuntimeError( const std::string aErrorMsg );
virtual VAR_REF* createVarRef( const std::string& var, const std::string& field ) virtual VAR_REF* createVarRef( COMPILER* aCompiler, const std::string& var, const std::string& field )
{ {
return NULL; return nullptr;
}; };
private: private:
@ -392,28 +399,15 @@ public:
/* Check if previous invokation of process() was successful */ /* Check if previous invokation of process() was successful */
inline bool IsValid() const inline bool IsValid() const
{ {
return !m_parseError; return !m_errorStatus.pendingError;
}
const std::string GetParseErrorToken() const
{
return m_parseErrorToken;
}
const std::string GetParseErrorMessage() const
{
return m_parseErrorMessage;
}
int GetParseErrorPosition() const
{
return m_parseErrorPos;
} }
void setRoot( LIBEVAL::TREE_NODE root ); void setRoot( LIBEVAL::TREE_NODE root );
bool Compile( const std::string& aString, UCODE* aCode ); bool Compile( const std::string& aString, UCODE* aCode );
std::string DumpTree(); std::string DumpTree();
void ReportError( const std::string aErrorMsg );
ERROR_STATUS GetErrorStatus();
protected: protected:
enum LEXER_STATE enum LEXER_STATE
@ -461,6 +455,7 @@ protected:
int m_parseErrorPos; int m_parseErrorPos;
std::unique_ptr<UNIT_RESOLVER> m_unitResolver; std::unique_ptr<UNIT_RESOLVER> m_unitResolver;
ERROR_STATUS m_errorStatus;
TREE_NODE* m_tree; TREE_NODE* m_tree;
}; };