libeval_compiler: general clean up of the Lemon grammar + some smart pointers + killed all memory leaks. WIP!

This commit is contained in:
Tomasz Wlostowski 2020-08-10 14:47:01 +02:00
parent 29a01e5515
commit a5a06e3c89
5 changed files with 739 additions and 192 deletions

View File

@ -18,9 +18,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
%token_type { LIBEVAL::TREE_NODE } %token_type { LIBEVAL::T_TOKEN }
%extra_argument { LIBEVAL::COMPILER* pEval } %extra_argument { LIBEVAL::COMPILER* pEval }
%type nt {LIBEVAL::TREE_NODE*}
%nonassoc G_IDENTIFIER G_ASSIGN G_SEMCOL. %nonassoc G_IDENTIFIER G_ASSIGN G_SEMCOL.
%left G_BOOL_AND. %left G_BOOL_AND.
%left G_BOOL_OR. %left G_BOOL_OR.
@ -53,27 +55,131 @@ in ::= in stmt.
/* A statement can be empty, an expr or an expr followed by ';' */ /* A statement can be empty, an expr or an expr followed by ';' */
stmt ::= G_ENDS. stmt ::= G_ENDS.
stmt ::= expr(A) G_ENDS. { pEval->setRoot(A); } stmt ::= nt(A) G_ENDS. { pEval->setRoot(A); }
//stmt ::= expr G_SEMCOL. { pEval->setRoot(NULL); }
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(); } nt(A) ::= G_VALUE(B).
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(); } A = newNode( pEval, TR_NUMBER, B.value );
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(); }
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(); } nt(A) ::= G_STRING(B).
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(); } {
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;
}

View File

