理解c语言的优先级规则:
A
声明从它的名字开始读取,然后按照优先级次序一次读取
B
优先级从高到底依次是:
b1 声明中被括号括起来的那部分
b2 后缀操作符
括号()表示这是一个函数,而方括号【】表示这是一个数组
b3 前缀操作符,星号*表示“指向。。。的指针”
C
如果const(或volatile)关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符,在其他情况下作用于它左边
紧邻的指针*号。
如 char * const*(*next)();
上式表示“next是一个指针,它指向一个函数,这个函数返回另外一个指针,该指针指向一个类型为char的常量指针”
这里有一个设计方案,主要的数据结构是一个堆栈,我们从左向右读取,把各个标记依次压入堆栈,知道读到标识符为止,然后我们继续向右读入一个标记,也就是标识符右边的那一个标记,接着观察标识符左边的那个标记(需要从堆栈中弹出)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LEN 100
enum type_token {IDENTIFIER,QUALIFIER,TYPE};
typedef struct token{
char string[100];
char type;
}token;
token tmp_token;
typedef struct stack{
token array[MAX_LEN];
int top;
}stack;
struct stack token_stack;
void init(stack *sta)
{
sta->top=-1;
}
int push(stack *sta,token s)
{
if(sta->top>=254)
{
printf("the stack is full.\n");
return 1;
}
else
{
sta->array[++(sta->top)]=s;
}
return 0;
}
token pop(stack *sta)
{
if(sta->top==-1)
{
printf("ERROR,the stack is empty!\n");
}
else
{
return sta->array[(sta->top)--];
}
}
int stack_empty(const stack s)
{
if(s.top==-1)
return 0;
else
return 1;
}
token top_stack(const stack s)
{
if(stack_empty(s)==0)
{
printf("ERROR the stack is empty!\n");
}
else
return s.array[s.top];
}
enum type_token classify_string();
void gettoken()
{//读取token函数,如果是字母,数字,下划线就一直读取,否则就停止存入tmp_token中处理
memset(tmp_token.string,'\0',sizeof(tmp_token.string));//先把tmp_token清空
char *p=tmp_token.string;
while((*p=getchar())==' ');//略过空白字符
if(isalnum(*p) || *p=='_'){
//读入的标志符要是字母,数字或者下划线,表示是标志符
while(1)
{
*(++p)=getchar();
if(isalnum(*p) || *p=='_')
continue;
else
break;
}
ungetc(*p,stdin);//把非满足的字符放回缓冲区,下次再用
*p='\0';
tmp_token.type=classify_string();
return;
}
if(*p=='*'){
strcpy(tmp_token.string,"pointer to ");
tmp_token.type='*';
return;
}
tmp_token.string[1]='\0';
tmp_token.type=*p;
return;
}
enum type_token classify_string()
{//推断标志符的类型
char *s=tmp_token.string;
if(!strcmp(s,"const")){
strcpy(s,"read-only ");
return QUALIFIER;
}
if(!strcmp(s,"volatile")) return QUALIFIER;
if(!strcmp(s,"extern")) 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 read_first_identifier(){
gettoken();
while(tmp_token.type!=IDENTIFIER){
push(&token_stack,tmp_token);
gettoken();
}
printf("%s is ",tmp_token.string);
gettoken();
}
void deal_with_array()
{
while(tmp_token.type=='[')
{
printf("array");
gettoken();
if(isdigit(tmp_token.string[0]))
{
printf(" 0..%d ",atoi(tmp_token.string)-1);
gettoken();
}
gettoken();//读取‘】’之后的token
printf("of ");
}
}
void deal_with_function()
{
while(tmp_token.type != ')')
gettoken();
gettoken();
printf(" function returning ");
}
void deal_with_pointer()
{
token t;
t=top_stack(token_stack);
while(t.type=='*')
{
printf("%s",t.string);
pop(&token_stack);
t=top_stack(token_stack);
}
}
void deal_with_declarator(){//递归处理的过程
switch(tmp_token.type){
case '[': deal_with_array();break;
case '(': deal_with_function();
}
deal_with_pointer();
while(stack_empty(token_stack)==1)
{
token t=top_stack(token_stack);
if(t.type=='('){
pop(&token_stack);
gettoken();//读取‘)’之后的符号
deal_with_declarator();
}
else
{
printf("%s",pop(&token_stack).string);
}
}
}
int main()
{
init(&token_stack);
read_first_identifier();
deal_with_declarator();
printf("\n");
return 0;
}