?? litc.c
字號:
/********************************************************
* 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, 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,
"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);
void exec_else(void);
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 */
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 */
exec_else();/*Rev 1.04 yock.yu 05-02-17*/
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);
}
}
}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)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -