设计一个小语言的词法分析程序

设计一个小语言的词法分析程序,第1张

任务1:识别小型语言所有单词词法分析程序设计

源程序设计语言 G[<程序>]

<程序>→<变量说明><BEGIN><语句表><END>.

<变量说明>→VAR<变量表>:<类型>;|<空>

<变量表>→<变量表>,<变量>|<变量>

<类型>→INTEGER

<语句表>→<语句>| <语句><语句表>

<语句>→<赋值语句>|<条件语句>|<WHILE语句>|<复合语句>

<赋值语句>→<变量>:=<算术表达式>

<条件语句>→IF<关系表达式>THEN<语句>ELSE<语句>

<WHILE语句>→WHILE<关系表达式>DO<语句>

<复合语句>→BEGIN<语句表>END

<算术表达式>→<项>|<算术表达式>+<项>|<算术表达式>-<项>

<项>→<因式>|<项>*<因式>|<项>/<因式>

<因式>→<变量>|<整数>|(<算术表达式>)

<关系表达式>→<算术表达式><关系符><算术表达式>

<变量>→<标识符>

<标识符>→<标识符><字母>|<标识符><数字>|<字母>

<整数>→0|<非零数字><泛整数>

<泛整数>→<数字>|<数字><泛整数>|ε

<关系符>→<|<=|==|>|>=|<>

<字母>

→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z

<非零数字>→1|2|3|4|5|6|7|8|9

<数字>→<非零数字>|0

<空>→

要求和提示:

词法分析阶段,可以打开任意位置和名称的源文件进行词法分析,可以进行非法字符和数字后边跟字母的错误判断,如果没有错误则提示“词法分析正确完成!”,并且可以选择输出token.txt(token文件)string.txt(符号表)两个文件;

1.词法分析程序的主要任务如下:

① 组织源程序的输入,识别出源程序中的各个基本语法单位(也称为单词或语法符号),按规则转换成二元式的形式;

② 删除无用的空白字符、回车符、及其它非实质性符号;

③ 删除注解行;

④ 为后面的语法和语义分析提供二元式链表;

单词 编码 单词 编码

标识符 1 <15

正整数 2 <= 16

BEGIN 3 >17

END 4 >= 18

IF 5 <>19

THEN 6 == 20

ELSE 7 ; 21

WHILE 8 . 22

DO 9 := 23

INTEGER 10 , 24

+ 11 ( 25

- 12 ) 26

* 13

/ 14

1) 对标识符的长度控制在8个字符(包括8个)以内,超过的做截断处理;

2) 数字不大于65535,否则报错;

3) 能跳过源程序中的空白格:两个单词之间的任何空格,制表符,回车,换行都是白空格,除了用来分隔单词以外,没有意义;

4) 能跳过注释:

a) 接连出现的/*到下一次接连出现的*/之间的任何文字都是注释(多行);

b) 从某行接连出现的//到该行的结尾的任何文字都是注释(单行)。

3.怎样编写词法分析程序:

1) 预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除注释,删除多余的白空格;

2) 从源程序字符数组中获得单词, 编码为二元式.:

二元式采用结构体数组存储, 把单词类型和词元记录下来。

分解单词的方法:

1) Case多路转换语句根据单词的特点直接编写;

2) 通过描述单词的正规文法得到相应的有穷自动机,通过case多路转换语句完成有穷自动机的处理流程。

3.编写词法分析程序要注意的问题:

1) 检查词法是否有错误

检查是否有非法字符:如 @, &, !

检查标志符和数字是否满足限制条件

检查注释符号是否配对

2) 符分隔单词

能够区分两个单词的符号为界符

有些界符不是单词:如白空格

有些界符仅仅用来分隔:如;

有些界符本身还是源程序不可缺少的单词,如(, ), +, /, 等等

有些界符包含两个字符:如<>, >=等等

3) 输出词法错误

如果有错误,需要报告词法错误的原因。并且要能够越过错误,分解下一个单词,直到源程序结束。

4) 输出的二元式流保存在二元式结构体数组中。

你好,希望采纳!

