建材秒知道
登录
建材号 > 设计 > 正文

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

友好的黑裤
风趣的睫毛
2023-03-07 02:59:48

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

最佳答案
激昂的乌冬面
等待的奇异果
2025-09-16 21:06:46

任务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) 输出的二元式流保存在二元式结构体数组中。

你好,希望采纳!

最新回答
乐观的鱼
背后的百合
2025-09-16 21:06:46

#include "stdio.h"                  

#include "string.h"                 

#include "conio.h"                  

#include "ctype.h"                  

char prog[80]={'\0'},

token[8]                     

char ch

int syn,                           

n,

sum,                           

m,p                           

char *rwtab[6]={"begin","if","then","while","do","end"}

void scaner(){

m=0

sum=0

for(n=0n<8n++)

token[n]='\0'

ch=prog[p++]

while(ch==' ')

ch=prog[p++]

if(isalpha(ch))    {

while(isalpha(ch)||isdigit(ch))    {

token[m++]=ch

ch=prog[p++]}

token[m++]='\0'

ch=prog[p--]

syn=10

for(n=0n<6n++)

if(strcmp(token,rwtab[n])==0)    {

syn=n+1

break}}

else

if(isdigit(ch))    {

while(isdigit(ch))    {

sum=sum*10+ch-'0'

ch=prog[p++]}

ch=prog[p--]

syn=11}

else

switch(ch){

case'<':m=0token[m++]=chch=prog[p++]

if(ch=='>'){

syn=21

token[m++]=ch}

else if(ch=='='){

syn=22

token[m++]=ch}

else{

syn=20

ch=prog[p--]}

break

case'>':m=0token[m++]=chch=prog[p++]

if(ch=='='){

syn=24

token[m++]=ch}

else{

syn=23

ch=prog[p--]}

break

case':':m=0token[m++]=chch=prog[p++]

if(ch=='='){

syn=18

token[m++]=ch}

else{

syn=17

ch=prog[p--]}

break

case'+':syn=13token[0]=chbreak

case'-':syn=14token[0]=chbreak

case'*':syn=15token[0]=chbreak

case'/':syn=16token[0]=chbreak

case'=':syn=25token[0]=chbreak

case'':syn=26token[0]=chbreak

case'(':syn=27token[0]=chbreak

case')':syn=28token[0]=chbreak

case'#':syn=0token[0]=chbreak

default:syn=-1}}

main()

{

printf("\n\nThe significance of the figures:\n"

"1.figures 1 to 6 said Keyword\n"

"2.figures 10 and 11 said Other indicators\n"

"3.figures 13 to 28 said Operators\n")

p=0

printf("\nplease input string:\n")

do {

ch=getchar()

prog[p++]=ch

}while(ch!='#')

p=0

do{

scaner()

switch(syn){

case 11: printf("(%d,%d)\n",syn,sum)break

case -1: printf("\n ERROR\n")break

default: printf("(%d,%s)\n",syn,token)

}

}while(syn!=0)

getch()

}

程序测试结果

对源程序begin x:=9: if x>9 then x:=2*x+1/3 end #的源文件,经过词法分析后输出如下图5-1所示:

具体的你在修改修改吧

羞涩的蜗牛
笨笨的小鸭子
2025-09-16 21:06:46
#include <iostream>

#include <string>

using namespace std

string key[6] = {"begin", "if", "then", "while", "do", "end"}

//关键字

bool isKey( string str, int &syn) //判断是否为关键字,若是传回相

应关键码的种别名

{

int i

for(i=0i<6i++)

{

if(str == key[i])

{

syn = i + 1

return true

}

}

return false

}

bool isLetter(char c) //是否为字母

{

if((c >= 'A' &&c <= 'Z') || (c >= 'a' &&c <= 'z'))

return true

else

return false

}

bool isDigit(char c) //是否为数字

{

if(c >= '0' &&c <= '9')

return true

else

return false

}

