3.8 理解所有分析过程的代码段
编写一个程序,把C语言的声明翻译成通俗的语言:
主要的数据结构是一个stack,我们从左向右读取,把各个标记依次压入stack,直到读到标示符为止。然后我们继续向右读入一个标记,也就是标示符右边的那个标记。接着,观察标示符左边的那个标记(需要从stack中弹出)。
数据结构大致如下:
struct token{
char type;
char string[MAXTOKENLEN];}
/* 保存第一个标示符之前的所有标记 */
struct token stack[MAXTOKENS];
/* 保存刚读入的那个标记 */
struct token this;
伪代码如下:
实用程序---------
classify_string(字符串分类)
查看当前的标记,
通过this.type返回一个值,内容为"type(类型)","gualifier(限定符)"或"indentifier(标示 符)"
gettoken(取标记)
把下一个标记读入this.string
如果是字母数字组合,调用classify_string
否则,它必须是一个单字符标记,this.type 该标记用一个NUL结束this.string
read_to_first_identifier(读至第一个标示符)
调用getoken,并把标记压入到stack中,直到遇见第一个标示符。
Print"identifier is ",this.string;
继续调用gettoken.
解析程序--------
deal_with_function_args(处理函数参数)
当读取越过右括号')'后,打印"函数返回"
deal_with_arrays(处理函数数组)
当读取"[size]"后,将其打印并继续向右读取。
deal_with_any_pointers(处理任何指针)
当你从stack中读取'*'时,打印"指向...的指针"并将其弹出stack.
deal_with_declarator(处理声明器)
if this.type is '[' deal_with_arrays;
if this.type is '{' deal_with_function_args;
deal_with_any_pointers;
while stack里还有东西
if 它是一个左括号'('
将其弹出,并调用gettoken;应该获得右括号')'
deal_with_declarator
else 将其弹出stack并打印它。
主程序---------
main
read_to_first_identifier
deal_with_declarator
code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum tyoe_tag{ IDENTIFIER,QUALIFIER,TYPE};
struct token{
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token this;
#define pop stack[top--]
#define push(s) stack[++top] = s;
void deal_with_declarator();
enum tyoe_tag classify_string(void);
void gettoken(void);
void read_to_first_identifier();
void deal_with_arrays();
enum tyoe_tag classify_string(void)
{/* 推断标识符 */
char *s = this.string;
if(!strcmp(s,"const")){
strcpy(s,"read-only");
return QUALIFIER;
}
if(!strcmp(s,"volatile")) return QUALIFIER;
if(!strcmp(s,"void")) return TYPE;
if(!strcmp(s,"char")) return TYPE;
if(!strcmp(s,"signed")) return TYPE;
if(!strcmp(s,"unsigned")) return TYPE;
if(!strcmp(s,"short")) return TYPE;
if(!strcmp(s,"int")) return TYPE;
if(!strcmp(s,"long")) return TYPE;
if(!strcmp(s,"float")) return TYPE;
if(!strcmp(s,"double")) return TYPE;
if(!strcmp(s,"struct")) return TYPE;
if(!strcmp(s,"union")) return TYPE;
if(!strcmp(s,"enum")) return TYPE;
return IDENTIFIER;
}
void gettoken(void)
{/* 读取下一个标记到"this" */
char *p = this.string;
/* 略国空白符 */
while((*p = getchar())==' ');
if(isalnum(*p)){
/* 读入的标识符以A-Z,0-9开头 */
while(isalnum(*++p=getchar()));
ungetc(*p,stdin);
*p = '\0';
this.type = classify_string();
return;
}
if(*p=='*'){
strcpy(this.string,"pointer to");
this.type = '*';
return;
}
this.string[1] = '\0';
this.type = *p;
return;
}
/* 理解所有分析过程的代码 */
void read_to_first_identifier(){
gettoken();
while(this.type != IDENTIFIER){
push(this);
gettoken();
}
printf("%sis ",this.string);
gettoken();
}
void deal_with_arrays(){
while(this.type=='['){
printf("array ");
gettoken(); /* 数字或']' */
if(isdigit(this.string[0])){
printf("0..%d",atof(this.string-1));
gettoken(); /* 读取']' */
}
gettoken(); /* 读取']'之后的再一个标记 */
printf("of ");
}
}
void deal_with_function_args(){
while(this.type != '|'){
gettoken();
}
gettoken();
printf("function returning ");
}
void deal_with_pointers(){
while(stack[top].type=='*'){
printf("%s ",pop.string);
}
}
void deal_with_declarator(){
/* 处理标识符之后可能存在的数组/函数 */
switch(this.type){
case '[': deal_with_arrays();break;
case '(': deal_with_function_args();
}
deal_with_pointers();
/* 处理在读入到标识符之前压入stack中的符号 */
while(top >= 0){
if(stack[top].type=='('){
pop;
gettoken(); /* 读取')'之后的符号*/
deal_with_declarator();
}
else{
printf("%s ",pop.string);
}
}
}
int main()
{
/* 将标记压入stack中,直到遇见标识符 */
read_to_first_identifier();
deal_with_declarator();
printf("\n");
system("pause");
return 0;
}

评论