前言
这个编译原理是一个系列,系列地址为: https://blog.csdn.net/lpstudy/article/category/937055
考虑到很多小伙伴咨询代码的问题,现把链接发出来:https://github.com/lpstudy/compile
这个链接里面具有这个系列所有的VS工程和代码,工程是按照系列中的一个教程环境配置6来配置的,不过lib我好像没有上传到github。
如果大家发现任何问题,可以在github或者csdn,我有空的时候完善一下,争取做到下载github工程即可跑。
#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
本文介绍了如何使用lex创建词法分析器,包括lex的基本用法、样例解析及功能说明。通过lex.l文件定义规则,lex编译器生成lex.h和lex.cpp,最终编译成可执行程序,实现对输入流的字符序列处理。

1万+

被折叠的 条评论
为什么被折叠?