嘿嘿,这个我做过哦。是编译原理的东西。

不过现在没有程序,没带来,给你一个参考的:虽然不是完全符合你的要求。不过其中很多函数你是要用到的,比如词法分析部分,其实你的要求就是进行词法分析的,无非你用scanf(),你用词法分析,分析出scanf()语句,再进行内部参数分析,就OK了;

祝你成功哦

///////////////////////////////////////////////////////////////////

for循环语句翻译 递归下降法 输出三地址码 /////////////

#define MAX 100

#include<iostream.h>

#include<stdio.h>

#include<string.h>

char str[MAX]

char ch

int turn

char strToken[MAX]

int kind

int n=0//存放strtoken[]元素的个数

struct Word//结构体 存放单词

{

int sort

char word[MAX]//存放strtoken[]的内容

}

//record[x]=new Word

Word *record[12]//放所有识别出来的单词,分别存放他们的编号以及字符串,x是其下标

////////////////////词法分析///////////////////////

int buffer()//载入

{

int i=0

cout<<"输入程序,以“#”作为结束标志。"<<endl

for(int n=0n<=MAXn++)

{

for(i<=MAXi++)

{

scanf("%c",&str[i])

/////////////cin>>str[i]不可用,用C语言读入字符。

if(str[i]=='#')

break///////如果尾数为识别码#,则表示程序读完,跳出循环.

}

break

}

return(i)

}

bool IsLetter(char ch)///////////判断是否是字母

{

if(ch>=65&&ch<=90||ch>=97&&ch<=122)

return(true)

else

return(false)

}

bool IsDigit(char ch)//////////判断是否是数字

{

if(ch>=48&&ch<=57)

return(true)

else

return(false)

}

char GetChar(int i)///////读取字符

{

char ch

ch=str[i]

return(ch)

}

char GetBC(char ch)////判断是不是空格或者换行,如果是,直接读取下一个字符直道不再空白为止

{

if(ch==32||ch==10)

{

turn++

ch=GetChar(turn)

ch=GetBC(ch)/////////递归实现

return(ch)

}

else

return(ch)

}

void Concat()/////////////连接,即为strtoken[]赋值

{

strToken[n]=ch

n++

}

int Reserve()/////以单词为单位查找保留字,是则返回编码,不是则返回0,用来区分标志符和保留字

{

if(strcmp(strToken," DIM\0")==0)///////调用strcmp函数实现,

return(1)

else if(strcmp(strToken,"for\0")==0)

return(2)

else if(strcmp(strToken,"step\0")==0)

return(3)

else if(strcmp(strToken,"until\0")==0)

return(4)

else if(strcmp(strToken,"do\0")==0)

return(5)

else

return(6)

}

void clear()

{

n=0

}

/////////////*语法递归分析*/////////////////

int A(int * c,int &q)

{

if(c[q++]==3)

{

if(c[q]==7)

{ q++

return 1

}

else {cout<<"step右部出错"<<endlreturn 0}

}else {cout<<"error 'step'"<<endlreturn 0}

}

int B(int * b,int &o)

{

if(b[o++]==4)

{

if(b[o]==7)

{ o++

return 1

}

else {cout<<"until右部出错"<<endlreturn 0}

}else {cout<<"error 'until'"<<endlreturn 0}

}

int S2(int * d,int &h)

{

if(d[h++]==6)

{

if(d[h++]==8)

{

if((d[h]==6||d[h]==7)) {h++return 1}

else {cout<<"赋值语句右部出错 "<<endlreturn 0}

}else {cout<<"赋值语句缺少赋值运算符 "<<endlreturn 0}

}else {cout<<"赋值语句左部出错 "<<endlreturn 0}

}

int S1(int * m,int &n)

{

if(S2(m,n))

{

if(A(m,n))

{

if(B(m,n)) return 1

else return 0

}else return 0

}else return 0

}

int S(int *a,int &z)

{

if (a[z++]==2)

{

if (S1(a,z))

{

if(a[z++]==5)

{

if(S2(a,z))

{

cout<<"succeed!"<<endlreturn 1

}else return 0

}else {cout<<"error 'do'"<<endlreturn 0}

}else return 0

}else {cout<<"error 'for'"<<endlreturn 0}

}

