您的位置:首页 > 其它

小白说编译原理-2-lex基本用法

2016-04-23 09:55 405 查看

lex词法分析器

概述

1,使用lex语言书写一套正规表达式的规则,命名为lex.l

2,由lex编译器负责将lex.l编译为lex.h和lex.cpp,这两个文件包含了lex定义的规则

3,再使用标准的c++编译器即可以将lex.cpp编译生成可执行程序lex.exe

4,lex.exe识别输入流,并将其转换为字符序列,并执行相应的操作(在lex.l中定义)

lex样例

%{
/***/
%}

// lexical analyser name
%name lexer

%%
[ \t]+ {printf(" ");}
\n|.    {printf("%s", yytext);}
%%

int main()
{
//create a lexer, and call the lex function.
//it will read from stdin and parser the tokens.
YYLEXERNAME lexer;
if(lexer.yycreate()){
lexer.yylex();
}
}


简单的语法结构

声明段:

%{
c++语言代码,一般为头文件包含,以及变量声明,定义。
注意:代码会被原样copy到生成的代码文件中。
%}
正规定义


规则段:

%%
用户定义的转换规则
P1 {action}
P1表示正规表达式,action为相应的执行动作。
%%


子程序段:

主要包含用户子程序代码,代码会被原样copy到生成的代码文件中。


解析说明例子

%name lexer

这是说明词法分析器的类名字为lexer,最后生成的代码中会有 #define YYLEXERNAME lexer。

[ \t]+ {printf(” “);}

前面是表达式,后面{}中是进行的动作。 [ \t]+表示连续的空白字符(空格,tab), 进行的语义动作是打印一个空格。

\n|. {printf(“%s”, yytext);}

其他任意字符,原样打印。因为.无法表达\n这样的字符,所以使用|的或操作。

功能说明

将连续的空格或者tab压缩为一个空格,其他字符原样输出。

lex样例2,解析token

%{
#include <iostream>
using namespace std;
enum{
LT,  EQ, GT, IF, ELSE, ID, NUMBER, PLUS, MINUS, TIMES, OVER, INT, DOUBLE,CHAR
};
const char* tokenStr[] = {"LT",  "EQ", "GT", "IF", "ELSE", "ID", "NUMBER", "PLUS", "MINUS", "TIMES", "OVER", "INT", "DOUBLE","CHAR"
};
static void print_token(int token, char* lex);

%}

%name lexer

delim [ \t\n]
ws    {delim}+
letter [a-zA-Z]
digit [0-9]
id    {letter}({letter}|{digit})*
/* can support 12.34 */
number {digit}+(\.{digit}+)?

%%
{ws} {/* do nothing */}
"int"  {print_token(INT, yytext);}
"double"  {print_token(DOUBLE, yytext);}
"char"  {print_token(CHAR, yytext);}

"+"         {print_token(PLUS, yytext); }
"-"         {print_token(MINUS, yytext);}
"*"         {print_token(TIMES, yytext);}
"/"         {print_token(OVER, yytext); }
{id}        {print_token(ID, yytext);}
{number}    {print_token(NUMBER, yytext);}
%%

static void print_token(int token, char* lex)
{
cout<<"token:" << tokenStr[token]<<" "<<"lex:"<<lex<<endl;
}

int main()
{
//create a lexer, and call the lex function.
//it will read from stdin and parser the tokens.
YYLEXERNAME lexer;
if(lexer.yycreate()){
lexer.yylex();
}
}


样例2说明

最前面的%{ … %}内的为变量以及函数声明部分

%name lexer 定义词法分析器的名字

delim [ \t\n] 这些是正规的定义,通过递归的定义可以定义更复杂的正规式,例如id和number的定义

%% … %% 正规表达式与执行的动作的绑定

最后的函数实现代码为整个驱动程序,它读取用户输入,并解析token,执行action

下节内容

yacc语法程序,能够实现一个简单的四则运算。

本人lpstudy,转载请注明出处: http://blog.csdn.net/lpstudy/article/details/51224869
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: