📄 eval.c
字号:
#include "eval.h"
// eval:
// Evaluate a node in the specified environment.
void eval( struct lisa_node *node, struct lisa_environment *env )
{
switch ( node->type )
{
case LISA_TYPE_CONDITION:
{
evalCondition( node->args, env );
break;
}
case LISA_TYPE_DIRECTIVE:
{
evalDirective( node, env );
break;
}
case LISA_TYPE_EXPRESSION:
{
evalExpression( node, env );
break;
}
case LISA_TYPE_KEYWORD:
{
evalKeyword( node, env );
break;
}
case LISA_TYPE_NUMBER:
{
evalNumber( node, env );
break;
}
case LISA_TYPE_STRING:
{
evalString( node, env );
break;
}
case LISA_TYPE_TAGKEYWORD:
{
evalTAGKeyword( node, env );
break;
}
default:
{
evalError( "unimplemented token type evaluation", node );
}
}
}//eval
// evalArray:
// Evaluate an array value or identifier in the specified environment.
void evalArray( struct lisa_node *node, struct lisa_environment *env )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
evalIdentifier( node, env );
// fprintf( "$%s", node->element );
if ( node->args )
{
fprintf( outstream, "[ " );
evalCondition( node->args, env );
fprintf( outstream, " ]" );
}
break;
}
}
}//evalArray
// evalBlock:
// Evaluate a sub-block of statements in a child of the specified environment.
void evalBlock( struct lisa_node *node, struct lisa_environment *env, int brackets )
{
struct lisa_node *tmp;
struct lisa_environment *e;
// creating a child environment...
e = childEnvironment( env );
// write start of block...
switch ( env->language )
{
case LISA_LANG_PHP:
{
if ( brackets ) fprintf( outstream, "{\n" );
break;
}
}
tmp = node;
while ( tmp )
{
eval( tmp, e );
tmp = tmp->next;
}
// write stop of block...
switch ( env->language )
{
case LISA_LANG_PHP:
{
if ( brackets ) fprintf( outstream, "}\n" );
break;
}
}
// destroying the child environment...
destroyEnvironment( e );
}//evalBlock
// evalCondition:
// Evaluate a condition in the specified environment.
void evalCondition( struct lisa_node *node, struct lisa_environment *env )
{
struct lisa_node *tmp;
tmp = node;
while( tmp )
{
switch ( tmp->type )
{
case LISA_TYPE_ARRAY:
{
evalArray( tmp, env );
break;
}
case LISA_TYPE_CONDITION:
{
fprintf( outstream, "( " );
evalCondition( tmp->args, env );
fprintf( outstream, " )" );
break;
}
case LISA_TYPE_DIRECTIVE:
{
evalDirective( tmp, env );
break;
}
case LISA_TYPE_EXPRESSION:
{
fprintf( outstream, "( " );
evalCondition( tmp->args, env );
fprintf( outstream, " )" );
break;
}
case LISA_TYPE_FUNCTION:
{
evalFunction( tmp, env );
break;
}
case LISA_TYPE_IDENTIFIER:
{
evalIdentifier( tmp, env );
break;
}
case LISA_TYPE_NUMBER:
{
evalNumber( tmp, env );
break;
}
case LISA_TYPE_OPERATOR:
{
evalOperator( tmp, env );
break;
}
case LISA_TYPE_STRING:
{
evalString( tmp, env );
break;
}
}
tmp = tmp->next;
}
}//evalCondition
// evalDirective:
// Evaluate a directive node in the specified environment.
void evalDirective( struct lisa_node *node, struct lisa_environment *env )
{
struct lisa_node *tmp;
if ( strcmp( node->element, "#self" ) == 0 )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
fprintf( outstream, "$PHP_SELF" );
break;
}
}
return;
}
if ( strcmp( node->element, "#include" ) == 0 )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
if ( node->args->type == LISA_TYPE_STRING )
{
// including a general file...
fprintf( outstream, "include( " );
evalString( node->args, env );
fprintf( outstream, " );\n" );
}
else
{
// including a module...
fprintf( outstream, "require( '%s.php' );\n", node->args->element );
}
break;
}
}
return;
}
if ( strcmp( node->element, "#php" ) == 0 )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
tmp = node->args;
while ( tmp )
{
fprintf( outstream, "%s\n", tmp->element );
tmp = tmp->args;
}
break;
}
}
return;
}
evalError( "unimplemented directive evaluation", node );
}//evalDirective
// evalError:
// Display an error message for the specified node
// and exit from evaluation.
void evalError( char *msg, struct lisa_node *node )
{
fprintf( stderr, "\nOn token '%s' (type %d) at line %d:\n\t", node->element, node->type, node->line );
error( msg );
}//evalError
// evalExpression:
// Evaluate an expression in the specified environment.
void evalExpression( struct lisa_node *node, struct lisa_environment *env )
{
// NOTE: (2002-06-28 Gabriele Budelacci)
// An EXPRESSION is equivalent to a CONDITION, followed by a
// SEMICOLON ';' (lisa language). So, I will evaluate firsts
// the condition, then I will write the terminal character,
// depending wich target language is compiling to.
// evaluating the condition firsts...
evalCondition( node->args, env );
switch ( env->language )
{
case LISA_LANG_PHP:
{
fprintf( outstream, ";\n" );
break;
}
}
}//evalExpression
// evalFunction:
// Evaluate a function node in the specified environment.
void evalFunction( struct lisa_node *node, struct lisa_environment *env )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
// NOTE: (2002-07-03 Gabriele Budelacci)
// Functions compiled have the same name as specified
// in lisa source, undercased and preceased by an
// underscore ('_').
fprintf( outstream, "_%s(", node->element );
if ( ! emptyNode( node->args ) )
{
fprintf( outstream, " " );
evalCondition( node->args->args, env );
fprintf( outstream, " " );
}
fprintf( outstream, ")" );
break;
}
}
}//evalFunction
// evalIdentifier:
// Evaluate a identifier node in the specified environment.
void evalIdentifier( struct lisa_node *node, struct lisa_environment *env )
{
if ( ! findNodeByElement( node->element, env->declared ) )
evalError( "undeclared variable", node );
switch ( env->language )
{
case LISA_LANG_PHP:
{
if ( findNodeByElement( node->element, env->globals ) )
fprintf( outstream, "$SESSION['%s']", node->element );
else
fprintf( outstream, "$%s", node->element );
break;
}
}
}//evalIdentifier
// evalKeyword:
// Evaluate a keyword node in the specified environment.
void evalKeyword( struct lisa_node *node, struct lisa_environment *env )
{
struct lisa_node *tmp, *next;
if ( strcmp( node->element, "array" ) == 0 )
{
// firsts, check if there is another identifiers declared...
next = node->args;
while ( next )
{
// search the node in declared list...
tmp = findNodeByElement( next->element, env->declared );
// if not exists, append a new identifier...
if ( tmp == NULL )
{
tmp = cloneNode( next );
// NOTE: (2002-07-12 Gabriele Budelacci)
// When a new variable is declared whithin a block,
// then the type is negated.
tmp->type = -LISA_TYPE_ARRAY; // please note minus '-' sign
appendNode( tmp, env->declared );
}
else
{
// The identifier is already declared...
// If the type is positive, the identifier can be redeclared...
if ( tmp->type < 0 )
{
evalError( "variable already declared", tmp );
}
tmp->type = -LISA_TYPE_ARRAY;
}
// process next element
next = next->next;
}
switch ( env->language )
{
case LISA_LANG_PHP:
{
// NOTE: (2002-06-27 Gabriele Budelacci)
// In PHP language, declaration of variants
// can be omitted.
break;
}
}
return;
}
if ( strcmp( node->element, "break" ) == 0 )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
fprintf( outstream, "break;\n" );
break;
}
}
return;
}
if ( strcmp( node->element, "continue" ) == 0 )
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
fprintf( outstream, "continue;\n" );
break;
}
}
return;
}
//
// foreach
// / |
// array-set-identifier ...
// / |
// block { identifier }
//
if ( strcmp( node->element, "foreach" ) == 0 )
{
int type;
struct lisa_environment *e;
// check if identifier is declared...
tmp = findNodeByElement( node->args->element, env->declared );
if ( tmp == NULL )
evalError( "undeclared variable", node->args );
// get the identifier type...
type = tmp->type;
if ( type < 0 ) type = -type;
// switch on array or set
switch ( type )
{
case LISA_TYPE_ARRAY:
{
switch ( env->language )
{
case LISA_LANG_PHP:
{
fprintf( outstream, "foreach ( $%s as ", node->args->element );
e = childEnvironment( env );
// declaring the identifiers as variants...
next = node->args->next;
while ( next )
{
// search the node in declared list...
tmp = findNodeByElement( next->element, e->declared );
// if not exists, append a new identifier...
if ( tmp == NULL )
{
tmp = cloneNode( next );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -