diff --git a/common/libeval_compiler/grammar.lemon b/common/libeval_compiler/grammar.lemon index 9d6b3190ab..7e1d184d84 100644 --- a/common/libeval_compiler/grammar.lemon +++ b/common/libeval_compiler/grammar.lemon @@ -24,6 +24,7 @@ %type nt {LIBEVAL::TREE_NODE*} %nonassoc G_IDENTIFIER G_ASSIGN G_SEMCOL. +%left G_COMMA. %left G_BOOL_AND. %left G_BOOL_OR. %left G_BOOL_XOR. @@ -78,6 +79,13 @@ nt(A) ::= G_IDENTIFIER(B). A = newNode( pEval, TR_IDENTIFIER, B.value ); } +nt(A) ::= nt(B) G_COMMA nt(C). +{ + A = newNode( pEval, TR_ARG_LIST ); + A->leaf[0] = B; + A->leaf[1] = C; +} + nt(A) ::= nt(B) G_LESS_THAN nt(C). { A = newNode( pEval, TR_OP_LESS ); diff --git a/common/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp index 1e1d6b2595..d3ad994d0a 100644 --- a/common/libeval_compiler/libeval_compiler.cpp +++ b/common/libeval_compiler/libeval_compiler.cpp @@ -21,6 +21,7 @@ #include <memory> #include <set> #include <vector> +#include <algorithm> #ifdef DEBUG #include <cstdarg> @@ -518,6 +519,8 @@ bool COMPILER::lexDefault( T_TOKEN& aToken ) case ')': retval.token = G_PARENR; break; case ';': retval.token = G_SEMCOL; break; case '.': retval.token = G_STRUCT_REF; break; + case ',': retval.token = G_COMMA; break; + default: reportError( CST_PARSE, wxString::Format( _( "Unrecognized character '%c'" ), (char) ch ) ); @@ -569,6 +572,17 @@ void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 ) break; + case TR_ARG_LIST: + buf += "ARG_LIST: "; + buf += formatNode( tok ); + + if( tok->leaf[0] ) + dumpNode( buf, tok->leaf[0], depth + 1 ); + if( tok->leaf[1] ) + dumpNode( buf, tok->leaf[1], depth + 1 ); + + break; + case TR_STRING: buf += "STRING: "; buf += formatNode( tok ); @@ -698,6 +712,44 @@ static void prepareTree( LIBEVAL::TREE_NODE *node ) prepareTree( node->leaf[1] ); } +static std::vector<TREE_NODE*> squashParamList( TREE_NODE* root ) +{ + std::vector<TREE_NODE*> args; + + if( !root ) + { + return args; + } + + if( root->op != TR_ARG_LIST && root->op != TR_NULL ) + { + args.push_back( root ); + } + else + { + TREE_NODE *n = root; + do + { + if( n->leaf[1] ) + args.push_back(n->leaf[1]); + + n = n->leaf[0]; + } while ( n && n->op == TR_ARG_LIST ); + + if( n ) + { + args.push_back(n); + } + } + + std::reverse( args.begin(), args.end() ); + + for(int i = 0; i < args.size(); i++ ) + libeval_dbg(10, "squash arg%d: %s\n", i, (const char*) *args[i]->value.str ); + + return args; +} + bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) { @@ -800,6 +852,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) wxString functionName = *node->leaf[1]->leaf[0]->value.str; auto func = aCode->CreateFuncCall( functionName ); + std::vector<TREE_NODE*> params = squashParamList( node->leaf[1]->leaf[1] ); libeval_dbg( 10, "emit func call: %s\n", functionName ); @@ -812,22 +865,18 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) if( func ) { // Preflight the function call - auto argsLeaf = node->leaf[1]->leaf[1]; - wxString paramStr; - if( argsLeaf->op != TR_NULL ) // function has an argument + for( auto pnode : params ) { - paramStr = *node->leaf[1]->leaf[1]->value.str; VALUE* param = aPreflightContext->AllocValue(); - - param->Set( paramStr ); + param->Set( *pnode->value.str ); aPreflightContext->Push( param ); } aPreflightContext->SetErrorCallback( [&]( const wxString& aMessage, int aOffset ) { - size_t loc = node->leaf[1]->leaf[1]->srcPos- paramStr.Length(); + size_t loc = node->leaf[1]->leaf[1]->srcPos; reportError( CST_CODEGEN, aMessage, (int) loc - 1 ); } ); @@ -851,7 +900,10 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) // a TR_OP_FUNC_CALL and its function parameter stack.pop_back(); stack.push_back( node->leaf[1] ); - stack.push_back( node->leaf[1]->leaf[1] ); + for( auto pnode : params ) + { + stack.push_back( pnode ); + } node->leaf[1]->SetUop( TR_OP_METHOD_CALL, func, std::move( vref ) ); node->isTerminal = false; diff --git a/include/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h index 0ce7f542ea..8471db754b 100644 --- a/include/libeval_compiler/libeval_compiler.h +++ b/include/libeval_compiler/libeval_compiler.h @@ -95,7 +95,8 @@ enum TOKEN_TYPE_T TR_STRUCT_REF = 4, TR_STRING = 5, TR_UNIT = 6, - TR_NULL = 7 + TR_ARG_LIST = 7, + TR_NULL = 8 }; class UOP;