libeval_compiler: general clean up of the Lemon grammar + some smart pointers + killed all memory leaks. WIP!
This commit is contained in:
parent
29a01e5515
commit
a5a06e3c89
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue