词法分析lex

1 分钟读完

本文不讲lex编程细节,主要是总结一下Lex能做什么,展现一下Lex和Yacc结合的威力,Lex编程技术可以参考《felx与bison(中文版)》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<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。

by geeksword

留下评论