⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 Coware的LISA指令集描述语言开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 + -