void analyse(FILE *fileP)

{

int n

char c

string str = ""

while((c = fgetc(fileP)) != EOF)

{

if(c == ' ' || c == '\n' || c == '\t')

continue

else if(isDigit(c)) //数字

{

while(isDigit(c))

{

str += c

c = fgetc(fileP)

}

fseek(fileP, -1, SEEK_CUR)

cout <<"(11, " <<str <<")" <<endl

str = ""

}

else if(isLetter(c)) //字母开头的

{

while(isDigit(c) || isLetter(c))

{

str += c

c = fgetc(fileP)

}

fseek(fileP, -1, SEEK_CUR)

if(isKey(str, n))

cout <<"(" <<n <<", " <<str <<")" <<endl//关键码

else

cout <<"(10, " <<"\'"<<str <<"\'" <<")" <<endl//标志符

str = ""

}

else //操作符等

{

switch(c)

{

case '+':

cout <<"(13, +)" <<endl

break

case '-':

cout <<"(14, -)" <<endl

break

case '*':

cout <<"(15, *)" <<endl

break

case '/':

cout <<"(16, /)" <<endl

break

case ':':

{

if(c=fgetc(fileP) == '=')

cout <<"(18, :=)" <<endl

else

{

cout <<"(17, :)" <<endl

fseek(fileP, -1, SEEK_CUR)

}

break

}

case '<':

{

c=fgetc(fileP)

if(c == '=')

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

else if(c == '>')

cout <<"(21, <>)" <<endl

else

{

cout <<"(20, <)" <<endl

fseek(fileP, -1, SEEK_CUR)

}

break

}

case '>':

{

c=fgetc(fileP)

if(c == '=')

cout <<"(24, >=)" <<endl

else

{

cout <<"(23, >)" <<endl

fseek(fileP, -1, SEEK_CUR)

}

break

}

case '=':

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

break

case '':

cout <<"(26, )" <<endl

break

case '(':

cout <<"(27, ()" <<endl

break

case ')':

cout <<"(28, ))" <<endl

break

case '#':

cout <<"(0, #)" <<endl

break

}

}

}

}

int main()

{

FILE *fileP

fileP = fopen("test.txt", "r")

cout <<"------词法分析如下------" <<endl

analyse(fileP)

return 0

}

虚幻的大炮
激动的火龙果
2025-09-16 21:06:46
词法分析是把构成源程序的字符串转换成单词符号序列。词法规则可用 3型文法 (正规文法)或正规表达式描述,他产生的集合是语言基本字符集Σ(字母表)上的字符串的一个子集,称为正规集。

正规式是一种表示正规集的工具,正规式是描述程序语言单词的表达式,对于字母表Σ。

正规式(正规表达式)的运算符有3个,优化级从高到低顺序排列为:*(闭包)、·(连接,可省略)、|(或)。

正规式  →  正规集

ab  →  字符串ab构成的集合

a|b  →  字符串a、b构成的集合

a*  →  由0个或多个a构成的字符串集合

(a|b)*  →  所有字符a和b构成的串的集合

a(a|b)*  →  以a为首字符的a、b字符串的集合

(a|b)*abb  →  以abb结尾的a、b字符串的集合

有限自动机可以转换为正规式,正规式也可以转换为有限自动机。

词法分析器的构造步骤:

1)用正规式描述语言中的单词构成规则。

2)为每个正规式构造一个NFA,它识别正规式所表示的正规集。

3)将构造出的NFA转换成等价的DFA。

4)对DFA进行最小化处理,使其最简。

5)从DFA构造词法分析器。

可靠的星月
听话的豌豆
2025-09-16 21:06:46
#include <stdio.h>

#include <ctype.h>

#include <malloc.h>

#include <stdlib.h>

#include <string.h>

#define NULL 0

#define MAX_KEY_NUM 10

#define MAX_BORDER_NUM 6

