Lex/Flex
69 个字符。在此处的文本中,我将制表符更改为 8 个空格,这样看起来正确,但所有这些连续的空格都应该是制表符,并且制表符很重要,所以它变成了 69 个字符。
#include <stdio.h>
%%
HAA|HH|H printf("AH");
AAH|AA|A printf("HA");
不管怎样,生成的lex.yy.c 是 42736 个字符,但我认为这并不重要。我可以(并且很快会)编写一个更短的纯 C 版本并且做同样的事情,但我觉得这可能应该是一个单独的条目。
编辑:
这是一个更合法的 Lex/Flex 条目(302 个字符):
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);if(t)c=t,strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);if(!c)return 1;*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
这会进行多次迭代(与上一次不同,它只进行一次迭代,每次都必须手动播种,但会产生正确的结果),并且具有看起来非常可怕的代码的优势。我使用一个函数宏、字符串化运算符和两个全局变量。如果您想要一个甚至不检查 malloc() 故障的更混乱的版本,它看起来像这样(282 个字符):
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);c=t;strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
还可以编造一个更糟糕的版本,其中 c 是堆栈上的一个数组,我们只是给它一个 MAX_BUFFER_SIZE 某种形式,但我觉得这太过分了。
...开个玩笑。 207 个字符,如果我们采用“99 个字符总是就足够了”的心态:
char c[99]="H";
%%
c[0]=0;
HAA|HH|H strcat(c, "AH");
AAH|AA|A strcat(c, "HA");
%%
int main(void){for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
我偏爱效果最好的那个(即第一个可以迭代直到内存耗尽并检查其错误的那个),但这是代码高尔夫。
要编译第一个,输入:
flex golf.l
gcc -ll lex.yy.c
(如果您有lex 而不是flex,只需将flex 更改为lex。它们应该是兼容的。)
要编译其他的,请输入:
flex golf.l
gcc -std=c99 lex.yy.c
否则 GCC 会抱怨 ‘for’ loop initial declaration used outside C99 mode 和其他废话。
纯 C 答案即将出现。