void main()

{

cout<<"*************产生式***************"<<endl// for step until do i j =

cout<<" S ->for S1 do S2"<<endl// 编号 2 3 4 5 6 7 8

cout<<" S1 ->S2AB"<<endl

cout<<" S2 ->i=j"<<endl

cout<<" A ->stepj"<<endl

cout<<" B ->untilj"<<endl

int num

turn=0

num=buffer()-1

int x=0//计识别的单词的个数

for(turn<=numturn++)//总循环,ch存放刚读入的字符,strtoken[]存放已识别的标志付或保留字,turn是数组str[]的下标

{

ch=GetChar(turn)

ch=GetBC(ch)

if(IsLetter(ch))

{

while(IsLetter(ch)&&turn<=num||IsDigit(ch)&&turn<=num)

{

Concat()

ch=GetChar(++turn)

}

strToken[n]='\0'

ch=NULL//此ch不是标志符中的符号

turn=turn-1

kind=Reserve()

record[x]=new Wordrecord[x]->sort=kind//12345或6

//cout<<kind//测试

cout<<"("

for(int i=0i<ni++)

{

record[x]->word[i]=strToken[i]

cout<<record[x]->word[i]//输出识别的标志符或保留字

}

cout<<","<<kind<<")"<<endl

record[x]->word[i]='\0'

clear()

x++

}

else if(IsDigit(ch))

{

while(IsDigit(ch)&&turn<=num)

{

Concat()

ch=GetChar(++turn)

}

ch=NULL

turn=turn-1

kind=7

//////////////

record[x]=new Word

record[x]->sort=kind

////////////////

cout<<"("

for(int i=0i<ni++)

{

record[x]->word[i]=strToken[i]

cout<<record[x]->word[i]

}

cout<<","<<kind<<")"<<endl

record[x]->word[i]='\0'

clear()x++

}

else if(ch=='=')

{

kind=8

///////

record[x]=new Word

record[x]->word[0]='='

record[x++]->sort=kind

cout<<"(=,"<<kind<<")"<<endl

}

else

cout<<"error input!"<<endl

}

//////////////////////*语法分析*////////////////

//int y

/*for(y=0y<xy++)

{cout<<record[y]->sort<<" "//打印单词的编号 。

}cout<<endl*/

int ana[MAX]//存放词法分析得到的单词序列的编号的序列

int m

for(m=0m<xm++)

{

ana[m]=record[m]->sort//将sort作为数组保存起来

}

/////////语法分析///////

int j=0

///////////////////制导翻译//////////////////

if(!S(ana,j)) cout<<"语法出错!"<<endl

else

{ cout<<"三地址码如下:"<<endl

cout<<"100 "

int i=0

while(record[1]->word[i]!='\0')

cout<<record[1]->word[i++]cout<<record[2]->word[0]

i=0

while(record[3]->word[i]!='\0')

cout<<record[3]->word[i++]cout<<endl

cout<<"101 goto 103"<<endl

cout<<"102 "

i=0

while(record[1]->word[i]!='\0')

cout<<record[1]->word[i++]cout<<":="

i=0

while(record[1]->word[i]!='\0')

cout<<record[1]->word[i++]cout<<"+"

i=0

while(record[5]->word[i]!='\0')

cout<<record[5]->word[i++]cout<<endl

cout<<"103 if "

i=0

while(record[1]->word[i]!='\0')

cout<<record[1]->word[i++]cout<<"<"

i=0

while(record[7]->word[i]!='\0')

cout<<record[7]->word[i++]

cout<<" goto 105"<<endl

cout<<"104 goto 107"<<endl

cout<<"105 "

i=0

while(record[9]->word[i]!='\0')

cout<<record[9]->word[i++]cout<<":="

i=0

while(record[11]->word[i]!='\0')

cout<<record[11]->word[i++]cout<<endl

cout<<"106 goto 102"<<endl

cout<<"107 end"<<endl

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7829658.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存