#define MAX_ARITH_NUM 4

#define MAX_RELATION_NUM 6

#define MAX_CONSTS_NUM 20

#define MAX_LABEL_NUM 20

FILE *fp

char cbuffer

char *key[MAX_KEY_NUM]={"if","else","for","while","do","return","break","continue","main","int"}

char *border[MAX_BORDER_NUM]={",","","{","}","(",")"}

char *arithmetic[MAX_ARITH_NUM]={"+","-","*","/"}

char *relation[MAX_RELATION_NUM]={"<","<=","==",">=",">","="}

char *consts[MAX_CONSTS_NUM]

char *label[MAX_LABEL_NUM]

int constnum=0,labelnum=0

//===============================================

int search(char searchchar[],int wordtype)

{

int i=0

switch (wordtype) {

case 1:

for (i=0i<MAX_KEY_NUMi++)

{

if (strcmp(key[i],searchchar)==0)

return(i+1)

}

case 2:

{for (i=0i<MAX_BORDER_NUMi++)

{

if (strcmp(border[i],searchchar)==0)

return(i+1)

}

return(0)

}

case 3:

{for (i=0i<MAX_ARITH_NUMi++)

{

if (strcmp(arithmetic[i],searchchar)==0)

{

return(i+1)

}

}

return(0)

}

case 4:

{for (i=0i<MAX_RELATION_NUMi++)

{

if (strcmp(relation[i],searchchar)==0)

{

return(i+1)

}

}

return(0)

}

case 5:

{

for (i=0i<constnumi++)

{

if(constnum>0)

if (strcmp(consts[i],searchchar)==0)

{

return(i+1)

}

}

consts[i]=(char *)malloc(sizeof(searchchar))

strcpy(consts[i],searchchar)

constnum++

return(i)

}

case 6:

{

for (i=0i<labelnumi++)

{

if (strcmp(label[i],searchchar)==0)

{

return(i+1)

}

}

label[i]=(char *)malloc(sizeof(searchchar))

strcpy(label[i],searchchar)

labelnum++

return(i)

}

} // end of switch

}

//===============================================

char alphaprocess(char buffer)

{

int atype

int i=-1

char alphatp[20]

while ((isalpha(buffer))||(isdigit(buffer)))

{

alphatp[++i]=buffer

buffer=fgetc(fp)

}

alphatp[i+1]='\0'

if (atype=search(alphatp,1))

printf("%s (1,%d)\n",alphatp,atype)

else

{

atype=search(alphatp,6)

printf("%s (6,%d)\n",alphatp,atype)

}

return(buffer)

}

//===============================================

char digitprocess(char buffer)

{

int i=-1

char digittp[20]

int dtype

while ((isdigit(buffer)))

{

digittp[++i]=buffer

buffer=fgetc(fp)

}

digittp[i+1]='\0'

dtype=search(digittp,5)

printf("%s (5,%d)\n",digittp,dtype)

return(buffer)

}

//===============================================

char otherprocess(char buffer)

{

int i=-1

char othertp[20]

int otype,otypetp

othertp[0]=buffer

othertp[1]='\0'

if (otype=search(othertp,3))

{

printf("%s (3,%d)\n",othertp,otype-1)

buffer=fgetc(fp)

goto out

}

if (otype=search(othertp,4))

{

buffer=fgetc(fp)

othertp[1]=buffer

othertp[2]='\0'

if (otypetp=search(othertp,4))

{

printf("%s (4,%d)\n",othertp,otypetp-1)

goto out

}

else

othertp[1]='\0'

printf("%s (4,%d)\n",othertp,otype-1)

goto out

}

if (buffer==':')

{

buffer=fgetc(fp)

if (buffer=='=')

printf(":= (2,2)\n")

buffer=fgetc(fp)

goto out

}

else

{

if (otype=search(othertp,2))

{

printf("%s (2,%d)\n",othertp,otype-1)

buffer=fgetc(fp)

goto out

}

}

if ((buffer!='\n')&&(buffer!=' '))

printf("%c error,not a word\n",buffer)

buffer=fgetc(fp)

out: return(buffer)

}

