一个cdecl 程序的混乱版本
#include <stdio.h>
#include <ctype.h>
#define w printf
#define p while
#define t(s) (W=T(s))
char*X,*B,*L,I[99];
M,W,V;
D(){
W==9 ? (w("'%.*s' is",V,X),t(0)) : W==40 ?
(t(0),D(),t(41)) : W==42 ? (t(0),D(),w("ptr to ")) : 0;
p(w == 40 ? (t(0),w("func returning "),t(41)) : W==91 ? (t(0)==32 ? (w("array[0..%d]of ",
atoi(X)-1),t(0)) : w("array of "),t(93)) : 0);
}
main(){
p( w("input:"),B=gets(I) )
if(t(0)==9)
L=X,M=V,t(0),D(),w("%.*s.\n\n",M,L);
}
T(s)
{
if(!s || s==w )
{
p(*B==9 || *B==32)B++;
X=B;
V=0;
if( W = isalpha(*B) ? 9 : isdigit(*B) ? 32 : *B++ )
if( W < 33 )
p(isalnum(*B))B++,V++;}
return W;
}
预处理并用 if 语句替换 "?:" 表达式之后程序还是蛮简单的
#i nclude <stdio.h>
#i nclude <ctype.h>
char *X,*B,*L,I[99];
int M,W,V;
int T(int s);
void D()
{
if(W==9)
{
/* 在此遇到的一定是 identifier 处理之并读取下一个 token */
printf("'%.*s' is",V,X),(W=T(0));
}
else if(W==40)
{
/* 使用()改变声明优先关系的情况,比如 "int (*next)[23]" */
(W=T(0)),D(),(W=T(41));
}
else if(W==42)
{
/* 处理 '*' 后面的所有信息 之后打印 "ptr to " */
((W=T(0)),D(),printf("ptr to "));
}
/* 处理函数("()") 和数组("[]") 的情况并读取下一个 token */
while(W==40?((W=T(0)),printf("func returning "),(W=T(41)))
:W==91?((W=T(0))==32?(printf("array[0..%d]of ",atoi(X)-1),(W=T(0)))
:printf("array of "),(W=T(93)))
:0);
}
void main()
{
while(printf("input:"),B=gets(I))
/* 取得输入 */
{
if((W=T(0))==9)
{
/* type-specifier,qualifier是最后在这里输出的 */
L=X,M=V,(W=T(0)),D(),printf("%.*s.\n\n",M,L);
}
}
}
/* lex 过程,s = 0,直接读取下一个token;
* 否则检查当前token是否是期望的 s 并读取下一个token
* *********************************************************
* 如果是 identifier 和 type-specifier 则返回 9;
* 如果是 number 则返回 32;
* 如果是其他的特殊字符返回 ascii 值
*/
int T(int s)
{
if(!s||s==W)
/* 检查当前的token(W)是否是期望的那个(s) 这一步起 match 的作用 */
{
while(*B==9||*B==32)
/* 跳过空白符 */
{
B++;
}
X=B;
V=0;
/* 处理识别 identifier 和 number 的情况
* 注意 type-specifier 也被作为 identifier 处理
*/
if(W=isalpha(*B)?9:isdigit(*B)?32:*B++)
if(W<33)
while(isalnum(*B))
B++,V++;
}
return W;
}
/************************************************
* B 存储的是当前分析过程处理到的输入串中的位置 如 f;
* L 存储之前处理的输入串中的位置,用于输出 如 float f;
* X 存储当前处理的token的开始位置 如 float f;
* L 输入缓冲区
* W 存储的是当前读到的 token 的值 如 9
* M,V 存储当前token长度用于输出控制
************************************************
*/
note:程序是1988年的 c 混乱大赛的获胜者,,在读的过程中我开始总是想const怎么办?函数形参序列怎么办,后来才意识到当时还没有ANSI C标准,只支持K&R C形式的声明(而且没有支持存储限定符),被被郁闷了!
不过想想这么短的程序,怎么能要求那么高呢?:-)
感觉比那个打印圣诞十二天的程序在思路上以及程序本身来说都简单
----郁闷的饿猫