IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    词法分析lex

    一根稻草发表于 2015-01-21 00:00:00
    love 0

    本文不讲lex编程细节,主要是总结一下Lex能做什么,展现一下Lex和Yacc结合的威力,Lex编程技术可以参考《felx与bison(中文版)》和lex&yacc;学习资料。

    目录

    • lex是什么
    • lex能做什么
    • 实例——读取配置文件
    • lex&yacc;学习资料

    lex是什么

    Lex is a computer program that generates lexical analyzers ("scanners" or "lexers"). Lex reads an input stream specifying the lexical analyzer and outputs source code implementing the lexer in the C programming language.——维基百科)

    Lex程序能够生成词法分析器(C代码),词法分析是编译器进行编译的第一个操作步骤。

    lexical analysis is the process of converting a sequence of characters into a sequence of tokens, i.e. meaningful character strings. ——维基百科

    lex能做什么

    除了写编译器之外,Lex还能做:

    1. 读取配置文件
    2. 做文本解析
    3. 高级计算器(可以自定义函数)
    4. 解析sql语句

    实例

    用纯Lex生成一个C程序,用来读取配置文件,可以添加注释,解析不规整的配置语句。
    源文件: config.h,config.l,test_cfg.c

    config.h

    #ifndef _CONFIG_H
    #define _CONFIG_H
    
    #include
    #include
    
    typedef struct config_item{
        char *name;
        char *value;
        struct config_item *next;
    }ConfigItem;
    
    //API
    
    void init_config(const char *cfg_file);
    void free_config();
    char* get_item(const char *name);
    
    #endif
    

    config.l

    %option noyywrap case-insensitive
    
    %{
    #include"config.h"
    ConfigItem *ConfigTable = NULL;
    ConfigItem *cItem = NULL;
    char flag = 0;
    %}
    
    %%
    ^[#].*  {
        //printf("ignore...\n");    
    }   
    =       {   
        flag = 1;   
        //printf("equal\n");    
    }
    ([\x20-\x7e]{-}[ \r\t\v\f\n=])+ {
    //  printf("another line\n");
        if(cItem && flag){
            cItem->value = strdup(yytext);
            cItem->value[strlen(cItem->value)] = '\0';
            flag = 0;
        }
        else{
            cItem = (ConfigItem*)malloc(sizeof(ConfigItem));
            cItem->name = strdup(yytext);
            cItem->value = NULL;
            if(ConfigTable){
                cItem->next = ConfigTable->next;
                ConfigTable->next = cItem;
            }
            else{
                ConfigTable = cItem;
            }
        }
    }
    .   {   
        //printf("no match\n"); 
    }
    %%
    
    void init_config(const char *cfg_file)
    {
        yyin = fopen(cfg_file, "r");
        yylex();
    }
    void free_config()
    {
        ConfigItem *p;
        p = ConfigTable; 
        while(p)
        {
            cItem = p->next;
            free(p);
            p = cItem;
        }
    }
    char* get_item(const char *name)
    {
        for(cItem = ConfigTable; cItem; cItem = cItem->next)
        {
            if(strcmp(name, cItem->name)==0)
            {
                return strdup(cItem->value);
            }
        }
        return NULL;
    }
    /*
    int main()
    {
        yylex();
        for(cItem = ConfigTable; cItem; cItem = cItem->next)
        {
            printf("%s -> %s\n", cItem->name, cItem->value);
        }
        return 0;
    }
    */
    

    test_cfg.c

    #include"config.h"
    
    void _test(const char *name)
    {
    
        char *value;
        value = get_item(name);
        if(!value){
            printf("%s not found\n", name);
            return;
        }
        printf("%s = %s\n", name, value);
        free(value);
    }
    
    void test_cfg(const char *cfg)
    {
        init_config(cfg);   
        _test("platform");
        _test("username");
        _test("password");
        _test("database");
        _test("admin");
        free_config();
    }
    
    int main(int argc, char *argv[])
    {
        test_cfg(argv[1]);
        return 0;
    }
    

    编译

    flex config.l
    gcc config.h lex.yy.c test_cfg.c -o test

    测试文件zz.cfg

    
          #hello flex
          platform          =         ubuntu14
    
          #database login
          username     =onestraw
          password     =nizhidao
    
    
                 database=mysql=
    

    运行

    ./test zz.cfg

    lex&yacc;学习资料

    yacc (Yet Another Compiler Compiler)不是语法解析器,它根据BNF语法规则生成语法解析器(C代码),它是一个LALR语法解析器生成器(parser generator),LALR是look ahead from left to right。

    • 如何使用Lex/Yacc
    • Lex变量列表
    • http://dinosaur.compilertools.net/lex/index.html
    • http://www.ibm.com/developerworks/cn/linux/sdk/lex/

    by geeksword



沪ICP备19023445号-2号
友情链接