//===============================================

void main()

{

int i

for (i=0i<=20i++)

{

label[i]=NULL

consts[i]=NULL

}

if ((fp=fopen("c:\example.c","r"))==NULL)

printf("error")

else

{

cbuffer = fgetc(fp)

while (cbuffer!=EOF)

{

if (isalpha(cbuffer))

cbuffer=alphaprocess(cbuffer)

else if (isdigit(cbuffer))

cbuffer=digitprocess(cbuffer)

else cbuffer=otherprocess(cbuffer)

}

printf("over\n")

getchar()

}

}

健康的背包
呆萌的小蚂蚁
2025-09-16 21:06:46
C语言词法分析器

#include<iostream>

#include<stdio.h>

#include<string>

using namespace std

FILE *f //定义一个文件变量

static int line = 1 //表示光标所在的行数

struct ID{ char *nameint count}id[100]//用于存放ID号码

static int I = 0//用于记录ID存放的数量

int Number[100]//用于存放数字

static int P = 0//用于记录存放数字的个数

int error[100] = {0} //用于记录错误所在的行数

static int K = 0//记录错误次数

void Error() //记录错误

void loginID(char *) //注册ID号

void loginNumber(int &)//记录数字

void noteLine(char &)//记录光标所在的行数

void print() //输出分析结果

int same(char *chr) //判断单词是否已经存在

void Error()

{ error[K++] = line}

void loginID(char *chr) //注册ID号

{

int k = 0

int h = 0

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

{

if(!strcmp(chr,id.name)) //如果单词已经存在

{

id.count++

k = 1

}

}

if(k == 0) //该单词不存在

{

h = I + 1

//I = h

id[h].count++

id[h].name = chr

//strcpy(id[h].name ,chr)

}

}

void loginNumber(int &nu)

{ Number[P++] = nu}

void noteLine(char &ch)

{

if ( ch == ' ' )

++line

}

void print()//输出部分

{

//cout <<"关键字以及变量:" <<endl

//for(int i = 0i <100i++)

//cout <<i <<" " <<id.name <<" " <<id.count <<endl

cout <<"数字:" <<endl

for(int i = 1i <= Pi++)

cout <<i <<": " <<Number[i-1] <<endl

if(error[0] != 0)

{

cout <<"出现的错误!" <<endl

for(int i = 1i <= Ki++)

cout <<"第" <<i <<"个错误: " <<"第" <<error[i-1] <<"行" <<endl

}

else cout <<"没有错误!" <<endl

}

//文件处理部分

void noblank( char &ch) //跳过空格,回车

{

noteLine(ch)

while(ch == ' ' || ch == ' ')

ch = fgetc(f)

}

void identifier(char name[],char &ch)//字母变量

