From a5a06e3c89c43a23932994ae2bddf73495376cb8 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Mon, 10 Aug 2020 14:47:01 +0200 Subject: [PATCH] libeval_compiler: general clean up of the Lemon grammar + some smart pointers + killed all memory leaks. WIP! --- common/libeval_compiler/grammar.lemon | 150 +++++- common/libeval_compiler/libeval_compiler.cpp | 201 +++++--- common/marker_base.cpp | 1 + include/libeval_compiler/libeval_compiler.h | 126 +++--- thirdparty/lemon/lempar.c | 453 +++++++++++++++++-- 5 files changed, 739 insertions(+), 192 deletions(-) diff --git a/common/libeval_compiler/grammar.lemon b/common/libeval_compiler/grammar.lemon index ada6951462..99f107d94a 100644 --- a/common/libeval_compiler/grammar.lemon +++ b/common/libeval_compiler/grammar.lemon @@ -18,9 +18,11 @@ along with this program. If not, see . */ -%token_type { LIBEVAL::TREE_NODE } +%token_type { LIBEVAL::T_TOKEN } %extra_argument { LIBEVAL::COMPILER* pEval } +%type nt {LIBEVAL::TREE_NODE*} + %nonassoc G_IDENTIFIER G_ASSIGN G_SEMCOL. %left G_BOOL_AND. %left G_BOOL_OR. @@ -53,27 +55,131 @@ 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 ::= nt(A) G_ENDS. { pEval->setRoot(A); } -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.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(); } +nt(A) ::= G_VALUE(B). +{ + A = newNode( pEval, TR_NUMBER, B.value ); +} -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(); } +nt(A) ::= G_VALUE(B) G_UNIT(C). +{ + A = newNode( pEval, TR_NUMBER, B.value ); + A->leaf[0] = newNode( pEval, TR_UNIT, C.value ); +} -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.value.wstr = NULL; A.leaf[0] = copyNode(F); A.leaf[1] = copyNode(B); A.valid = true; A.srcPos = pEval->GetSourcePos(); } +nt(A) ::= G_STRING(B). +{ + A = newNode( pEval, TR_STRING, B.value ); +} + +nt(A) ::= G_IDENTIFIER(B). +{ + A = newNode( pEval, TR_IDENTIFIER, B.value ); +} + +nt(A) ::= nt(B) G_LESS_THAN nt(C). +{ + A = newNode( pEval, TR_OP_LESS ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_GREATER_THAN nt(C). +{ + A = newNode( pEval, TR_OP_GREATER ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_LESS_EQUAL_THAN nt(C). +{ + A = newNode( pEval, TR_OP_LESS_EQUAL ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_GREATER_EQUAL_THAN nt(C). +{ + A = newNode( pEval, TR_OP_GREATER_EQUAL ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_NOT_EQUAL nt(C). +{ + A = newNode( pEval, TR_OP_NOT_EQUAL ); + A->leaf[0] = B; + A->leaf[1] = C; +} + + +nt(A) ::= nt(B) G_BOOL_AND nt(C). +{ + A = newNode( pEval, TR_OP_BOOL_AND ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_BOOL_OR nt(C). +{ + A = newNode( pEval, TR_OP_BOOL_OR ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_PLUS nt(C). +{ + A = newNode( pEval, TR_OP_ADD ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_MINUS nt(C). +{ + A = newNode( pEval, TR_OP_SUB ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_MULT nt(C). +{ + A = newNode( pEval, TR_OP_MUL ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_DIVIDE nt(C). +{ + A = newNode( pEval, TR_OP_DIV ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_EQUAL nt(C). +{ + A = newNode( pEval, TR_OP_EQUAL ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= nt(B) G_STRUCT_REF nt(C). +{ + A = newNode( pEval, TR_STRUCT_REF ); + A->leaf[0] = B; + A->leaf[1] = C; +} + +nt(A) ::= G_PARENL nt(B) G_PARENR. +{ + A = newNode( pEval, B->op ); + A->leaf[0] = B->leaf[0]; + A->leaf[1] = B->leaf[1]; +} + +nt(A) ::= G_IDENTIFIER(F) G_PARENL nt(B) G_PARENR. +{ + A = newNode( pEval, TR_OP_FUNC_CALL ); + A->leaf[0] = newNode( pEval, TR_IDENTIFIER, F.value); + A->leaf[1] = B; +} diff --git a/common/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp index dbd69e2bc9..969817d1c3 100644 --- a/common/libeval_compiler/libeval_compiler.cpp +++ b/common/libeval_compiler/libeval_compiler.cpp @@ -50,44 +50,29 @@ namespace LIBEVAL #define libeval_dbg(level, fmt, ...) \ - wxLogTrace( "libeval_compiler", fmt, __VA_ARGS__ ) + wxLogTrace( "libeval_compiler", fmt, __VA_ARGS__ ); -TREE_NODE* copyNode( TREE_NODE& t ) + +TREE_NODE* newNode( LIBEVAL::COMPILER* compiler, int op, const T_TOKEN_VALUE& value ) { auto t2 = new TREE_NODE(); - t2->valid = t.valid; - - if( t.value.wstr ) - { - t2->value.wstr = new wxString(*t.value.wstr); - } - 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; -} - -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->value.str = value.str ? new wxString( *value.str ) : nullptr; + t2->value.num = value.num; + t2->value.idx = value.idx; t2->op = op; - t2->value.type = type; t2->leaf[0] = nullptr; t2->leaf[1] = nullptr; t2->isTerminal = false; - t2->srcPos = -1; + t2->srcPos = compiler->GetSourcePos(); t2->uop = nullptr; + + if(t2->value.str) + compiler->GcItem( t2->value.str ); + + compiler->GcItem( t2 ); + return t2; } @@ -125,19 +110,17 @@ wxString UOP::Format() const switch( m_op ) { case TR_UOP_PUSH_VAR: - str = wxString::Format( "PUSH VAR [%p]", m_arg ); + str = wxString::Format( "PUSH VAR [%p]", m_ref.get() ); break; case TR_UOP_PUSH_VALUE: { - VALUE* val = reinterpret_cast( m_arg ); - - if( !val ) + if( !m_value ) str = wxString::Format( "PUSH nullptr" ); - else if( val->GetType() == VT_NUMERIC ) - str = wxString::Format( "PUSH NUM [%.10f]", val->AsDouble() ); + else if( m_value->GetType() == VT_NUMERIC ) + str = wxString::Format( "PUSH NUM [%.10f]", m_value->AsDouble() ); else - str = wxString::Format( "PUSH STR [%ls]", GetChars( val->AsString() ) ); + str = wxString::Format( "PUSH STR [%ls]", GetChars( m_value->AsString() ) ); } break; @@ -161,7 +144,10 @@ wxString UOP::Format() const UCODE::~UCODE() { for ( auto op : m_ucode ) + { + printf("destroy uop %p\n", op ); delete op; + } } @@ -243,6 +229,15 @@ void COMPILER::Clear() } m_tree = nullptr; + + for( auto tok : m_gcItems ) + delete tok; + + for( auto tok: m_gcStrings ) + delete tok; + + m_gcItems.clear(); + m_gcStrings.clear(); } @@ -273,6 +268,8 @@ bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflig m_parseFinished = false; T_TOKEN tok; + tok.value.str = nullptr; + libeval_dbg(0, "str: '%s' empty: %d\n", aString.c_str(), !!aString.empty() ); if( aString.empty() ) @@ -286,8 +283,12 @@ bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflig m_sourcePos = m_tokenizer.GetPos(); tok = getToken(); + + if( tok.value.str ) + GcItem( tok.value.str ); + libeval_dbg(10, "parse: tok %d\n", tok.token ); - Parse( m_parser, tok.token, tok.value, this ); + Parse( m_parser, tok.token, tok, this ); if ( m_errorStatus.pendingError ) return false; @@ -295,7 +296,7 @@ bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflig if( m_parseFinished || tok.token == G_ENDS ) { // Reset parser by passing zero as token ID, value is ignored. - Parse( m_parser, 0, tok.value, this ); + Parse( m_parser, 0, tok, this ); break; } } while( tok.token ); @@ -313,9 +314,11 @@ void COMPILER::newString( const wxString& aString ) m_parseFinished = false; } -COMPILER::T_TOKEN COMPILER::getToken() +T_TOKEN COMPILER::getToken() { T_TOKEN rv; + rv.value.str = nullptr; + bool done = false; do @@ -336,13 +339,13 @@ COMPILER::T_TOKEN COMPILER::getToken() } -bool COMPILER::lexString( COMPILER::T_TOKEN& aToken ) +bool COMPILER::lexString( T_TOKEN& aToken ) { wxString str = m_tokenizer.GetChars( []( int c ) -> bool { return c != '\''; } ); //printf("STR LIT '%s'\n", (const char *)str.c_str() ); aToken.token = G_STRING; - aToken.value.value.wstr = new wxString( str ); + aToken.value.str = new wxString( str ); m_tokenizer.NextChar( str.length() + 1 ); m_lexerState = LS_DEFAULT; @@ -370,13 +373,14 @@ int COMPILER::resolveUnits() } -bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) +bool COMPILER::lexDefault( T_TOKEN& aToken ) { T_TOKEN retval; wxString current; int convertFrom; wxString msg; + retval.value.str = nullptr; retval.token = G_ENDS; //printf( "tokdone %d\n", !!m_tokenizer.Done() ); @@ -448,7 +452,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) // VALUE extractNumber(); retval.token = G_VALUE; - retval.value.value.wstr = new wxString( current ); + retval.value.str = new wxString( current ); } else if( ( convertFrom = resolveUnits() ) >= 0 ) { @@ -460,7 +464,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) // The factor is assigned to the terminal UNIT. The actual // conversion is done within a parser action. retval.token = G_UNIT; - retval.value.value.type = convertFrom; + retval.value.idx = convertFrom; } else if( ch == '\'' ) // string literal { @@ -477,7 +481,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) //printf("id '%s'\n", (const char *) current.c_str() ); //fflush( stdout ); retval.token = G_IDENTIFIER; - retval.value.value.wstr = new wxString( current ); + retval.value.str = new wxString( current ); m_tokenizer.NextChar( current.length() ); } else if( m_tokenizer.MatchAhead( "==", []( int c ) -> bool { return c != '='; } ) ) @@ -540,9 +544,9 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken ) } -const wxString formatNode( TREE_NODE* tok ) +const wxString formatNode( TREE_NODE* node ) { - return *(tok->value.wstr); + return *(node->value.str); } @@ -592,13 +596,13 @@ void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 ) case TR_OP_FUNC_CALL: buf += "CALL '"; - buf += *tok->leaf[0]->value.wstr; + buf += *tok->leaf[0]->value.str; buf += "': "; dumpNode( buf, tok->leaf[1], depth + 1 ); break; case TR_UNIT: - str.Printf( "UNIT: %d ", tok->value.type ); + str.Printf( "UNIT: %d ", tok->value.idx ); buf += str; break; } @@ -644,21 +648,67 @@ void COMPILER::reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, } -void COMPILER::setRoot( TREE_NODE root ) +void COMPILER::setRoot( TREE_NODE *root ) { - m_tree = copyNode( root ); + m_tree = root; } void COMPILER::freeTree( LIBEVAL::TREE_NODE *tree ) { + printf("->FreeTre %p\n", tree ); + if ( tree->leaf[0] ) freeTree( tree->leaf[0] ); if ( tree->leaf[1] ) freeTree( tree->leaf[1] ); - delete tree; + if( tree->uop ) + { + printf("Free uop %p\n", tree->uop ); + delete tree->uop; + } + +/* if( tree->value.str ) + delete tree->value.str; + + delete tree;*/ } +void TREE_NODE::SetUop( int aOp, double aValue ) +{ + if( uop ) + delete uop; + + std::unique_ptr val( new VALUE( aValue ) ); + uop = new UOP( aOp, std::move( val ) ); +} + +void TREE_NODE::SetUop( int aOp, const wxString& aValue ) +{ + if( uop ) + delete uop; + + std::unique_ptr val( new VALUE( aValue ) ); + uop = new UOP( aOp, std::move( val ) ); +} + +void TREE_NODE::SetUop( int aOp, std::unique_ptr aRef ) +{ + if( uop ) + delete uop; + + uop = new UOP( aOp, std::move( aRef ) ); +} + +void TREE_NODE::SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr aRef ) +{ + if( uop ) + delete uop; + + uop = new UOP( aOp, std::move( aFunc ), std::move( aRef ) ); +} + + bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) { std::vector stack; @@ -706,9 +756,9 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) { case TR_IDENTIFIER: { - wxString itemName = *node->leaf[0]->value.wstr; - wxString propName = *node->leaf[1]->value.wstr; - VAR_REF* vref = aCode->CreateVarRef( itemName, propName ); + wxString itemName = *node->leaf[0]->value.str; + wxString propName = *node->leaf[1]->value.str; + std::unique_ptr vref = aCode->CreateVarRef( itemName, propName ); if( !vref ) { @@ -724,14 +774,14 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) return false; } - node->uop = makeUop( TR_UOP_PUSH_VAR, vref ); + node->SetUop( TR_UOP_PUSH_VAR, std::move( vref ) ); node->isTerminal = true; break; } case TR_OP_FUNC_CALL: { - wxString itemName = *node->leaf[0]->value.wstr; - VAR_REF* vref = aCode->CreateVarRef( itemName, "" ); + wxString itemName = *node->leaf[0]->value.str; + std::unique_ptr vref = aCode->CreateVarRef( itemName, "" ); if( !vref ) { @@ -740,7 +790,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) return false; } - wxString functionName = *node->leaf[1]->leaf[0]->value.wstr; + wxString functionName = *node->leaf[1]->leaf[0]->value.str; auto func = aCode->CreateFuncCall( functionName ); libeval_dbg(10, "emit func call: %s\n", (const char*) functionName.c_str() ); @@ -775,8 +825,8 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) #endif /* SREF -> FUNC_CALL -> leaf0/1 */ - node->leaf[1]->leaf[0]->leaf[0] = nullptr; - node->leaf[1]->leaf[0]->leaf[1] = nullptr; + // node->leaf[1]->leaf[0]->leaf[0] = nullptr; + // node->leaf[1]->leaf[0]->leaf[1] = nullptr; #if 0 if( aPreflightContext->IsErrorPending() ) @@ -791,7 +841,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) visitedNodes.insert( node->leaf[0] ); visitedNodes.insert( node->leaf[1]->leaf[0] ); - node->uop = makeUop( TR_OP_METHOD_CALL, func, vref ); + node->SetUop( TR_OP_METHOD_CALL, func, std::move( vref ) ); node->isTerminal = false; } break; @@ -807,16 +857,16 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) if( son && son->op == TR_UNIT ) { //printf( "HandleUnit: %s unit %d\n", node->value.str, son->value.type ); - int units = son->value.type; - value = m_unitResolver->Convert( *node->value.wstr, units ); + int units = son->value.idx; + value = m_unitResolver->Convert( *node->value.str, units ); visitedNodes.insert( son ); } else { - value = wxAtof( *node->value.wstr ); + value = wxAtof( *node->value.str ); } - node->uop = makeUop( TR_UOP_PUSH_VALUE, value ); + node->SetUop( TR_UOP_PUSH_VALUE, value ); node->isTerminal = true; break; @@ -824,28 +874,28 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) case TR_STRING: { - node->uop = makeUop( TR_UOP_PUSH_VALUE, *node->value.wstr ); + node->SetUop( TR_UOP_PUSH_VALUE, *node->value.str ); node->isTerminal = true; break; } case TR_IDENTIFIER: { - VAR_REF* vref = aCode->CreateVarRef( *node->value.wstr, "" ); + std::unique_ptr vref = aCode->CreateVarRef( *node->value.str, "" ); if( !vref ) { - msg.Printf( _( "Unrecognized item '%s'" ), *node->value.wstr ); - reportError( CST_CODEGEN, msg, node->srcPos - (int) strlen( *node->value.wstr ) ); + msg.Printf( _( "Unrecognized item '%s'" ), *node->value.str ); + reportError( CST_CODEGEN, msg, node->srcPos - (int) strlen( *node->value.str ) ); return false; } - node->uop = makeUop( TR_UOP_PUSH_VALUE, vref ); + node->SetUop( TR_UOP_PUSH_VALUE, std::move( vref ) ); break; } default: - node->uop = makeUop( node->op ); + node->SetUop( node->op ); break; } @@ -865,7 +915,10 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) visitedNodes.insert( node ); if( node->uop ) + { aCode->AddOp( node->uop ); + node->uop = nullptr; + } stack.pop_back(); } @@ -883,18 +936,18 @@ void UOP::Exec( CONTEXT* ctx ) case TR_UOP_PUSH_VAR: { auto value = ctx->AllocValue(); - value->Set( reinterpret_cast( m_arg )->GetValue( ctx ) ); + value->Set( m_ref->GetValue( ctx ) ); ctx->Push( value ); } break; case TR_UOP_PUSH_VALUE: - ctx->Push( reinterpret_cast( m_arg ) ); + ctx->Push( m_value.get() ); return; case TR_OP_METHOD_CALL: //printf("CALL METHOD %s\n" ); - m_func( ctx, m_arg ); + m_func( ctx, m_ref.get() ); return; default: diff --git a/common/marker_base.cpp b/common/marker_base.cpp index 93e99a406a..165a0e04a5 100644 --- a/common/marker_base.cpp +++ b/common/marker_base.cpp @@ -85,6 +85,7 @@ MARKER_BASE::MARKER_BASE( int aScalingFactor, RC_ITEM* aItem, TYPEMARKER aType ) MARKER_BASE::~MARKER_BASE() { + printf("del rcitem %p\n", m_rcItem ); delete m_rcItem; } diff --git a/include/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h index a33fdf856d..a16653144c 100644 --- a/include/libeval_compiler/libeval_compiler.h +++ b/include/libeval_compiler/libeval_compiler.h @@ -92,18 +92,32 @@ enum TOKEN_TYPE_T TR_UNIT = 6 }; -#define LIBEVAL_MAX_LITERAL_LENGTH 1024 - class UOP; +class UCODE; +class CONTEXT; +class VAR_REF; -struct TREE_NODE +typedef std::function FUNC_CALL_REF; + +struct T_TOKEN_VALUE { - struct value_s - { - wxString *wstr; - //char str[LIBEVAL_MAX_LITERAL_LENGTH]; - int type; - } value; + wxString *str; + double num; + int idx; +}; + +constexpr T_TOKEN_VALUE defaultTokenValue = { nullptr, 0.0, 0 }; + +struct T_TOKEN +{ + int token; + T_TOKEN_VALUE value; +}; + +class TREE_NODE +{ +public: + T_TOKEN_VALUE value; int op; TREE_NODE* leaf[2]; @@ -111,10 +125,15 @@ struct TREE_NODE bool valid; bool isTerminal; int srcPos; + + void SetUop( int aOp, double aValue ); + void SetUop( int aOp, const wxString& aValue ); + void SetUop( int aOp, std::unique_ptr aRef = nullptr ); + void SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr aRef = nullptr ); }; -TREE_NODE* copyNode( TREE_NODE& t ); -TREE_NODE* newNode( int op, int type, const wxString& value ); + +TREE_NODE* newNode( LIBEVAL::COMPILER* compiler, int op, const T_TOKEN_VALUE& value = defaultTokenValue); class UNIT_RESOLVER { @@ -141,7 +160,7 @@ public: }; -class VALUE +class VALUE { public: VALUE(): @@ -214,14 +233,12 @@ private: wxString m_valueStr; }; - -class UCODE; -class CONTEXT; - - class VAR_REF { public: + VAR_REF() {}; + virtual ~VAR_REF() {}; + virtual VAR_TYPE_T GetType() = 0; virtual VALUE GetValue( CONTEXT* aCtx ) = 0; }; @@ -278,8 +295,6 @@ class UCODE public: virtual ~UCODE(); - typedef std::function FUNC_PTR; - void AddOp( UOP* uop ) { m_ucode.push_back(uop); @@ -288,17 +303,18 @@ public: VALUE* Run( CONTEXT* ctx ); wxString Dump() const; - virtual VAR_REF* CreateVarRef( const wxString& var, const wxString& field ) + virtual std::unique_ptr CreateVarRef( const wxString& var, const wxString& field ) { return nullptr; }; - virtual FUNC_PTR CreateFuncCall( const wxString& name ) + virtual FUNC_CALL_REF CreateFuncCall( const wxString& name ) { return nullptr; }; -private: +protected: + std::vector m_ucode; }; @@ -306,25 +322,39 @@ private: class UOP { public: - UOP( int op, void* arg ) : + UOP( int op, std::unique_ptr value ) : m_op( op ), - m_arg( arg ) + m_ref(nullptr), + m_value( std::move( value ) ) {}; - UOP( int op, UCODE::FUNC_PTR func, void *arg ) : + UOP( int op, std::unique_ptr vref ) : m_op( op ), - m_arg(arg), - m_func( std::move( func ) ) + m_ref( std::move( vref ) ), + m_value(nullptr) {}; + UOP( int op, FUNC_CALL_REF func, std::unique_ptr vref = nullptr ) : + m_op( op ), + m_func( std::move( func ) ), + m_ref( std::move( vref ) ), + m_value(nullptr) + {}; + + ~UOP() + { + } + void Exec( CONTEXT* ctx ); wxString Format() const; private: int m_op; - void* m_arg; - UCODE::FUNC_PTR m_func; + + FUNC_CALL_REF m_func; + std::unique_ptr m_ref; + std::unique_ptr m_value; }; class TOKENIZER @@ -393,7 +423,7 @@ public: int GetSourcePos() const { return m_sourcePos; } - void setRoot( LIBEVAL::TREE_NODE root ); + void setRoot( LIBEVAL::TREE_NODE *root ); void freeTree( LIBEVAL::TREE_NODE *tree ); bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext ); @@ -402,6 +432,9 @@ public: bool IsErrorPending() const { return m_errorStatus.pendingError; } const ERROR_STATUS& GetError() const { return m_errorStatus; } + void GcItem( TREE_NODE* aItem ) { m_gcItems.push_back( aItem ); } + void GcItem( wxString* aItem ) { m_gcStrings.push_back( aItem ); } + protected: enum LEXER_STATE { @@ -415,13 +448,6 @@ protected: void reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, int aPos = -1 ); - /* Token type used by the tokenizer */ - struct T_TOKEN - { - int token; - TREE_NODE value; - }; - /* Begin processing of a new input string */ void newString( const wxString& aString ); @@ -432,30 +458,6 @@ protected: int resolveUnits(); - UOP* makeUop( int op, double value ) - { - auto uop = new UOP( op, new VALUE( value ) ); - return uop; - } - - UOP* makeUop( int op, const wxString& value ) - { - UOP* uop = new UOP( op, new VALUE( value ) ); - return uop; - } - - UOP* makeUop( int op, VAR_REF* aRef = nullptr ) - { - UOP* uop = new UOP( op, aRef ); - return uop; - } - - UOP* makeUop( int op, UCODE::FUNC_PTR aFunc, void *arg = nullptr ) - { - UOP* uop = new UOP( op, std::move( aFunc ), arg ); - return uop; - } - protected: /* Token state for input string. */ void* m_parser; // the current lemon parser state machine @@ -469,6 +471,8 @@ protected: TREE_NODE* m_tree; ERROR_STATUS m_errorStatus; + std::vector m_gcItems; + std::vector m_gcStrings; std::function m_errorCallback; }; diff --git a/thirdparty/lemon/lempar.c b/thirdparty/lemon/lempar.c index c82e33298a..704ff501b6 100644 --- a/thirdparty/lemon/lempar.c +++ b/thirdparty/lemon/lempar.c @@ -25,13 +25,16 @@ #include #include /************ Begin %include sections from the grammar ************************/ -%% +#line 37 "grammar.lemon" + +#include +#include +#line 33 "grammar.c" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols ** in a format understandable to "makeheaders". This section is blank unless ** "lemon" is run with the "-m" command-line option. ***************** Begin makeheaders token definitions *************************/ -%% /**************** End makeheaders token definitions ***************************/ /* The next sections is a series of control #defines. @@ -89,7 +92,39 @@ # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ -%% +#define YYCODETYPE unsigned char +#define YYNOCODE 29 +#define YYACTIONTYPE unsigned char +#define ParseTOKENTYPE LIBEVAL::T_TOKEN +typedef union { + int yyinit; + ParseTOKENTYPE yy0; + LIBEVAL::TREE_NODE* yy31; +} YYMINORTYPE; +#ifndef YYSTACKDEPTH +#define YYSTACKDEPTH 100 +#endif +#define ParseARG_SDECL LIBEVAL::COMPILER* pEval ; +#define ParseARG_PDECL , LIBEVAL::COMPILER* pEval +#define ParseARG_PARAM ,pEval +#define ParseARG_FETCH LIBEVAL::COMPILER* pEval =yypParser->pEval ; +#define ParseARG_STORE yypParser->pEval =pEval ; +#define ParseCTX_SDECL +#define ParseCTX_PDECL +#define ParseCTX_PARAM +#define ParseCTX_FETCH +#define ParseCTX_STORE +#define YYNSTATE 35 +#define YYNRULE 24 +#define YYNTOKEN 25 +#define YY_MAX_SHIFT 34 +#define YY_MIN_SHIFTREDUCE 43 +#define YY_MAX_SHIFTREDUCE 66 +#define YY_ERROR_ACTION 67 +#define YY_ACCEPT_ACTION 68 +#define YY_NO_ACTION 69 +#define YY_MIN_REDUCE 70 +#define YY_MAX_REDUCE 93 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -156,7 +191,61 @@ ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -%% +#define YY_ACTTAB_COUNT (135) +static const YYACTIONTYPE yy_action[] = { + /* 0 */ 19, 68, 1, 1, 10, 9, 17, 16, 14, 13, + /* 10 */ 12, 4, 11, 87, 8, 7, 5, 6, 3, 5, + /* 20 */ 6, 3, 10, 9, 61, 16, 14, 13, 12, 4, + /* 30 */ 11, 22, 8, 7, 5, 6, 3, 31, 32, 28, + /* 40 */ 10, 9, 62, 16, 14, 13, 12, 4, 11, 29, + /* 50 */ 8, 7, 5, 6, 3, 19, 43, 9, 92, 16, + /* 60 */ 14, 13, 12, 4, 11, 23, 8, 7, 5, 6, + /* 70 */ 3, 67, 67, 67, 67, 67, 67, 67, 8, 7, + /* 80 */ 5, 6, 3, 16, 14, 13, 12, 4, 11, 33, + /* 90 */ 8, 7, 5, 6, 3, 90, 33, 20, 24, 25, + /* 100 */ 26, 3, 27, 69, 18, 21, 45, 15, 66, 34, + /* 110 */ 46, 2, 33, 69, 69, 66, 34, 46, 2, 69, + /* 120 */ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + /* 130 */ 69, 69, 34, 46, 2, +}; +static const YYCODETYPE yy_lookahead[] = { + /* 0 */ 25, 26, 27, 28, 4, 5, 25, 7, 8, 9, + /* 10 */ 10, 11, 12, 25, 14, 15, 16, 17, 18, 16, + /* 20 */ 17, 18, 4, 5, 24, 7, 8, 9, 10, 11, + /* 30 */ 12, 25, 14, 15, 16, 17, 18, 25, 25, 25, + /* 40 */ 4, 5, 24, 7, 8, 9, 10, 11, 12, 25, + /* 50 */ 14, 15, 16, 17, 18, 25, 20, 5, 28, 7, + /* 60 */ 8, 9, 10, 11, 12, 25, 14, 15, 16, 17, + /* 70 */ 18, 7, 8, 9, 10, 11, 12, 18, 14, 15, + /* 80 */ 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, + /* 90 */ 14, 15, 16, 17, 18, 0, 1, 25, 25, 25, + /* 100 */ 25, 18, 25, 29, 25, 25, 19, 23, 20, 21, + /* 110 */ 22, 23, 1, 29, 29, 20, 21, 22, 23, 29, + /* 120 */ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + /* 130 */ 29, 29, 21, 22, 23, 29, 29, 29, +}; +#define YY_SHIFT_COUNT (34) +#define YY_SHIFT_MIN (0) +#define YY_SHIFT_MAX (111) +static const unsigned char yy_shift_ofst[] = { + /* 0 */ 88, 95, 111, 111, 111, 111, 111, 111, 111, 111, + /* 10 */ 111, 111, 111, 111, 111, 111, 111, 0, 18, 36, + /* 20 */ 52, 64, 64, 76, 64, 64, 64, 64, 3, 3, + /* 30 */ 59, 83, 83, 84, 87, +}; +#define YY_REDUCE_COUNT (16) +#define YY_REDUCE_MIN (-25) +#define YY_REDUCE_MAX (80) +static const signed char yy_reduce_ofst[] = { + /* 0 */ -25, 30, -19, -12, 6, 12, 13, 14, 24, 40, + /* 10 */ 72, 73, 74, 75, 77, 79, 80, +}; +static const YYACTIONTYPE yy_default[] = { + /* 0 */ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + /* 10 */ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + /* 20 */ 80, 75, 86, 81, 79, 78, 77, 76, 83, 82, + /* 30 */ 87, 85, 84, 74, 71, +}; /********** End of lemon-generated parsing tables *****************************/ /* The next table maps tokens (terminal symbols) into fallback tokens. @@ -175,7 +264,6 @@ */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { -%% }; #endif /* YYFALLBACK */ @@ -263,7 +351,35 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { -%% + /* 0 */ "$", + /* 1 */ "G_IDENTIFIER", + /* 2 */ "G_ASSIGN", + /* 3 */ "G_SEMCOL", + /* 4 */ "G_BOOL_AND", + /* 5 */ "G_BOOL_OR", + /* 6 */ "G_BOOL_XOR", + /* 7 */ "G_LESS_THAN", + /* 8 */ "G_GREATER_THAN", + /* 9 */ "G_LESS_EQUAL_THAN", + /* 10 */ "G_GREATER_EQUAL_THAN", + /* 11 */ "G_EQUAL", + /* 12 */ "G_NOT_EQUAL", + /* 13 */ "G_BOOL_NOT", + /* 14 */ "G_PLUS", + /* 15 */ "G_MINUS", + /* 16 */ "G_DIVIDE", + /* 17 */ "G_MULT", + /* 18 */ "G_STRUCT_REF", + /* 19 */ "G_UNIT", + /* 20 */ "G_ENDS", + /* 21 */ "G_VALUE", + /* 22 */ "G_STRING", + /* 23 */ "G_PARENL", + /* 24 */ "G_PARENR", + /* 25 */ "nt", + /* 26 */ "main", + /* 27 */ "in", + /* 28 */ "stmt", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -271,7 +387,30 @@ static const char *const yyTokenName[] = { /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = { -%% + /* 0 */ "stmt ::= nt G_ENDS", + /* 1 */ "nt ::= G_VALUE", + /* 2 */ "nt ::= G_VALUE G_UNIT", + /* 3 */ "nt ::= G_STRING", + /* 4 */ "nt ::= G_IDENTIFIER", + /* 5 */ "nt ::= nt G_LESS_THAN nt", + /* 6 */ "nt ::= nt G_GREATER_THAN nt", + /* 7 */ "nt ::= nt G_LESS_EQUAL_THAN nt", + /* 8 */ "nt ::= nt G_GREATER_EQUAL_THAN nt", + /* 9 */ "nt ::= nt G_NOT_EQUAL nt", + /* 10 */ "nt ::= nt G_BOOL_AND nt", + /* 11 */ "nt ::= nt G_BOOL_OR nt", + /* 12 */ "nt ::= nt G_PLUS nt", + /* 13 */ "nt ::= nt G_MINUS nt", + /* 14 */ "nt ::= nt G_MULT nt", + /* 15 */ "nt ::= nt G_DIVIDE nt", + /* 16 */ "nt ::= nt G_EQUAL nt", + /* 17 */ "nt ::= nt G_STRUCT_REF nt", + /* 18 */ "nt ::= G_PARENL nt G_PARENR", + /* 19 */ "nt ::= G_IDENTIFIER G_PARENL nt G_PARENR", + /* 20 */ "main ::= in", + /* 21 */ "in ::= stmt", + /* 22 */ "in ::= in stmt", + /* 23 */ "stmt ::= G_ENDS", }; #endif /* NDEBUG */ @@ -397,7 +536,6 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ -%% /********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } @@ -521,18 +659,15 @@ static YYACTIONTYPE yy_find_shift_action( do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); - assert( i<=YY_ACTTAB_COUNT ); - assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); + /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - assert( i<(int)YY_NLOOKAHEAD ); - if( yy_lookahead[i]!=iLookAhead ){ + if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - assert( iLookAhead %s\n", @@ -547,8 +682,16 @@ static YYACTIONTYPE yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); - if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j0 + ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -562,7 +705,6 @@ static YYACTIONTYPE yy_find_shift_action( #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ - assert( i>=0 && isetRoot(yymsp[-1].minor.yy31); } +#line 972 "grammar.c" + break; + case 1: /* nt ::= G_VALUE */ +#line 61 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_NUMBER, yymsp[0].minor.yy0.value ); +} +#line 979 "grammar.c" + yymsp[0].minor.yy31 = yylhsminor.yy31; + break; + case 2: /* nt ::= G_VALUE G_UNIT */ +#line 66 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_NUMBER, yymsp[-1].minor.yy0.value ); + yylhsminor.yy31->leaf[0] = newNode( pEval, TR_UNIT, yymsp[0].minor.yy0.value ); +} +#line 988 "grammar.c" + yymsp[-1].minor.yy31 = yylhsminor.yy31; + break; + case 3: /* nt ::= G_STRING */ +#line 72 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_STRING, yymsp[0].minor.yy0.value ); +} +#line 996 "grammar.c" + yymsp[0].minor.yy31 = yylhsminor.yy31; + break; + case 4: /* nt ::= G_IDENTIFIER */ +#line 77 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_IDENTIFIER, yymsp[0].minor.yy0.value ); +} +#line 1004 "grammar.c" + yymsp[0].minor.yy31 = yylhsminor.yy31; + break; + case 5: /* nt ::= nt G_LESS_THAN nt */ +#line 82 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_LESS ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1014 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 6: /* nt ::= nt G_GREATER_THAN nt */ +#line 89 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_GREATER ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1024 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 7: /* nt ::= nt G_LESS_EQUAL_THAN nt */ +#line 96 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_LESS_EQUAL ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1034 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 8: /* nt ::= nt G_GREATER_EQUAL_THAN nt */ +#line 103 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_GREATER_EQUAL ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1044 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 9: /* nt ::= nt G_NOT_EQUAL nt */ +#line 110 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_NOT_EQUAL ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1054 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 10: /* nt ::= nt G_BOOL_AND nt */ +#line 118 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_BOOL_AND ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1064 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 11: /* nt ::= nt G_BOOL_OR nt */ +#line 125 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_BOOL_OR ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1074 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 12: /* nt ::= nt G_PLUS nt */ +#line 132 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_ADD ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1084 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 13: /* nt ::= nt G_MINUS nt */ +#line 139 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_SUB ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1094 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 14: /* nt ::= nt G_MULT nt */ +#line 146 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_MUL ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1104 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 15: /* nt ::= nt G_DIVIDE nt */ +#line 153 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_DIV ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1114 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 16: /* nt ::= nt G_EQUAL nt */ +#line 160 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_EQUAL ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1124 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 17: /* nt ::= nt G_STRUCT_REF nt */ +#line 167 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_STRUCT_REF ); + yylhsminor.yy31->leaf[0] = yymsp[-2].minor.yy31; + yylhsminor.yy31->leaf[1] = yymsp[0].minor.yy31; +} +#line 1134 "grammar.c" + yymsp[-2].minor.yy31 = yylhsminor.yy31; + break; + case 18: /* nt ::= G_PARENL nt G_PARENR */ +#line 174 "grammar.lemon" +{ + yymsp[-2].minor.yy31 = newNode( pEval, yymsp[-1].minor.yy31->op ); + yymsp[-2].minor.yy31->leaf[0] = yymsp[-1].minor.yy31->leaf[0]; + yymsp[-2].minor.yy31->leaf[1] = yymsp[-1].minor.yy31->leaf[1]; +} +#line 1144 "grammar.c" + break; + case 19: /* nt ::= G_IDENTIFIER G_PARENL nt G_PARENR */ +#line 181 "grammar.lemon" +{ + yylhsminor.yy31 = newNode( pEval, TR_OP_FUNC_CALL ); + yylhsminor.yy31->leaf[0] = newNode( pEval, TR_IDENTIFIER, yymsp[-3].minor.yy0.value); + yylhsminor.yy31->leaf[1] = yymsp[-1].minor.yy31; +} +#line 1153 "grammar.c" + yymsp[-3].minor.yy31 = yylhsminor.yy31; + break; + default: + /* (20) main ::= in */ yytestcase(yyruleno==20); + /* (21) in ::= stmt (OPTIMIZED OUT) */ assert(yyruleno!=21); + /* (22) in ::= in stmt */ yytestcase(yyruleno==22); + /* (23) stmt ::= G_ENDS */ yytestcase(yyruleno==23); + break; /********** End reduce actions ************************************************/ }; assert( yyrulenoparseError("Syntax error"); +#line 1223 "grammar.c" /************ End %syntax_error code ******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE @@ -866,7 +1245,10 @@ static void yy_accept( /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ -%% +#line 46 "grammar.lemon" + + pEval->parseOk(); +#line 1252 "grammar.c" /*********** End %parse_accept code *******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE @@ -1067,10 +1449,11 @@ void Parse( */ int ParseFallback(int iToken){ #ifdef YYFALLBACK - assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); - return yyFallback[iToken]; + if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ + return yyFallback[iToken]; + } #else (void)iToken; - return 0; #endif + return 0; }