From aaa91655aadfa3604fc1d9378f147765cc50dc07 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Sun, 14 Jun 2020 01:19:22 +0200 Subject: [PATCH] libeval_compiler: integrated in common/ --- common/CMakeLists.txt | 3 +- {qa => common}/libeval_compiler/grammar.c | 2 +- {qa => common}/libeval_compiler/grammar.h | 0 {qa => common}/libeval_compiler/grammar.lemon | 2 +- .../libeval_compiler/libeval_compiler.cpp | 76 +++++++++++++------ .../libeval_compiler/libeval_compiler.h | 47 +++++------- 6 files changed, 79 insertions(+), 51 deletions(-) rename {qa => common}/libeval_compiler/grammar.c (99%) rename {qa => common}/libeval_compiler/grammar.h (100%) rename {qa => common}/libeval_compiler/grammar.lemon (98%) rename {qa => common}/libeval_compiler/libeval_compiler.cpp (90%) rename {qa => include}/libeval_compiler/libeval_compiler.h (94%) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 49b0d5b55f..c6d9c7beed 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -4,7 +4,7 @@ if( COMPILER_SUPPORTS_WARNINGS ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}") endif() -add_subdirectory( libeval ) +add_subdirectory( libeval libeval_compiler ) include_directories( BEFORE ${INC_BEFORE} ) include_directories( @@ -409,6 +409,7 @@ set( COMMON_SRCS project/project_local_settings.cpp libeval/numeric_evaluator.cpp + libeval_compiler/libeval_compiler.cpp ) add_library( common STATIC diff --git a/qa/libeval_compiler/grammar.c b/common/libeval_compiler/grammar.c similarity index 99% rename from qa/libeval_compiler/grammar.c rename to common/libeval_compiler/grammar.c index 7cb716b9ca..106fff6697 100644 --- a/qa/libeval_compiler/grammar.c +++ b/common/libeval_compiler/grammar.c @@ -28,7 +28,7 @@ #line 33 "grammar.lemon" #include -#include "libeval_compiler.h" +#include #line 33 "grammar.c" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols diff --git a/qa/libeval_compiler/grammar.h b/common/libeval_compiler/grammar.h similarity index 100% rename from qa/libeval_compiler/grammar.h rename to common/libeval_compiler/grammar.h diff --git a/qa/libeval_compiler/grammar.lemon b/common/libeval_compiler/grammar.lemon similarity index 98% rename from qa/libeval_compiler/grammar.lemon rename to common/libeval_compiler/grammar.lemon index 2747bc462b..7f2d0f0d6e 100644 --- a/qa/libeval_compiler/grammar.lemon +++ b/common/libeval_compiler/grammar.lemon @@ -32,7 +32,7 @@ %include { #include -#include "libeval_compiler.h" +#include } %syntax_error { diff --git a/qa/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp similarity index 90% rename from qa/libeval_compiler/libeval_compiler.cpp rename to common/libeval_compiler/libeval_compiler.cpp index ca8961d430..32ebc12b8b 100644 --- a/qa/libeval_compiler/libeval_compiler.cpp +++ b/common/libeval_compiler/libeval_compiler.cpp @@ -24,7 +24,7 @@ #include #endif -#include "libeval_compiler.h" +#include /* The (generated) lemon parser is written in C. * 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 #endif -static void libeval_dbg( const char* fmt, ... ) +static void libeval_dbg( int level, const char* fmt, ... ) { #ifdef DEBUG - va_list ap; - va_start( ap, fmt ); - fprintf( stderr, "libeval: " ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); + if(level <= 10) // fixme: tom's debugging. + { + va_list ap; + va_start( ap, fmt ); + fprintf( stderr, "libeval: " ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + } #endif } @@ -146,8 +149,8 @@ bool TOKENIZER::MatchAhead( std::string match, std::function stopCo COMPILER::COMPILER() { + m_errorStatus.pendingError = false; m_localeDecimalSeparator = '.'; - m_parseError = false; m_parseFinished = false; m_unitResolver.reset( new UNIT_RESOLVER ); m_parser = LIBEVAL::ParseAlloc( malloc ); @@ -169,13 +172,15 @@ void COMPILER::Clear() { //free( current.token ); m_tokenizer.Clear(); - m_parseError = true; + } 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. + newString( aString ); + m_errorStatus.pendingError = false; m_tree = nullptr; - m_parseError = false; m_parseFinished = false; 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() ) { @@ -206,14 +212,15 @@ bool COMPILER::Compile( const std::string& aString, UCODE* aCode ) do { 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 ); - //printf('error') - if( m_parseError ) + + if( m_errorStatus.pendingError ) { - //printf( "PARSE ERR\n" ); - m_parseErrorToken = ""; - m_parseErrorPos = m_tokenizer.GetPos(); + m_errorStatus.stage = ERROR_STATUS::CST_PARSE; + m_errorStatus.failingPosition = m_tokenizer.GetPos(); + m_errorStatus.failingObject = tok.value.value.str; + m_errorStatus.message = "Parse error"; return false; } @@ -282,7 +289,7 @@ int COMPILER::resolveUnits() { 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() ); return unitId; } @@ -356,7 +363,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) 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 ) { @@ -466,7 +473,10 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) retval.token = G_STRUCT_REF; break; 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 */ } @@ -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 ) { m_tree = copyNode( root ); @@ -576,7 +592,7 @@ bool COMPILER::generateUCode( UCODE* aCode ) assert( node->leaf[0]->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 ); break; } @@ -732,4 +748,20 @@ VALUE* UCODE::Run() 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 diff --git a/qa/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h similarity index 94% rename from qa/libeval_compiler/libeval_compiler.h rename to include/libeval_compiler/libeval_compiler.h index a7393e228d..02c028562d 100644 --- a/qa/libeval_compiler/libeval_compiler.h +++ b/include/libeval_compiler/libeval_compiler.h @@ -52,6 +52,8 @@ namespace LIBEVAL { +class COMPILER; + struct ERROR_STATUS { bool pendingError; @@ -62,9 +64,12 @@ struct ERROR_STATUS CST_RUNTIME }; + STAGE stage; std::string message; std::string failingObject; int failingPosition; + + std::string Format() const; }; @@ -230,6 +235,15 @@ private: 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 { public: @@ -289,14 +303,6 @@ public: 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 ) { auto uop = new UOP( op, new VALUE( value ) ); @@ -317,10 +323,11 @@ public: VALUE* Run(); 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: @@ -392,28 +399,15 @@ public: /* Check if previous invokation of process() was successful */ inline bool IsValid() const { - return !m_parseError; - } - - const std::string GetParseErrorToken() const - { - return m_parseErrorToken; - } - - const std::string GetParseErrorMessage() const - { - return m_parseErrorMessage; - } - - int GetParseErrorPosition() const - { - return m_parseErrorPos; + return !m_errorStatus.pendingError; } void setRoot( LIBEVAL::TREE_NODE root ); bool Compile( const std::string& aString, UCODE* aCode ); std::string DumpTree(); + void ReportError( const std::string aErrorMsg ); + ERROR_STATUS GetErrorStatus(); protected: enum LEXER_STATE @@ -461,6 +455,7 @@ protected: int m_parseErrorPos; std::unique_ptr m_unitResolver; + ERROR_STATUS m_errorStatus; TREE_NODE* m_tree; };