博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
词法分析器模拟
阅读量:5030 次
发布时间:2019-06-12

本文共 5045 字,大约阅读时间需要 16 分钟。

模拟词法分析器,把读入的字符串,识别为一个个词法单元并输出。

对应语言关键字 else if int return void while

专用符号  + - * / < <= > >= == != = ; , ( ) [ ] { } /* */

首先理清思路:需要做什么?

1 从输入文件读取字符 。

2 识别字符,这个识别过程应该是循环的。

3 输出识别结果。

------------------------------------------------------

怎么读:词法分析需要我们一个一个的读入字符

这里使用fgetc(FILE*file)函数。

-----------------------------------------------------

怎么识别:对接收的字符进行处理,这里需要识别

的结果有:数字,操作符,标识符,函数名,保留字,

注释,不能识别。这些可以存在一个字符型指针数组中。

如何开始识别数字:读入一个 '0'~‘9’之间的字符

如何开始识别操作符,标识符,函数名,保留字,注释,

读入一个字母,如果这个字母是'/',开始识别注释,如果是

操作符中的字符,那么开始识别操作符,如果是其他,开始识别

标识符与函数名。

------------------------------------------------------

怎么输出,这里使用格式:<RESERVED,INT>

在文件中输出用 fprintf(FILE*file,s)

-----------------------------------------------------

打印部分代码:

void console_print(int i,int start_pos,int end_pos){       cout<<"<"<
<<","; fprintf(output,"%c%s%c","<",token[i],","); int length=end_pos-start_pos; //识别的串的长度 fseek(input,-length,1); //fseek(input,start_pos,0); //移动位置太多 /********************** 要打印识别的串,首先要把 读取文本的文件指针的位置 回退到,串的开始位置。 source:文件指针 length:移动偏移,负数为 向左偏移 1:此部分有三个参数可选 0:从文件的开始位置移动 1:从文件的当前位置移动 2:从文件的结束位置移动 **********************/ char temp; for(int j=start_pos;j
",'/n'); cout<<">"<
/**********************************************fucntion:    file_print(int i,int start_pos,int end_pos)    parameter:     @i:在字符指针数组中的索引,代表识别的类型      @start_pos: 要打印的串在文件中的开始位置     @end_pos:   要打印的串在文件中的结束位置      usage:    在文件中打印识别的串 format:    打印样例:
分开打印会存在问题,当调用cosole_print后,又要重新调整文件指针,较为麻烦 写完之后发现,又注释掉,把此部分合道cosole_print中 void file_print(int i,int start_pos,int end_pos){ int length=end_pos=start_pos; //写完代码测试发现出错,应为减号 fseek(input,-length,1); fprintf(output,"<%s, ",token[i]); for(int j=start_pos;j
\n");}

在get_number()中调用,打印

console_print(i,start_pos,end_pos);file_print(i,start_pos,end_pos);

这样存在的问题是,当调用console_print后,文件的指针与最初调用console时原来相比又有变化,

在file_print时,需要重新改动代码,如果是与console_print中一样的计算方法,就会出现问题,

为简单方便,直接把file_print()中的代码中合并到console_print()中。

get_comment()识别注释

void get_comment(char ch){        start_pos=ftell(input)-1;  //记录开始位置    state=0;        while(!feof(input)){        //若基于读入的字符分类,则比较麻烦        //需要回吐字符判断        switch(state){            case 0:                state=1;                ch=fgetc(input);                            break;            case 1:                if(ch=='*'){                                state=2;                ch=fgetc(input);                }                else    //紧跟着'/'的不是'*'说明不是注释 ,根据定义只能是操作符                 {                        if(ch=='\n')                    fseek(input,-2,1);                    else                    fseek(input,-1,1);  //回退一个字符到结束位置 ,打印操作符 /                                         end_pos=ftell(input);                    console_print(1,start_pos,end_pos);                    file_print(1,start_pos,end_pos);                     return;                }                                break;            case 2:                if(ch=='`'){                    end_pos=ftell(input);                    console_print(3,start_pos,end_pos);                    file_print(3,start_pos,end_pos);                }  //程序读取时候遇到一点问题,这里加一个"`"作为技术符号                                 else if(ch=='/'){             //如果是'/'检查是否为注释的结束                     fseek(input,-2,1);  //回退到'/'前面的位置,检查是否为*                     char temp=fgetc(input);                                    //system("pause");                    if(temp=='*'){      //如果是则结束对注释的识别,打印注释部分                         fseek(input,1,1);                        end_pos=ftell(input);                         console_print(3,start_pos,end_pos);                        file_print(3,start_pos,end_pos);                                                return;                     }                    else{              //否则继续识别                         fseek(input,1,1);                        ch=fgetc(input);                                            }                }                                else{                    ch=fgetc(input);                }                            break;                            }     } }

这里起初用转化输入字符的方式,但是太麻烦,需要频繁的回吐字符,判断是否到达条件

因此用转换状态的方法。其次是在代码中有很多的选择结构,要注意文件指针的位置。

 

 get_id识别标识符(保留字,函数名,变量名)

void get_id(char ch){    start_pos=ftell(input)-1;    state=0;    int end=0;     while(!feof(input)){        if(!is_letter(ch)&&!is_number(ch)){            if(state==0){  //状态为0时,判断是否为保留字                                      if(ch=='\n')            fseek(input,-2,1);            else            fseek(input,-1,1);                        end_pos=ftell(input);            char s[100]="";            fseek(input,-(end_pos-start_pos),1);                        for(int i=0;i

 

遇到的问题:

(1)

while(!is_recognized(ch)){//读取到可以识别的字符的地方                 fgetc(input);            //    system("pause");  检查代码时用到             }

最初的部分代码是这样的,这里存在一个问题是,

识别一个不能识别的字符后,就不能结束while循环了。

 (2)

注意换行符\n的特殊性,在使用fgetc时,会把\n一块读

入,但文件指针向前移动两份位置。

转载于:https://www.cnblogs.com/qynx/p/8006347.html

你可能感兴趣的文章
Android权限 uses-permission
查看>>
NSEnumerator用法小结
查看>>
vim如何配置go语言环境
查看>>
机器学习好网站
查看>>
python 中的 sys , os 模块用法总结
查看>>
解题:国家集训队 Middle
查看>>
响应者链
查看>>
指针从函数内部带回返回值
查看>>
在使用webView播放flash或视频文件时无法关闭声音的问题
查看>>
redhat 7 源码安装 mysql5.5.49
查看>>
CCP浅谈
查看>>
NAT虚拟网络配置
查看>>
c#部分---需要实例化的内容;
查看>>
销售类
查看>>
技术项目,问题
查看>>
线程池总结
查看>>
Learning to rank (software, datasets)
查看>>
git常见问题
查看>>
.NETFramework:template
查看>>
HM16.0之帧内模式——xCheckRDCostIntra()函数
查看>>