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

📄 litc.c

📁 自己做的一个C语言的解释器 给大家做个参考
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************
* Porject Name:
*	Little C Interprete
* Version & Revision:
*	1.0.1
* Creation Date:
*	2005-02-02
* Author:
*	Herbet Schildt & Yock Yu
* Description:
*	A little C interpreter
********************************************************/

#include "stdio.h"
#include "setjmp.h"
#include "math.h"
#include "ctype.h"
#include "stdlib.h"
#include "string.h"

#define NUM_FUNC		100
#define NUM_GLOBAL_VARS	100
#define NUM_LOCAL_VARS	200
#define ID_LEN			31
#define FUNC_CALLS		31
#define NUM_PARAMS		31
#define PROG_SIZE		10000
#define LOOP_NEST		31

enum tok_types{DELIMITER, IDENTIFIER, NUMBER, KEYWORD, TEMP, STRING, BLOCK};

enum tokens{ARG, CHAR, INT, IF, ELSE, FOR, DO, WHILE, 
				SWITCH, CASE, BREAK, CONTINUE, /*Rev 1.05 yock.yu 05-02-18*/
				RETURN, EOL, FINISHED, END};

enum double_ops{LT = 1, LE, GT, GE, EQ, NE};

/*
	These are the constants used to all sntx_err()
	when a syntax error occurs. Add more if you like.
	NOTE:SYNTAX is generic error message used when
	noting else seems appropriate.
*/
enum error_msg{SYNTAX, UNBAL_PARENS, NO_EXP, EQUALS_EXPECTED, NOT_VAR, PARAM_ERR,
				SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF, TYPE_EXPECTED, NEST_FUNC,
				RET_NOCALL, PAREN_EXPECTED, WHILE_EXPECTED, QUOTE_EXPECTED,
				NO_TEMP, TOO_MANY_LVARS, DIV_BY_ZERO};

char *prog; /* current location in source code */
char *p_buf; /* points to start of program buffer */
jmp_buf e_buf; /* hold enviorment for longjmp() */

/* global block count */
static int gblock = 0;/*Rev 1.03 yock.yu 05-02-16*/
/* backup block count */
static int bak_gblock = 0;/*Rev 1.03 yock.yu 05-02-16*/

struct var_type{
	char var_name[32];
	int v_type;
	int value;
}global_vars[NUM_GLOBAL_VARS];

struct var_type local_var_stack[NUM_LOCAL_VARS];

/*
	This is the function call stack
*/
struct func_type{
	char func_name[32];
	int ret_type;
	char *loc; /* location of function entry point in file */
}func_table[NUM_FUNC];

int call_stack[NUM_FUNC];

/*
	Keyword table
*/
struct commands{
	char command[20];
	char tok;
}table[]={ /* Commands must be entered lowercase */
	"if", IF, /* in this table */
	"else", ELSE,
	"for", FOR,
	"do", DO,
	"while", WHILE,
	"char", CHAR,
	"int", INT,
	/*Rev 1.05 yock.yu 05-02-18 start*/
	"switch", SWITCH,
	"case", CASE,
	"break", BREAK,
	"continue", CONTINUE,
	/*Rev 1.05 yock.yu 05-02-18 end*/
	"return", RETURN,
	"end", END,
	"", END /* mark end of table */
};

char token[80]; /* string representation of token */
char token_type; /* contains type of token */
char tok; /* internal representation of token */

int functos; /* index to top of function call stack */
static int func_index = 0; /* index into function table */
static int gvar_index = 0; /* index into global variable table */
int lvartos; /* index into local variable stack */

int ret_value; /* function return value */

extern void print(void);
void	prescan(void), decl_global(void), call(void);
extern void putback(void);
void decl_local(void), local_push(struct var_type);
extern void eval_exp(int *value);
extern void sntx_err(int error);
void exec_if(void), find_eob(void), exec_for(void);
void get_params(void), get_args(void);
void exec_while(void), func_push(int i), exec_do(void);
void assign_var(char *var_name, int value);
int load_program(char *p, char *fname), find_var(char *s);
void interp_block(void), func_ret(void);
int func_pop(void), is_var(char *s), get_token(void);
char *find_func(char *name);
/*Rev 1.05 yock.yu 05-02-18*/
void exec_switch(void), fetch(char c);

int main(int argc, char *argv[])
{
	if(argc != 2){
		printf("Usage: litc <filename> \n");
		exit(1);
	}

	/* allocate memory for the program */
	if((p_buf = (char *)malloc(PROG_SIZE)) == NULL){
		printf("Allocation Failure");
		exit(1);
	}

	/* load the program to execute */
	if(!load_program(p_buf, argv[1])){
		printf("Open source file [%s] Failure\n", argv[1]);
		exit(1);
	}
	if(setjmp(e_buf))
		exit(1); /* initialize long jump buffer */

	gvar_index = 0; /* initialize global variable index */

	/* set program pointer to start of program buffer */
	prog = p_buf;

	prescan(); /* find the location of all functions
				and global variables in the program */

	lvartos = 0; /* initialize local variable stack index */
	functos = 0; /* initialize the CALL stack index */

	/* setup call to main() */
	prog = find_func("main"); /* find program starting point */

	if(!prog){ /* incorrect or missing main() function in program */
		printf("main() not found. \n");
		exit(1);
	}

	prog--; /* back up to opening ( */
	strcpy(token, "main");
	call(); /* call main() to start interpreteting */

	return 0;
}