@ -50,44 +50,29 @@ namespace LIBEVAL
#define libeval_dbg(level, fmt, ...) \ #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(); 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->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->op = op;
t2->value.type = type;
t2->leaf[0] = nullptr; t2->leaf[0] = nullptr;
t2->leaf[1] = nullptr; t2->leaf[1] = nullptr;
t2->isTerminal = false; t2->isTerminal = false;
t2->srcPos = -1; t2->srcPos = compiler->GetSourcePos();
t2->uop = nullptr; t2->uop = nullptr;
if(t2->value.str)
compiler->GcItem( t2->value.str );
compiler->GcItem( t2 );
return t2; return t2;
} }
@ -125,19 +110,17 @@ wxString UOP::Format() const
switch( m_op ) switch( m_op )
{ {
case TR_UOP_PUSH_VAR: case TR_UOP_PUSH_VAR:
str = wxString::Format( "PUSH VAR [%p]", m_arg ); str = wxString::Format( "PUSH VAR [%p]", m_ref.get() );
break; break;
case TR_UOP_PUSH_VALUE: case TR_UOP_PUSH_VALUE:
{ {
VALUE* val = reinterpret_cast<VALUE*>( m_arg ); if( !m_value )
if( !val )
str = wxString::Format( "PUSH nullptr" ); str = wxString::Format( "PUSH nullptr" );
else if( val->GetType() == VT_NUMERIC ) else if( m_value->GetType() == VT_NUMERIC )
str = wxString::Format( "PUSH NUM [%.10f]", val->AsDouble() ); str = wxString::Format( "PUSH NUM [%.10f]", m_value->AsDouble() );
else else
str = wxString::Format( "PUSH STR [%ls]", GetChars( val->AsString() ) ); str = wxString::Format( "PUSH STR [%ls]", GetChars( m_value->AsString() ) );
} }
break; break;
@ -161,7 +144,10 @@ wxString UOP::Format() const
UCODE::~UCODE() UCODE::~UCODE()
{ {
for ( auto op : m_ucode ) for ( auto op : m_ucode )
{
printf("destroy uop %p\n", op );
delete op; delete op;
}
} }
@ -243,6 +229,15 @@ void COMPILER::Clear()
} }
m_tree = nullptr; 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; m_parseFinished = false;
T_TOKEN tok; T_TOKEN tok;
tok.value.str = nullptr;
libeval_dbg(0, "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() )
@ -286,8 +283,12 @@ bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflig
m_sourcePos = m_tokenizer.GetPos(); m_sourcePos = m_tokenizer.GetPos();
tok = getToken(); tok = getToken();
if( tok.value.str )
GcItem( tok.value.str );
libeval_dbg(10, "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, this );
if ( m_errorStatus.pendingError ) if ( m_errorStatus.pendingError )
return false; return false;
@ -295,7 +296,7 @@ bool COMPILER::Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflig
if( m_parseFinished || tok.token == G_ENDS ) if( m_parseFinished || tok.token == G_ENDS )
{ {
// Reset parser by passing zero as token ID, value is ignored. // 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; break;
} }
} while( tok.token ); } while( tok.token );
@ -313,9 +314,11 @@ void COMPILER::newString( const wxString& aString )
m_parseFinished = false; m_parseFinished = false;
} }
COMPILER::T_TOKEN COMPILER::getToken() T_TOKEN COMPILER::getToken()
{ {
T_TOKEN rv; T_TOKEN rv;
rv.value.str = nullptr;
bool done = false; bool done = false;
do 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 != '\''; } ); wxString str = m_tokenizer.GetChars( []( int c ) -> bool { return c != '\''; } );
//printf("STR LIT '%s'\n", (const char *)str.c_str() ); //printf("STR LIT '%s'\n", (const char *)str.c_str() );
aToken.token = G_STRING; aToken.token = G_STRING;
aToken.value.value.wstr = new wxString( str ); aToken.value.str = new wxString( str );
m_tokenizer.NextChar( str.length() + 1 ); m_tokenizer.NextChar( str.length() + 1 );
m_lexerState = LS_DEFAULT; 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; T_TOKEN retval;
wxString current; wxString current;
int convertFrom; int convertFrom;
wxString msg; wxString msg;
retval.value.str = nullptr;
retval.token = G_ENDS; retval.token = G_ENDS;
//printf( "tokdone %d\n", !!m_tokenizer.Done() ); //printf( "tokdone %d\n", !!m_tokenizer.Done() );
@ -448,7 +452,7 @@ bool COMPILER::lexDefault( COMPILER::T_TOKEN& aToken )
// VALUE // VALUE
extractNumber(); extractNumber();
retval.token = G_VALUE; retval.token = G_VALUE;
retval.value.value.wstr = new wxString( current ); retval.value.str = new wxString( current );
} }
else if( ( convertFrom = resolveUnits() ) >= 0 ) 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 // The factor is assigned to the terminal UNIT. The actual
// conversion is done within a parser action. // conversion is done within a parser action.
retval.token = G_UNIT; retval.token = G_UNIT;
retval.value.value.type = convertFrom; retval.value.idx = convertFrom;
} }
else if( ch == '\'' ) // string literal 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() ); //printf("id '%s'\n", (const char *) current.c_str() );
//fflush( stdout ); //fflush( stdout );
retval.token = G_IDENTIFIER; retval.token = G_IDENTIFIER;
retval.value.value.wstr = new wxString( current ); retval.value.str = new wxString( current );
m_tokenizer.NextChar( current.length() ); m_tokenizer.NextChar( current.length() );
} }
else if( m_tokenizer.MatchAhead( "==", []( int c ) -> bool { return c != '='; } ) ) 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: case TR_OP_FUNC_CALL:
buf += "CALL '"; buf += "CALL '";
buf += *tok->leaf[0]->value.wstr; buf += *tok->leaf[0]->value.str;
buf += "': "; buf += "': ";
dumpNode( buf, tok->leaf[1], depth + 1 ); dumpNode( buf, tok->leaf[1], depth + 1 );
break; break;
case TR_UNIT: case TR_UNIT:
str.Printf( "UNIT: %d ", tok->value.type ); str.Printf( "UNIT: %d ", tok->value.idx );
buf += str; buf += str;
break; 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 ) void COMPILER::freeTree( LIBEVAL::TREE_NODE *tree )
{ {
printf("->FreeTre %p\n", tree );
if ( tree->leaf[0] ) if ( tree->leaf[0] )
freeTree( tree->leaf[0] ); freeTree( tree->leaf[0] );
if ( tree->leaf[1] ) if ( tree->leaf[1] )
freeTree( 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<VALUE> 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<VALUE> val( new VALUE( aValue ) );
uop = new UOP( aOp, std::move( val ) );
}
void TREE_NODE::SetUop( int aOp, std::unique_ptr<VAR_REF> 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<VAR_REF> aRef )
{
if( uop )
delete uop;
uop = new UOP( aOp, std::move( aFunc ), std::move( aRef ) );
}
bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
{ {
std::vector<TREE_NODE*> stack; std::vector<TREE_NODE*> stack;
@ -706,9 +756,9 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
{ {
case TR_IDENTIFIER: case TR_IDENTIFIER:
{ {
wxString itemName = *node->leaf[0]->value.wstr; wxString itemName = *node->leaf[0]->value.str;
wxString propName = *node->leaf[1]->value.wstr; wxString propName = *node->leaf[1]->value.str;
VAR_REF* vref = aCode->CreateVarRef( itemName, propName ); std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, propName );
if( !vref ) if( !vref )
{ {
@ -724,14 +774,14 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
return false; return false;
} }
node->uop = makeUop( TR_UOP_PUSH_VAR, vref ); node->SetUop( TR_UOP_PUSH_VAR, std::move( vref ) );
node->isTerminal = true; node->isTerminal = true;
break; break;
} }
case TR_OP_FUNC_CALL: case TR_OP_FUNC_CALL:
{ {
wxString itemName = *node->leaf[0]->value.wstr; wxString itemName = *node->leaf[0]->value.str;
VAR_REF* vref = aCode->CreateVarRef( itemName, "" ); std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, "" );
if( !vref ) if( !vref )
{ {
@ -740,7 +790,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
return false; 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 ); auto func = aCode->CreateFuncCall( functionName );
libeval_dbg(10, "emit func call: %s\n", (const char*) functionName.c_str() ); 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 #endif
/* SREF -> FUNC_CALL -> leaf0/1 */ /* SREF -> FUNC_CALL -> leaf0/1 */
node->leaf[1]->leaf[0]->leaf[0] = nullptr; // node->leaf[1]->leaf[0]->leaf[0] = nullptr;
node->leaf[1]->leaf[0]->leaf[1] = nullptr; // node->leaf[1]->leaf[0]->leaf[1] = nullptr;
#if 0 #if 0
if( aPreflightContext->IsErrorPending() ) if( aPreflightContext->IsErrorPending() )
@ -791,7 +841,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
visitedNodes.insert( node->leaf[0] ); visitedNodes.insert( node->leaf[0] );
visitedNodes.insert( node->leaf[1]->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; node->isTerminal = false;
} }
break; break;
@ -807,16 +857,16 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
if( son && son->op == TR_UNIT ) if( son && son->op == TR_UNIT )
{ {
//printf( "HandleUnit: %s unit %d\n", node->value.str, son->value.type ); //printf( "HandleUnit: %s unit %d\n", node->value.str, son->value.type );
int units = son->value.type; int units = son->value.idx;
value = m_unitResolver->Convert( *node->value.wstr, units ); value = m_unitResolver->Convert( *node->value.str, units );
visitedNodes.insert( son ); visitedNodes.insert( son );
} }
else 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; node->isTerminal = true;
break; break;
@ -824,28 +874,28 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
case TR_STRING: 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; node->isTerminal = true;
break; break;
} }
case TR_IDENTIFIER: case TR_IDENTIFIER:
{ {
VAR_REF* vref = aCode->CreateVarRef( *node->value.wstr, "" ); std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( *node->value.str, "" );
if( !vref ) if( !vref )
{ {
msg.Printf( _( "Unrecognized item '%s'" ), *node->value.wstr ); msg.Printf( _( "Unrecognized item '%s'" ), *node->value.str );
reportError( CST_CODEGEN, msg, node->srcPos - (int) strlen( *node->value.wstr ) ); reportError( CST_CODEGEN, msg, node->srcPos - (int) strlen( *node->value.str ) );
return false; return false;
} }
node->uop = makeUop( TR_UOP_PUSH_VALUE, vref ); node->SetUop( TR_UOP_PUSH_VALUE, std::move( vref ) );
break; break;
} }
default: default:
node->uop = makeUop( node->op ); node->SetUop( node->op );
break; break;
} }
@ -865,7 +915,10 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
visitedNodes.insert( node ); visitedNodes.insert( node );
if( node->uop ) if( node->uop )
{
aCode->AddOp( node->uop ); aCode->AddOp( node->uop );
node->uop = nullptr;
}
stack.pop_back(); stack.pop_back();
} }
@ -883,18 +936,18 @@ void UOP::Exec( CONTEXT* ctx )
case TR_UOP_PUSH_VAR: case TR_UOP_PUSH_VAR:
{ {
auto value = ctx->AllocValue(); auto value = ctx->AllocValue();
value->Set( reinterpret_cast<VAR_REF*>( m_arg )->GetValue( ctx ) ); value->Set( m_ref->GetValue( ctx ) );
ctx->Push( value ); ctx->Push( value );
} }
break; break;
case TR_UOP_PUSH_VALUE: case TR_UOP_PUSH_VALUE:
ctx->Push( reinterpret_cast<VALUE*>( m_arg ) ); ctx->Push( m_value.get() );
return; return;
case TR_OP_METHOD_CALL: case TR_OP_METHOD_CALL:
//printf("CALL METHOD %s\n" ); //printf("CALL METHOD %s\n" );
m_func( ctx, m_arg ); m_func( ctx, m_ref.get() );
return; return;
default: default:

View File

@ -85,6 +85,7 @@ MARKER_BASE::MARKER_BASE( int aScalingFactor, RC_ITEM* aItem, TYPEMARKER aType )
MARKER_BASE::~MARKER_BASE() MARKER_BASE::~MARKER_BASE()
{ {
printf("del rcitem %p\n", m_rcItem );
delete m_rcItem; delete m_rcItem;
} }

View File

@ -92,18 +92,32 @@ enum TOKEN_TYPE_T
TR_UNIT = 6 TR_UNIT = 6
}; };
#define LIBEVAL_MAX_LITERAL_LENGTH 1024
class UOP; class UOP;
class UCODE;
class CONTEXT;
class VAR_REF;
struct TREE_NODE typedef std::function<void( CONTEXT*, void* )> FUNC_CALL_REF;
struct T_TOKEN_VALUE
{ {
struct value_s wxString *str;
{ double num;
wxString *wstr; int idx;
//char str[LIBEVAL_MAX_LITERAL_LENGTH]; };
int type;
} value; 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; int op;
TREE_NODE* leaf[2]; TREE_NODE* leaf[2];
@ -111,10 +125,15 @@ struct TREE_NODE
bool valid; bool valid;
bool isTerminal; bool isTerminal;
int srcPos; int srcPos;
void SetUop( int aOp, double aValue );
void SetUop( int aOp, const wxString& aValue );
void SetUop( int aOp, std::unique_ptr<VAR_REF> aRef = nullptr );
void SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr<VAR_REF> 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 class UNIT_RESOLVER
{ {
@ -214,14 +233,12 @@ private:
wxString m_valueStr; wxString m_valueStr;
}; };
class UCODE;
class CONTEXT;
class VAR_REF class VAR_REF
{ {
public: public:
VAR_REF() {};
virtual ~VAR_REF() {};
virtual VAR_TYPE_T GetType() = 0; virtual VAR_TYPE_T GetType() = 0;
virtual VALUE GetValue( CONTEXT* aCtx ) = 0; virtual VALUE GetValue( CONTEXT* aCtx ) = 0;
}; };
@ -278,8 +295,6 @@ class UCODE
public: public:
virtual ~UCODE(); virtual ~UCODE();
typedef std::function<void( CONTEXT*, void* )> FUNC_PTR;
void AddOp( UOP* uop ) void AddOp( UOP* uop )
{ {
m_ucode.push_back(uop); m_ucode.push_back(uop);
@ -288,17 +303,18 @@ public:
VALUE* Run( CONTEXT* ctx ); VALUE* Run( CONTEXT* ctx );
wxString Dump() const; wxString Dump() const;
virtual VAR_REF* CreateVarRef( const wxString& var, const wxString& field ) virtual std::unique_ptr<VAR_REF> CreateVarRef( const wxString& var, const wxString& field )
{ {
return nullptr; return nullptr;
}; };
virtual FUNC_PTR CreateFuncCall( const wxString& name ) virtual FUNC_CALL_REF CreateFuncCall( const wxString& name )
{ {
return nullptr; return nullptr;
}; };
private: protected:
std::vector<UOP*> m_ucode; std::vector<UOP*> m_ucode;
}; };
@ -306,25 +322,39 @@ private:
class UOP class UOP
{ {
public: public:
UOP( int op, void* arg ) : UOP( int op, std::unique_ptr<VALUE> value ) :
m_op( op ), 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<VAR_REF> vref ) :
m_op( op ), m_op( op ),
m_arg(arg), m_ref( std::move( vref ) ),
m_func( std::move( func ) ) m_value(nullptr)
{}; {};
UOP( int op, FUNC_CALL_REF func, std::unique_ptr<VAR_REF> vref = nullptr ) :
m_op( op ),
m_func( std::move( func ) ),
m_ref( std::move( vref ) ),
m_value(nullptr)
{};
~UOP()
{
}
void Exec( CONTEXT* ctx ); void Exec( CONTEXT* ctx );
wxString Format() const; wxString Format() const;
private: private:
int m_op; int m_op;
void* m_arg;
UCODE::FUNC_PTR m_func; FUNC_CALL_REF m_func;
std::unique_ptr<VAR_REF> m_ref;
std::unique_ptr<VALUE> m_value;
}; };
class TOKENIZER class TOKENIZER
@ -393,7 +423,7 @@ public:
int GetSourcePos() const { return m_sourcePos; } int GetSourcePos() const { return m_sourcePos; }
void setRoot( LIBEVAL::TREE_NODE root ); void setRoot( LIBEVAL::TREE_NODE *root );
void freeTree( LIBEVAL::TREE_NODE *tree ); void freeTree( LIBEVAL::TREE_NODE *tree );
bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext ); bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext );
@ -402,6 +432,9 @@ public:
bool IsErrorPending() const { return m_errorStatus.pendingError; } bool IsErrorPending() const { return m_errorStatus.pendingError; }
const ERROR_STATUS& GetError() const { return m_errorStatus; } 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: protected:
enum LEXER_STATE enum LEXER_STATE
{ {
@ -415,13 +448,6 @@ protected:
void reportError( COMPILATION_STAGE stage, 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
{
int token;
TREE_NODE value;
};
/* Begin processing of a new input string */ /* Begin processing of a new input string */
void newString( const wxString& aString ); void newString( const wxString& aString );
@ -432,30 +458,6 @@ protected:
int resolveUnits(); 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: protected:
/* Token state for input string. */ /* Token state for input string. */
void* m_parser; // the current lemon parser state machine void* m_parser; // the current lemon parser state machine
@ -469,6 +471,8 @@ protected:
TREE_NODE* m_tree; TREE_NODE* m_tree;
ERROR_STATUS m_errorStatus; ERROR_STATUS m_errorStatus;
std::vector<TREE_NODE*> m_gcItems;
std::vector<wxString*> m_gcStrings;
std::function<void(const ERROR_STATUS&)> m_errorCallback; std::function<void(const ERROR_STATUS&)> m_errorCallback;
}; };

View File

@ -25,13 +25,16 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
/************ Begin %include sections from the grammar ************************/ /************ Begin %include sections from the grammar ************************/
%% #line 37 "grammar.lemon"
#include <assert.h>
#include <libeval_compiler/libeval_compiler.h>
#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
** in a format understandable to "makeheaders". This section is blank unless ** in a format understandable to "makeheaders". This section is blank unless
** "lemon" is run with the "-m" command-line option. ** "lemon" is run with the "-m" command-line option.
***************** Begin makeheaders token definitions *************************/ ***************** Begin makeheaders token definitions *************************/
%%
/**************** End makeheaders token definitions ***************************/ /**************** End makeheaders token definitions ***************************/
/* The next sections is a series of control #defines. /* The next sections is a series of control #defines.
@ -89,7 +92,39 @@
# define INTERFACE 1 # define INTERFACE 1
#endif #endif
/************* Begin control #defines *****************************************/ /************* 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 *******************************************/ /************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@ -156,7 +191,61 @@
** yy_default[] Default action for each state. ** yy_default[] Default action for each state.
** **
*********** Begin parsing tables **********************************************/ *********** 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 *****************************/ /********** End of lemon-generated parsing tables *****************************/
/* The next table maps tokens (terminal symbols) into fallback tokens. /* The next table maps tokens (terminal symbols) into fallback tokens.
@ -175,7 +264,6 @@
*/ */
#ifdef YYFALLBACK #ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = { static const YYCODETYPE yyFallback[] = {
%%
}; };
#endif /* YYFALLBACK */ #endif /* YYFALLBACK */
@ -263,7 +351,35 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
/* For tracing shifts, the names of all terminals and nonterminals /* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */ ** are required. The following table supplies these names */
static const char *const yyTokenName[] = { 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) */ #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. /* For tracing reduce actions, the names of all rules are required.
*/ */
static const char *const yyRuleName[] = { 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 */ #endif /* NDEBUG */
@ -397,7 +536,6 @@ static void yy_destructor(
** inside the C code. ** inside the C code.
*/ */
/********* Begin destructor definitions ***************************************/ /********* Begin destructor definitions ***************************************/
%%
/********* End destructor definitions *****************************************/ /********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */ default: break; /* If no destructor action specified: do nothing */
} }
@ -521,18 +659,15 @@ static YYACTIONTYPE yy_find_shift_action(
do{ do{
i = yy_shift_ofst[stateno]; i = yy_shift_ofst[stateno];
assert( i>=0 ); 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!=YYNOCODE );
assert( iLookAhead < YYNTOKEN ); assert( iLookAhead < YYNTOKEN );
i += iLookAhead; i += iLookAhead;
assert( i<(int)YY_NLOOKAHEAD ); if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
if( yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK #ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */ YYCODETYPE iFallback; /* Fallback token */
assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) ); if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
iFallback = yyFallback[iLookAhead]; && (iFallback = yyFallback[iLookAhead])!=0 ){
if( iFallback!=0 ){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
@ -547,8 +682,16 @@ static YYACTIONTYPE yy_find_shift_action(
#ifdef YYWILDCARD #ifdef YYWILDCARD
{ {
int j = i - iLookAhead + YYWILDCARD; int j = i - iLookAhead + YYWILDCARD;
assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); if(
if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ #if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
@ -562,7 +705,6 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */ #endif /* YYWILDCARD */
return yy_default[stateno]; return yy_default[stateno];
}else{ }else{
assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
return yy_action[i]; return yy_action[i];
} }
}while(1); }while(1);
@ -613,7 +755,6 @@ static void yyStackOverflow(yyParser *yypParser){
/* Here code is inserted which will execute if the parser /* Here code is inserted which will execute if the parser
** stack every overflows */ ** stack every overflows */
/******** Begin %stack_overflow code ******************************************/ /******** Begin %stack_overflow code ******************************************/
%%
/******** End %stack_overflow code ********************************************/ /******** End %stack_overflow code ********************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument var */ ParseARG_STORE /* Suppress warning about unused %extra_argument var */
ParseCTX_STORE ParseCTX_STORE
@ -685,13 +826,59 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */ ** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = { static const YYCODETYPE yyRuleInfoLhs[] = {
%% 28, /* (0) stmt ::= nt G_ENDS */
25, /* (1) nt ::= G_VALUE */
25, /* (2) nt ::= G_VALUE G_UNIT */
25, /* (3) nt ::= G_STRING */
25, /* (4) nt ::= G_IDENTIFIER */
25, /* (5) nt ::= nt G_LESS_THAN nt */
25, /* (6) nt ::= nt G_GREATER_THAN nt */
25, /* (7) nt ::= nt G_LESS_EQUAL_THAN nt */
25, /* (8) nt ::= nt G_GREATER_EQUAL_THAN nt */
25, /* (9) nt ::= nt G_NOT_EQUAL nt */
25, /* (10) nt ::= nt G_BOOL_AND nt */
25, /* (11) nt ::= nt G_BOOL_OR nt */
25, /* (12) nt ::= nt G_PLUS nt */
25, /* (13) nt ::= nt G_MINUS nt */
25, /* (14) nt ::= nt G_MULT nt */
25, /* (15) nt ::= nt G_DIVIDE nt */
25, /* (16) nt ::= nt G_EQUAL nt */
25, /* (17) nt ::= nt G_STRUCT_REF nt */
25, /* (18) nt ::= G_PARENL nt G_PARENR */
25, /* (19) nt ::= G_IDENTIFIER G_PARENL nt G_PARENR */
26, /* (20) main ::= in */
27, /* (21) in ::= stmt */
27, /* (22) in ::= in stmt */
28, /* (23) stmt ::= G_ENDS */
}; };
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */ ** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = { static const signed char yyRuleInfoNRhs[] = {
%% -2, /* (0) stmt ::= nt G_ENDS */
-1, /* (1) nt ::= G_VALUE */
-2, /* (2) nt ::= G_VALUE G_UNIT */
-1, /* (3) nt ::= G_STRING */
-1, /* (4) nt ::= G_IDENTIFIER */
-3, /* (5) nt ::= nt G_LESS_THAN nt */
-3, /* (6) nt ::= nt G_GREATER_THAN nt */
-3, /* (7) nt ::= nt G_LESS_EQUAL_THAN nt */
-3, /* (8) nt ::= nt G_GREATER_EQUAL_THAN nt */
-3, /* (9) nt ::= nt G_NOT_EQUAL nt */
-3, /* (10) nt ::= nt G_BOOL_AND nt */
-3, /* (11) nt ::= nt G_BOOL_OR nt */
-3, /* (12) nt ::= nt G_PLUS nt */
-3, /* (13) nt ::= nt G_MINUS nt */
-3, /* (14) nt ::= nt G_MULT nt */
-3, /* (15) nt ::= nt G_DIVIDE nt */
-3, /* (16) nt ::= nt G_EQUAL nt */
-3, /* (17) nt ::= nt G_STRUCT_REF nt */
-3, /* (18) nt ::= G_PARENL nt G_PARENR */
-4, /* (19) nt ::= G_IDENTIFIER G_PARENL nt G_PARENR */
-1, /* (20) main ::= in */
-1, /* (21) in ::= stmt */
-2, /* (22) in ::= in stmt */
-1, /* (23) stmt ::= G_ENDS */
}; };
static void yy_accept(yyParser*); /* Forward Declaration */ static void yy_accept(yyParser*); /* Forward Declaration */
@ -725,15 +912,12 @@ static YYACTIONTYPE yy_reduce(
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfoNRhs[yyruleno]; yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){ if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
yyTracePrompt, yyTracePrompt,
yyruleno, yyRuleName[yyruleno], yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yymsp[yysize].stateno);
}else{ }else{
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n", fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno], yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
} }
} }
#endif /* NDEBUG */ #endif /* NDEBUG */
@ -780,7 +964,200 @@ static YYACTIONTYPE yy_reduce(
** break; ** break;
*/ */
/********** Begin reduce actions **********************************************/ /********** Begin reduce actions **********************************************/
%% YYMINORTYPE yylhsminor;
case 0: /* stmt ::= nt G_ENDS */
#line 58 "grammar.lemon"
{ pEval->setRoot(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 ************************************************/ /********** End reduce actions ************************************************/
}; };
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) ); assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
@ -821,7 +1198,6 @@ static void yy_parse_failed(
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser fails */ ** parser fails */
/************ Begin %parse_failure code ***************************************/ /************ Begin %parse_failure code ***************************************/
%%
/************ End %parse_failure code *****************************************/ /************ End %parse_failure code *****************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -840,7 +1216,10 @@ static void yy_syntax_error(
ParseCTX_FETCH ParseCTX_FETCH
#define TOKEN yyminor #define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/ /************ Begin %syntax_error code ****************************************/
%% #line 42 "grammar.lemon"
pEval->parseError("Syntax error");
#line 1223 "grammar.c"
/************ End %syntax_error code ******************************************/ /************ End %syntax_error code ******************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -866,7 +1245,10 @@ static void yy_accept(
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser accepts */ ** parser accepts */
/*********** Begin %parse_accept code *****************************************/ /*********** Begin %parse_accept code *****************************************/
%% #line 46 "grammar.lemon"
pEval->parseOk();
#line 1252 "grammar.c"
/*********** End %parse_accept code *******************************************/ /*********** End %parse_accept code *******************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -1067,10 +1449,11 @@ void Parse(
*/ */
int ParseFallback(int iToken){ int ParseFallback(int iToken){
#ifdef YYFALLBACK #ifdef YYFALLBACK
assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
return yyFallback[iToken]; return yyFallback[iToken];
}
#else #else
(void)iToken; (void)iToken;
return 0;
#endif #endif
return 0;
} }