自制脚本语言(4) 自动生成的词法分析器

本文介绍了如何设计和实现词法分析器,通过读取正则表达式生成NFA和DFA,实现从文本文档中按符号分割的词法分析功能。重点讨论了保留字、正则表达式和运算符的处理,并详细描述了NFA到DFA的转换过程。文章末尾提到了未来优化的方向,包括支持更复杂正则、NFA子集查找以及编译器相关组件的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要:设计并实现了词法分析器。读取文件中的正则表达式及其相匹配的符号,生成由NFA到DFA转移表,最终得到表格驱动的词法分析器。

  词法分析器是根据一个符号表分析文本文档。符号表中有两种符号,一种是保留字,例如if、else这类,还有一种是正则表达式,例如整型和浮点型数字、普通的变量名等。词法分析器的功能就是读取原始的文本文档,将其按照符号定义分割为符号的序列。那么对外提供一个接口getToken(),每次调用,返回一个已分析的符号。整个文档分析完成后,需要有个“EOF”符号。

  getToken( )的过程是读取字符,与DFA确定型有限自动机进行匹配,当遇到空格或换行时,自动机刚好是结束状态,则返回相应的符号。这里面有几个要注意的点。通常来讲,这个过程是按照正则表达式,先构建NFA,然后生成DFA。但有几个点稍微要注意。一是正则表达式无非是数字、变量名,保留字、运算符都是确定的字符串。那么,对确定的字符串就没必要生成NFA,可以直接生成DFA。二是运算符往往跟数字和变量名、保留字之间都没有空格分开。那么,就要自动将运算符和数字、变量名、保留字分割。

  这里设计的几个类,首先最基本的表示自动机的NFA_State与DFA_State。其次要有表示正则表达式的RegexPattern与普通保留字的ReservedWord。最后,有个RegexParser来分析正则表达式生成NFA。

class NFA_State:
	HashMap<Character,HashSet<NFA_State>> nfa_edges		//字符转移的路径
	HashSet<NFA_State> e_edges                              //e转移的路径
class DFA_State:
	HashMap<Character,DFA_State> dfa_edges			//字符转移的路径
class RegexPaser:	
	String rule;						//要解析的正则表达式String
	NFA_State pars
实验二 词法分析器 一、实验目的 掌握词法分析器的构造原理,掌握手工编程或LEX编程方法之一。 二、实验内容 编写一个LEX源程序,使之生成一个词法分析器,能够输入的源程序转换为单词序列输出。 三、实验环境 Flex+VC6.0 四、实验注意 1.Id正则表达式:{letter}({letter}|{digit})* 2.Num正则表达式:{digit}+(\.{digit}+)?(E[+-]?{digit}+)? 3.注释:(\/\*(.)*\*\/) 4.关键字再加上其他字符就又能编程id,所以在词法分析时,id的判断应该放在关键字前面,这样才不会误判 5.由于本程序知识简单的打印数字,因此没有考虑数字的转换 6.">="比">"多一个字符,它应该放在前面判断,其他类似的也应该如此安排 五、实验代码 ******************************************************************************* 实验文件:lex.l、lex.yy.c 实验结果:lex.exe 运行方式:打开lex.exe,弹出input.txt,在其中输入所要测试的程序,保存并关闭,即可在output.txt中看到所得结果 ******************************************************************************* %{ void Install(char *type); %} %option noyywrap delim [ \t] newline [\n] digit [0-9] num {digit}+(\.{digit}+)?(E[+-]?{digit}+)? letter [A-Za-z] id {letter}({letter}|{digit})* key ("if"|"while"|"do"|"break"|"true") basic ("int"|"float"|"bool"|"char") op (">="|""|"<"|"="|"!="|"+"|"-"|"*"|"/") comment (\/\*(.)*\*\/) %% delim {;} newline {printf("\n");} {num} {Install("Num");} {key} {Install("Key");} {basic} {Install("Basic");} {op} {Install("Op");} ";" {Install("Comma");} {id} {Install("ID");} {comment} {Install("Comment");} "(" | "[" | "{" {Install("lbracket");} ")" | "]" | "}" {Install("rbracket");} %% void Install(char *s) { fprintf(yyout, "%s:%s ", s, yytext); } int main() { printf("please input the test program in input.txt\n"); system("input.txt"); yyin = fopen("input.txt", "r"); yyout = fopen("output.txt", "w" ); yylex(); fclose(yyout); fclose(yyin); printf("analysis result in output.txt\n"); system("output.txt"); return 0; } 六、实验小结 本次的实验由于使用了flex,所以代码较短,麻烦的事flex的正则式表达,由于该使用规则只有简单介绍,而网上找的教程难免有比重就轻之嫌,所以得到上述表达式着实费力,且有的没有成功,例如bracket的(\ ((.)*\ ))或者("("(.)*")")使用时都没有成功,所以便单独写出,有点不伦不类。至于其他的,都较为简单,完。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值