{

int i

for(i = 0i <20i++)

name = ''

i = 0

while (('0'<= ch &&ch <= '9')||('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))

{

name = ch

i++

ch = fgetc(f)

}

loginID(name)

//for(int j = 0j <ij++)

//{cout <<name[j]}

// cout <<' '

}

int number(char &ch)//数字

{

int num=0

while('0'<= ch &&ch <= '9')

{

num = num* 10 + (ch-'0')

ch = fgetc(f)

}

if( ('a'<= ch&&ch <= 'z')||('A'<= ch&&ch <='Z'))

{

Error()

}

else if( ch == '.')

{}

loginNumber(num) //记录数字

return num

}

void test(char &ch)//符号

{

char str[2]={'0/'}

if(ch == '*')

{ str[0] = chch = fgetc(f)}

if(ch == '.')

{ str[0] = chch = fgetc(f)}

if(ch == ',')

{ str[0] = chch = fgetc(f)}

if(ch == '"')

{ str[0] = chch = fgetc(f)}

if(ch == '/')

{ str[0] = chch = fgetc(f)}

if(ch == '%')

{ str[0] = chch = fgetc(f)}

if(ch == '^')

{ str[0] = chch = fgetc(f)}

if(ch == '-')

{ str[0] = chch = fgetc(f)}

if(ch == '{')

{ str[0] = chch = fgetc(f)}

if(ch == '}')

{ str[0] = chch = fgetc(f)}

if(ch == '[')

{ str[0] = chch = fgetc(f)}

if(ch == ']')

{ str[0] = chch = fgetc(f)}

if(ch == '')

{str[0] = chch = fgetc(f)}

if(ch == ':')

{ str[0] = chch = fgetc(f)}

if(ch == '?')

{ str[0] = chch = fgetc(f)}

if(ch == '(')

{ str[0] = chch = fgetc(f)}

if(ch == ')')

{str[0] = chch = fgetc(f)}

if(ch =='+')

{

str[0] = ch

if((ch = fgetc(f)) == '+' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

//cout <<str[0]<<endl

}

if(ch == '-')

{

str[0] = ch

if((ch = fgetc(f)) == '-' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

//cout <<str[0]<<endl

}

if(ch == '&')

{

str[0] = ch

if((ch = fgetc(f)) == '&' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

//cout <<str[0]<<endl

}

if(ch == '|')

{

str[0] = ch

if((ch = fgetc(f)) == '|' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

//cout <<str[0]<<endl

}

if(ch == '!')

{

str[0] = ch

if((ch = fgetc(f)) == '=' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

//cout <<str[0]<<endl

}

if(ch == '=')

{

str[0] = ch

if((ch = fgetc(f)) == '=' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

}

if(ch == '>')

{

str[0] = ch

if((ch = fgetc(f)) == '=' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

else

if(ch == '>' )

{

str[1] = ch

ch = fgetc(f)

//cout <<str[0] <<str[1] <<endl

}

}

if(ch == '<')

{

str[0] = ch

if((ch = fgetc(f)) == '=' )

{

str[1] = ch

ch = fgetc(f)

}

else

if(ch == '<' )

{

str[1] = ch

ch = fgetc(f)

}

}

}

int main()

{

char ch

char name[30]

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

name = '/0'

f = fopen("c.txt","r") //打开指定输入文件

if (f == NULL)

cout<<"文件不存在!"<<endl

ch = fgetc(f)

while(!feof(f))

{

noblank( ch )//跳过回车,空格

if( ( ch >= 'a' &&ch <= 'z' )||( ch >= 'A' &&ch <= 'Z' ))

{ identifier(name,ch)} //处理字母

else if( ch >= '0'&&ch <= '9')

{ number(ch)} //处理数字

else

{ test(ch)} //处理符号

}

print() //打印词法分析结果

fclose(f) //关闭文件

system("pause")

return 0

}

忧伤的草莓
冷静的月饼
2025-09-16 21:06:46
编译原理IF条件语句的翻译程序设计—简单优先法、输出四元式通过设计、编制、调试一个条件语句的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。具体做到以下几点:①对输入语句进行词法分析。将输入的字符串进行扫描和分解,识别出一个个合法的单词。单词种类包括:关键字,标识符,运算符,常数和界限符②进行语法分析。编写条件语句的相应文法,按照语法分析方法中的简单优先分析法为文法设计简单优先表,对词法分析得到的单词序列进行语法分析,以判别输入的语句是否属于该文法的条件语句。③语法制导翻译。设计中间代码(四元式)序列的结构及属性文法,运用语法制导翻译,在进行语法分析的同时,执行相应的语义规则描述的动作,从而实现语义处理,生成中间代码以四元式的形式输出。④错误提示。对不同的错误给出简略描述,并终止程序的继续执行。下载地址如下,有你要的东西!pile.rar