词法分析lex
本文不讲lex编程细节,主要是总结一下Lex能做什么,展现一下Lex和Yacc结合的威力,Lex编程技术可以参考《felx与bison(中文版)》和lex&yacc学习资料。 ###目录
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还能做:
- 读取配置文件
- 做文本解析
- 高级计算器(可以自定义函数)
- 解析sql语句
##实例
用纯Lex生成一个C程序,用来读取配置文件,可以添加注释,解析不规整的配置语句。
源文件: config.h
,config.l
,test_cfg.c
config.h
#ifndef _CONFIG_H
#define _CONFIG_H
#include<stdio.h>
#include<stdlib.h>
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
留下评论