📄 chap29.lst
字号:
token_type = 0; tok = 0;
temp = token;
*temp = '\0';
/* skip over white space */
while(iswhite(*prog) && *prog) ++prog;
if(*prog == '\r') {
++prog;
++prog;
/* skip over white space */
while(iswhite(*prog) && *prog) ++prog;
}
if(*prog == '\0') { /* end of file */
*token = '\0';
tok = FINISHED;
return (token_type = DELIMITER);
}
if(strchr("{}", *prog)) { /* block delimiters */
*temp = *prog;
temp++;
*temp = '\0';
prog++;
return (token_type = BLOCK);
}
/* look for comments */
if(*prog == '/')
if(*(prog+1) == '*') { /* is a comment */
prog += 2;
do { /* find end of comment */
while(*prog != '*') prog++;
prog++;
} while (*prog != '/');
prog++;
}
if(strchr("!<>=", *prog)) { /* is or might be
a relational operator */
switch(*prog) {
case '=': if(*(prog+1) == '=') {
prog++; prog++;
*temp = EQ;
temp++; *temp = EQ; temp++;
*temp = '\0';
}
break;
case '!': if(*(prog+1) == '=') {
prog++; prog++;
*temp = NE;
temp++; *temp = NE; temp++;
*temp = '\0';
}
break;
case '<': if(*(prog+1) == '=') {
prog++; prog++;
*temp = LE; temp++; *temp = LE;
}
else {
prog++;
*temp = LT;
}
temp++;
*temp = '\0';
break;
case '>': if(*(prog+1) == '=') {
prog++; prog++;
*temp = GE; temp++; *temp = GE;
}
else {
prog++;
*temp = GT;
}
temp++;
*temp = '\0';
break;
}
if(*token) return(token_type = DELIMITER);
}
if(strchr("+-*^/%=;(),'", *prog)){ /* delimiter */
*temp = *prog;
prog++; /* advance to next position */
temp++;
*temp = '\0';
return (token_type = DELIMITER);
}
if(*prog=='"') { /* quoted string */
prog++;
while(*prog != '"'&& *prog != '\r') *temp++ = *prog++;
if(*prog == '\r') sntx_err(SYNTAX);
prog++; *temp = '\0';
return (token_type = STRING);
}
if(isdigit(*prog)) { /* number */
while(!isdelim(*prog)) *temp++ = *prog++;
*temp = '\0';
return (token_type = NUMBER);
}
if(isalpha(*prog)) { /* var or command */
while(!isdelim(*prog)) *temp++ = *prog++;
token_type = TEMP;
}
*temp = '\0';
/* see if a string is a command or a variable */
if(token_type==TEMP) {
tok = look_up(token); /* convert to internal rep */
if(tok) token_type = KEYWORD; /* is a keyword */
else token_type = IDENTIFIER;
}
return token_type;
}
/* Return a token to input stream. */
void putback(void)
{
char *t;
t = token;
for(; *t; t++) prog--;
}
/* Look up a token's internal representation in the
token table.
*/
int look_up(char *s)
{
register int i;
char *p;
/* convert to lowercase */
p = s;
while(*p) { *p = tolower(*p); p++; }
/* see if token is in table */
for(i=0; *table[i].command; i++) {
if(!strcmp(table[i].command, s)) return table[i].tok;
}
return 0; /* unknown command */
}
/* Return index of internal library function or -1 if
not found.
*/
int internal_func(char *s)
{
int i;
for(i=0; intern_func[i].f_name[0]; i++) {
if(!strcmp(intern_func[i].f_name, s)) return i;
}
return -1;
}
/* Return true if c is a delimiter. */
int isdelim(char c)
{
if(strchr(" !;,+-<>'/*%^=()", c) || c == 9 ||
c == '\r' || c == 0) return 1;
return 0;
}
/* Return 1 if c is space or tab. */
int iswhite(char c)
{
if(c == ' ' || c == '\t') return 1;
else return 0;
}
listing 4
/* "Standard library" functions are declared here so
they can be put into the internal function table that
follows.
*/
int call_getche(void), call_putch(void);
int call_puts(void), print(void), getnum(void);
struct intern_func_type {
char *f_name; /* function name */
int (*p)(); /* pointer to the function */
} intern_func[] = {
"getche", call_getche,
"putch", call_putch,
"puts", call_puts,
"print", print,
"getnum", getnum,
"", 0 /* null terminate the list */
};
listing 5
/* 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 functions */
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;
}
listing 6
/* An array of these structures will hold the info
associated with global variables.
*/
struct var_type {
char var_name[ID_LEN];
int v_type;
int value;
} global_vars[NUM_GLOBAL_VARS];
int gvar_index; /* index into global variable table */
/* 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);
}
listing 7
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("Usage: littlec <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])) 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 interpreting */
return 0;
}
listing 8
/* Interpret a single statement or block of code. When
interp_block() returns from its initial call, the final
brace (or a return) in main() has been encountered.
*/
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, not statement */
else return; /* is a }, so return */
}
else /* is keyword */
switch(tok) {
case CHAR:
case INT: /* declare local variables */
putback();
decl_local();
break;
case RETURN: /* return from function call */
func_ret();
return;
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: /* process a for loop */
exec_for();
break;
case END:
exit(0);
}
} while (tok != FINISHED && block);
}
listing 9
/* 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 NUM_BLOCK 100
#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};
/* add additional C keyword tokens here */
enum tokens {ARG, CHAR, INT, IF, ELSE, FOR, DO, WHILE,
SWITCH, RETURN, EOL, FINISHED, END};
/* add additional double operators here (such as ->) */
enum double_ops {LT=1, LE, GT, GE, EQ, NE};
/* These are the constants used to call sntx_err() when
a syntax error occurs. Add more if you like.
NOTE: SYNTAX is a generic error message used when
nothing 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, NOT_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 environment for longjmp() */
/* An array of these structures will hold the info
associated with global variables.
*/
struct var_type {
char var_name[ID_LEN];
int v_type;
int value;
} global_vars[NUM_GLOBAL_VARS];
struct var_type local_var_stack[NUM_LOCAL_VARS];
struct func_type {
char func_name[ID_LEN];
int ret_type;
char *loc; /* location of entry point in file */
} func_table[NUM_FUNC];
int call_stack[NUM_FUNC];
struct commands { /* keyword lookup table */
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];
char token_type, tok;
int functos; /* index to top of function call stack */
int func_index; /* index into function table */
int gvar_index; /* index into global variable table */
int lvartos; /* index into local variable stack */
int ret_value; /* function return value */
void print(void), prescan(void);
void decl_global(void), call(void), putback(void);
void decl_local(void), local_push(struct var_type i);
void eval_exp(int *value), 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);
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("Usage: littlec <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])) 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -