码迷,mamicode.com
首页 > 其他好文 > 详细

初识 lex

时间:2017-12-20 03:55:21      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:lex

一、背景

     从零开始学习下lex和yacc

     1. 基础

      lex只有状态和状态转换,没有栈,善于模式匹配;yacc能处理带栈的FSA(有限状态机),更适合更复杂的任务。

      

模式匹配原语

元字符
匹配说明
.
任意字符( 除了换行)
\n
换行
*
0次或者多次重复前面的表达式
+
1次或者多次重复前面的表达式
?
0次或者1次重复前面的表达式
^
行的开始
$
行的结尾
a|b
a or b
(ab)+

1次或者多次重复组ab

[...]
任意一个出现的字符


一些匹配的例子

 

表达式
匹配说明
abc
abc
abc*
ab, abc, abcc, abccc,.....
abc+
abc, abcc, baccc,......
a(bc)+
abc, abcbc, abcbcbc,......
a(bc)?
a, abc
[abc]
a, b, c
[a-z]
a到z的任意字符
[a\-z]
a, -, z
[-az]
-, a, z
[a-zA-Z0-9]+
一个或者多个任何数字字母
[ \t\n]
witespace
[^ab]
除了a,b的任何字符
[a^b]
a, ^, b
[a|b]
a, |, b
a|b
a or b


匹配规则:

    1. 贪心: 两个模式去匹同一个字符串,匹配上最长的模式

    2. 顺序优先: 两个相同长度的模式, 匹配上先定义的模式


.l文件内容的格式被%%分成了三部分,如下:

     ....definitions.....

%%

  .....rules....

%%

 ...subroutines...

  

    其中rules是必须的,其他部分可选


    一些内置函数以及变量

    

int yylex(void)
调用分析器,返回 token
char *yytext
指定匹配的字符串
yyleng
匹配上的字符串的长度
int yywrap(void)
返回1 则结束了
FILE *yyout
输出文件,默认 stdout
FILE *yyin
输入文件, 默认stdin
INITIAL
initial start condition
BEGIN condition
switch start condition
ECHO 
write mached string

#define ECHO fwrite(yytext, yyleng, 1, yyout)


二、开始第一个例子

   环境说明:

          VMware Workstation 12 Pro, ubuntu17.04 ,lex2.6.1

    输出文件的内容并且在前面增加行号

   lineno.l

   

%{ 
    int yylineno;
%}
%%
^(.*)\n printf("%4d\t%s",  ++yylineno, yytext);
%%
int main(int argc, char *argv[])
{ 
    FILE *fp = NULL;
    if (argc == 2) {
      fp = fopen(argv[1], "r");
      if (NULL != fp) {
         yyin = fp;  
      } 
    }  
     
    yylex();
    
    if (NULL != fp) { 
       fclose(fp); 
    }
    
    return 0;
}


 使用lex将lineno.l文件转换为.c文件

  $ lex lineno.l
  $ls
  lex.yy.c lineno.l

   使用gcc 将lex.yy.c编译成可执行文件

   $ gcc lex.yy.c -o lineno

    /tmp/ccNgesbZ.o:在函数‘yylex’中:
    lex.yy.c:(.text+0x55c):对‘yywrap’未定义的引用
    /tmp/ccNgesbZ.o:在函数‘input’中:
    lex.yy.c:(.text+0x116c):对‘yywrap’未定义的引用
    collect2: error: ld returned 1 exit status

    网上查询说是要在.l文件中实现yywrap函数

    修改后:

%{   
  int yylineno;
%}
%%
^(.*)\n printf("%4d\t%s",  ++yylineno, yytext);
%%
int main(int argc, char *argv[])
{    
     FILE *fp = NULL;
     yylineno = 0; 
     
     if (argc == 2) {    
         fp = fopen(argv[1], "r");    
         if (NULL != fp) {   
            yyin = fp;   
          }   
      }   
        
      yylex();  
      
      if (NULL != fp) {    
          fclose(fp);  
      }   
      
     return 0;
}

int yywrap()
{ 
    return 1;
}

再次编译成功

$gcc lex.yy.c -o lineno
$lineno lineno.l

  1    %{
   2            int yylineno;
   3    %}
   4
   5    %%
   6    ^(.*)\n printf("%4d\t%s",  ++yylineno, yytext);
   7    %%
   8
   9    int main(int argc, char *argv[])
  10    {
  11            FILE *fp = NULL;
  12            yylineno = 0;
  13
  14            if (argc == 2) {
  15                    fp = fopen(argv[1], "r");
  16                    if (NULL != fp) {
  17                            yyin = fp;
  18                    }
  19            }
  20
  21            yylex();
  22
  23            if (NULL != fp) {
  24                    fclose(fp);
  25            }
  26
  27            return 0;
  28    }
  29
  30    int yywrap()
  31    {
  32            return 1;

  33    }

初识 lex

标签:lex

原文地址:http://blog.51cto.com/happytree007/2052238

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!