/*
	Interpret a single statement or block of code.
	When interp_block() returns its initial call,
	the final brace(or a return) in main() has been encounted.
*/
void interp_block(void)
{
	int value;
	char block = 0;

	do{
		token_type = get_token();

		/*
			if interpreting single statement,
			return on first semicolon.
		*/

		/* see what kind of token is up */
		if(token_type == IDENTIFIER){
			/* not a keyword, so process expression. */
			putback(); /* restore token to input stream for
						further processing by eval_exp() */
			eval_exp(&value); /* process the expression */
			if(*token != ';')
				sntx_err(SEMI_EXPECTED);
		}
		else if(token_type == BLOCK){ /* if block delimiter */
			if(*token == '{'){ /* is a block */
				block = 1; /* interpreting block, no statement */
				gblock++;/* increamt block number *//*Rev 1.03 yock.yu 05-02-16*/
			}
			else{ /* is a }, so return */
				gblock--;/* decreamt block number*//*Rev 1.03 yock.yu 05-02-16*/
				return;
			}
		}
		else{ /* is keyword */
			if(tok >= IF && tok <= SWITCH)/*Rev 1.03 yock.yu 05-02-16*/
				bak_gblock = gblock;/*Rev 1.03 yock.yu 05-02-16*/
			switch(tok){
				case CHAR:
				case INT: /* declare local variables */
					putback();
					decl_local();
					break;
				case RETURN: /* return from function call */
					func_ret();
					break;
				case IF: /* process an if statement */
					exec_if();
					break;
				case ELSE: /* process an else statement */
					find_eob(); /* find end of else block
								and continue execution */
					break;
				case WHILE: /* process a while loop */
					exec_while();
					break;
				case DO: /* process a do-while loop */
					exec_do();
					break;
				case FOR:
					exec_for(); /* process a for loop */
					break;
				case END:
					exit(0);
					break;
				/*Rev 1.05 yock.yu 05-02-18 start*/
				case SWITCH:
					exec_switch();
					break;
				case BREAK:
					
					break;
				/*Rev 1.05 yock.yu 05-02-18 end*/
			}
		}
	}while(tok != FINISHED && block);
}

/* Load a program. */
int load_program(char *p, char *fname)
{
	FILE *fp;
	int i = 0;

	if((fp = fopen(fname, "rb")) == NULL)
		return 0;

	do{
		*p = getc(fp);
		p++;i++;
	}while(!feof(fp) && i < PROG_SIZE);

	if(*(p - 2) == 0x1A)
		*(p - 2) = '\0'; /* null terminate the program */
	else
		*(p - 1) = '\0';

	fclose(fp);

	return 1;
}

/*
	Find the location of all functions in the
	program and store global variables.
*/
void prescan(void)
{
	char *p, *tp;
	char temp[32];
	int datatype;
	int brace = 0; /* when 0, this var tells us that current
					source position is outside of any function. */

	p = prog;
	func_index = 0;
	do{
		while(brace){ /* bypass code inside function */
			get_token();
			if(*token == '{')
				brace++;
			if(*token == '}')
				brace--;
		}

		tp = prog; /* save current position */
		get_token();
		/* global var type or function return type */
		if(tok == CHAR || tok == INT){
			datatype = tok; /* save data type */
			get_token();
			if(token_type == IDENTIFIER){
				strcpy(temp, token);
				get_token();
				if(*token != '('){ /* must be global var */
					prog = tp; /* return to start of declaration */
					decl_global();
				}
				else if(*token == '('){ /*must be a function */
					func_table[func_index].loc = prog;
					func_table[func_index].ret_type = datatype;
					strcpy(func_table[func_index].func_name, temp);
					func_index++;
					while(*prog != ')')
						prog++;
					prog++;
					/* now prog points to opening curly brace of function */
				}
				else
					putback();
			}
		}
		else if(*token == '{')
			brace++;
	}while(tok != FINISHED);

	prog = p;
}

/*
	Return the entry point of the specified function.
	Return NULL if not found.
*/
char *find_func(char *name)
{
	register int i;

	for(i = 0; i < func_index; i++)
		if(!strcmp(name, func_table[i].func_name))
			return func_table[i].loc;

	return NULL;
}

/* Declare a global variable. */
void decl_global(void)
{
	int vartype;

	get_token(); /* get type */

	vartype = tok; /* save var type */

	do{ /* process comma-separated list */
		global_vars[gvar_index].v_type = vartype;
		global_vars[gvar_index].value = 0; /* init to 0 */
		get_token(); /* get name */
		strcpy(global_vars[gvar_index].var_name, token);
		get_token();
		gvar_index++;
	}while(*token == ',');

	if(*token != ';')
		sntx_err(SEMI_EXPECTED);
}

/* Declare a local variable. */
void decl_local(void)
{
	struct var_type i;

	get_token(); /* get type */

	i.v_type = tok;
	i.value = 0; /* init to 0 */

	do{ /* process comma-separated list */
		get_token(); /* get var name*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -