分类: C/C++
2008-09-24 11:48:10
C语言的声明语句,一直是我的一个弱项。这两天读《Expert C Programing》,发现一个读复杂的声明的方法,而且提供了伪代码,于是自己翻译成了一个完整的C程序。
后来才发现,后面几页就是C源码,而且实现的也很像(一样的伪码嘛)。
不过反正也写了,就贴出来显摆一下吧!
/*
* This is a cdecl, translate C definetion to nature setence
*
* Author: Alf
* Email: naihe2010@gmail.com
* Blog: http://naihe2010.cublog.cn
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXTOKENLEN 0x10
#define MAXTOKENS 0x20
enum { TYPE, QUAILITER, IDENTIFIER };
struct token
{
char type;
char string[MAXTOKENLEN];
};
struct token stack[MAXTOKENS];
struct token this;
static int top;
static char *p, *e;
static void
classify_string (void)
{
static char *types[] = {
"signed", "unsigned", "char", "int", "short", "long", "float", "double",
"struct", "union", "enum"
};
static char *quailiters[] = { "const", "static", "volatile" };
unsigned int i;
for (i=0; i<sizeof (types) / sizeof (types[0]); ++i)
{
if (strcmp (this.string, types[i]) == 0)
{
this.type = TYPE;
return;
}
}
for (i=0; i<sizeof (quailiters) / sizeof (quailiters[0]); ++i)
{
if (strcmp (this.string, quailiters[i]) == 0)
{
this.type = QUAILITER;
return;
}
}
this.type = IDENTIFIER;
}
static void
gettoken (void)
{
int len = 0;
while (isspace (*p))
p ++;
if (isalnum (*p))
{
while (isalnum (*p))
{
this.string[len ++] = *p;
p ++;
}
this.string[len] = '\0';
classify_string ();
}
else
{
this.type = *p;
this.string[len] = '\0';
if (*p == '*')
{
strcpy (this.string, "pointer to ");
}
p ++;
}
}
static void
read_to_first_identifier (void)
{
gettoken ();
while (this.type != IDENTIFIER)
{
stack[++ top] = this;
gettoken ();
if (p >= e)
break;
}
printf ("%s is ", this.string);
gettoken ();
}
static void
deal_with_func_args (void)
{
while (this.type != ')')
{
gettoken ();
}
printf ("function returning ");
gettoken ();
}
static void
deal_with_arrays (void)
{
while (this.type == '[')
{
printf ("array ");
gettoken ();
if (isdigit (this.string[0]))
{
printf ("0 .. %d ", atoi (this.string) - 1);
gettoken ();
}
gettoken ();
printf ("of ");
}
}
static void
deal_with_any_pointers (void)
{
while (stack[top].type == '*')
{
printf ("%s ", stack[top].string);
top --;
}
}
static void
deal_with_declarator (void)
{
if (this.type == '[')
{
deal_with_arrays ();
}
if (this.type == '(')
{
deal_with_func_args ();
}
deal_with_any_pointers ();
while (top > -1)
{
if (stack[top].type == '(')
{
top --;
gettoken ();
deal_with_declarator ();
}
else
{
printf ("%s ", stack[top].string);
top --;
}
}
}
static void
usage (void)
{
fprintf (stderr, "cdecl setence\n");
}
int
main (int argc, char *argv[])
{
if (argc < 2)
{
usage ();
return -1;
}
p = argv[1];
e = p + strlen (p);
printf ("\n\n");
read_to_first_identifier ();
deal_with_declarator ();
printf ("\n\n\n");
return 0;
}