有时候,C语言声明十分反人类……于是,cdecl应运而生~~~
//
// main.cpp
// f-cdecl
//
// Created by ZYJ on 2016/11/2.
// Copyright © 2016年 ZYJ. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
#define pop stack[top--]
#define push(s) stack[++top] = s
enum type_tag
{
IDENTIFIER, QUALIFIER, TYPE
};
struct token
{
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token this_;
enum type_tag classify_string() // 推断标识符的类型
{
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() // 读取下一个标记到 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("%s is ", this_.string);
gettoken();
}
void deal_with_arrays()
{
while (this_.type == '[')
{
printf("array ");
gettoken(); // 数字或']'
if (isdigit(this_.string[0]))
{
int temp;
sscanf(this_.string, "%d", &temp);
printf("0..%d ", temp - 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();
break;
}
deal_with_pointers();
// 处理在读入到标识符之前压入到堆栈的符号
while (top >= 0)
{
if (stack[top].type == '(')
{
pop;
gettoken(); // 读取')'之后的符号
deal_with_declarator();
}
else
{
printf("%s ",pop.string);
}
}
}
int main()
{
// 将标记呀入堆栈中,直到遇见标识符
read_to_first_identifier();
deal_with_declarator();
printf("\n");
return 0;
}
PS:源码来自《C专家编程》,Xcode [Version 8.1 (8B62)]亲测无误。