在清华大学出版的《编译原理》的附录里虽然有关于tex的简介和使用方法,但毕竟是作为附录登出的,在可读性上自然就要大打折扣。不过还好有internet,一切就变得简单多了。google了一大堆文章,一边看,一边写,觉得lex入门还是挺容易的。
例1:
%{
int num_lines=0,num_chars=0, num_words=0;
%}
%%
/n {++num_lines;++num_chars;}
. {++num_chars;}
[a-zA-Z]* {++num_words;}
%%
main()
{
num_lines=0;
num_chars=0;
yylex();
printf("lines: %d/nchars: %d/nwords: %d/n", num_lines, num_chars, num_words);
}
一般地,一个lex文件由三个部分组成,每个部分之间用%%分隔。例1就很清晰地展现出了这一结构。
第一部分:
%{
int num_lines=0,num_chars=0, num_words=0;
%}
的作用是声明三个全局变量,以便在lex和c源程序之间传递数值,%{和%}千万不能忘记,否则lex编译器就不会把它们之间的语句写进转换后的c源代码中。
第二部分:
/n {++num_lines;++num_chars;}
. {++num_chars;}
[a-zA-Z]* {++num_words;}
则是转换规则,功能不用解释,一看就明白。
第三部分:
main()
{
yylex();
printf("lines:%d /tchars:%d/twords:%d/n", num_lines, num_chars, num_words);
}
由于在这里lex是使用的c作为宿主语言,因此,就可以在这里放上c的别的功能的函数。
编译并运行:
lex f1.l
gcc lex.l.c -of1 -ll
./f1 < f1.l
结果就出来了。没费什么力气,一个可以统记行数,字符数和单词数的记数器就被构造出来了。
例1:
%{
int num_lines=0,num_chars=0, num_words=0;
%}
%%
/n {++num_lines;++num_chars;}
. {++num_chars;}
[a-zA-Z]* {++num_words;}
%%
main()
{
num_lines=0;
num_chars=0;
yylex();
printf("lines: %d/nchars: %d/nwords: %d/n", num_lines, num_chars, num_words);
}
一般地,一个lex文件由三个部分组成,每个部分之间用%%分隔。例1就很清晰地展现出了这一结构。
第一部分:
%{
int num_lines=0,num_chars=0, num_words=0;
%}
的作用是声明三个全局变量,以便在lex和c源程序之间传递数值,%{和%}千万不能忘记,否则lex编译器就不会把它们之间的语句写进转换后的c源代码中。
第二部分:
/n {++num_lines;++num_chars;}
. {++num_chars;}
[a-zA-Z]* {++num_words;}
则是转换规则,功能不用解释,一看就明白。
第三部分:
main()
{
yylex();
printf("lines:%d /tchars:%d/twords:%d/n", num_lines, num_chars, num_words);
}
由于在这里lex是使用的c作为宿主语言,因此,就可以在这里放上c的别的功能的函数。
编译并运行:
lex f1.l
gcc lex.l.c -of1 -ll
./f1 < f1.l
结果就出来了。没费什么力气,一个可以统记行数,字符数和单词数的记数器就被构造出来了。
博客提到清华大学出版的《编译原理》附录中关于tex的介绍可读性欠佳,借助网络搜索文章后,认为lex入门较容易。展示了lex文件的结构,包括声明全局变量、转换规则等部分,还给出编译运行步骤,最终构造出统计行数、字符数和单词数的记数器。
1077

被折叠的 条评论
为什么被折叠?



