时间:2012-10-30 晚
要求:输入一串字符串,对其进行词法分析,并且按照(<种别>,<字符串/数字>)格式进行输出
种别编码:
符号 种别 符号 种别 符号 种别
begin 1 + 13 <= 22
if 2 - 14 > 23
then 3 15 >= 24
while 4 / 16 = 25
do 5 : 17 ; 26
end 6 := 18 ( 27
l(l|d) 10 < 20 ) 28
数字① 11 <> 21 # 0
①数字的词法正规式如下:( +|-|ε ) dd(dd | ε)( e ( +|-|ε ) dd|ε)
ps:输入的字符串以“#”结尾
运行环境:VC++60
说明:搜索网上的资源,大部分的“数字”部分都是dd形式,但这次试验要求的是①形式,因而在数字部分做了很大努力。与dd形式的不同有三个地方——ch是数字时,ch是+后接着是数字形式,ch是-后接着是数字形式。然而由于水平有限,时间较短,每个“加号”或“减号”后必须要在输入数字正负符号,否则会默认“+”“-”为正负符号而不是“加号”“减号”。希望能有简单方法解决这个问题。
源代码:
#include <stdioh> //定义I/O库所用的某些宏和变量
#include <stringh> //定义字符串库函数
#include <mathh> //定义数学运算符号库函数
char prog[80],token[8]; //prog:缓冲区;token:一个有意义的字符串
char ch; //ch:当前处理的字符
int syn,p,m,n,f,e;
//syn:类别;p,m,n:计数变量;f,标记数字正负;e,10的次方数
double sum; //sum,数字
char rwtab[6]={"begin","if","then","while","do","end"};
//基本字表置初值
void main(void) //主函数
{
void scaner(void); //声明函数
p=0;
printf("\n请输入字符串:\n");
do{ //输入的字符放入缓冲区
ch=getchar();
prog[p++]=ch;
}while(ch!='#');
p=0;
do{ //分析词法并输出结果
scaner();
switch(syn)
{
case 11:printf("(%2d,%16g)\n",syn,sum);break;
case -1:printf("输入错误\n");break;
default:printf("(%2d,%16s)\n",syn,token);
}
}while(syn!=0);
}
void scaner(void)
{
for(n=0;n<8;n++) //token初始化
token[n]=NULL;
ch=prog[p++];
while(ch==' ') //如果取消空字符(目前空字符只包括空格)
ch=prog[p++];
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
//如果ch是字母字符
{
m=0;
while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
//如果ch是字母字符或数字字符
{
token[m++]=ch;
ch=prog[p++]; //读下一个字符
}
token[m++]='\0';
p--;
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1; //给出syn值
break;
}
}
else if(ch>='0'&&ch<='9') //数字(1)
{
sum=0;
while(ch>='0'&&ch<='9')
{
sum=sum10+ch-'0';
ch=prog[p++];
}
if(ch=='') //有小数点
{
e=-1;
ch=prog[p++];
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
sum=sum+(ch-'0')pow(10,e--);
ch=prog[p++];
}
}
}
if(ch=='e'||ch=='E') //有e
{
e=0,f=1;
ch=prog[p++];
if(ch=='+')
{
f=1;
ch=prog[p++];
}
else if(ch=='-')
{
f=-1;
ch=prog[p++];
}
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
e=e10+ch-'0';
ch=prog[p++];
}
}
e=ef;
sum=sumpow(10,e);
}
p--;
syn=11;
}
else switch(ch)
{
case '<':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='>') //<>
{
syn=21;
token[m++]=ch;
}
else if(ch=='=') //<=
{
syn=22;
token[m++]=ch;
}
else //<
{
syn=20;
p--;
}
break;
case '>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=') //>=
{
syn=24;
token[m++]=ch;
}
else //>
{
syn=23;
p--;
}
break;
case ':':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=') //:=
{
syn=18;
token[m++]=ch;
}
else //:
{
syn=17;
p--;
}
break;
case '+':
ch=prog[p++];
if(ch>='0'&&ch<='9') //数字(2)
{
sum=0;
while(ch>='0'&&ch<='9')
{
sum=sum10+ch-'0';
ch=prog[p++];
}
if(ch=='') //有小数点
{
e=-1;
ch=prog[p++];
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
sum=sum+(ch-'0')pow(10,e--);
ch=prog[p++];
}
}
}
if(ch=='e'||ch=='E') //有e
{
e=0,f=1;
ch=prog[p++];
if(ch=='+')
{
f=1;
ch=prog[p++];
}
else if(ch=='-')
{
f=-1;
ch=prog[p++];
}
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
e=e10+ch-'0';
ch=prog[p++];
}
}
e=ef;
sum=sumpow(10,e);
}
p--;
syn=11;
}
else //+
{
syn=13;
p--;
ch=prog[p-1];
token[0]=ch;
}
break;
case '-':
ch=prog[p++];
if(ch>='0'&&ch<='9') //数字(3)
{
sum=0;
while(ch>='0'&&ch<='9')
{
sum=sum10+ch-'0';
ch=prog[p++];
}
if(ch=='') //有小数点
{
e=-1;
ch=prog[p++];
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
sum=sum+(ch-'0')pow(10,e--);
ch=prog[p++];
}
}
}
if(ch=='e'||ch=='E') //有e
{
e=0,f=1;
ch=prog[p++];
if(ch=='+')
{
f=1;
ch=prog[p++];
}
else if(ch=='-')
{
f=-1;
ch=prog[p++];
}
if(ch>='0'&&ch<='9')
{
while(ch>='0'&&ch<='9')
{
e=e10+ch-'0';
ch=prog[p++];
}
}
e=ef;
sum=sumpow(10,e);
}
sum=-sum;
p--;
syn=11;
}
else //-
{
syn=13;
p--;
ch=prog[p-1];
token[0]=ch;
}
break;
case '': syn=15;token[0]=ch;break;
case '/': syn=16;token[0]=ch;break;
case '=': syn=25;token[0]=ch;break;
case ';': syn=26;token[0]=ch;break;
case '(': syn=27;token[0]=ch;break;
case ')': syn=28;token[0]=ch;break;
case '#': syn=0;token[0]=ch;break;
default: syn=-1;
}
}
试试吧
没有这种工具,标识每行代码的作用没有任何意义,还影响阅读。
就算标识你也是把每个函数的意思写上,有什么用呢?一查msdn比
你写的不清楚多了?
要标识你的逻辑,算法,作用。
编译原理语规则词规则同处于:规则主要识别单词,语主要识别单词组句
词析词析程序:
词析阶段编译程第阶段阶段任务左右字符字符读入源程序即构源程序字符流进行扫描根据构词规则识别单词(称单词符号或符号)词析程序实现任务词析程序使用lex等工具自
语析(Syntax analysis或Parsing)语析程序(Parser)
语析编译程逻辑阶段语析任务词析基础单词序列组合各类语短语程序语句表达式等等语析程序判断源程序结构否确源程序结构由文关文描述
语义析(Syntax analysis)
语义析编译程逻辑阶段 语义析任务结构确源程序进行文关性质审查, 进行类型审查语义析审查类型并报告错误:能表达式使用数组变量,赋值语句右端左端类型匹配
求出“男”生的语文成绩和。特别提醒:如果把
在编译原理中,语法规则和词法规则不同之处在于:规则主要识别单词,而语法主要识别多个单词组成的句子。
词法分析和词法分析程序:
词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。词法分析程序实现这个任务。词法分析程序可以使用lex等工具自动生成。
语法分析(Syntax analysis或Parsing)和语法分析程序(Parser)
语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等语法分析程序判断源程序在结构上是否正确源程序的结构由上下文无关文法描述
语义分析(Syntax analysis)
语义分析是编译过程的一个逻辑阶段 语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查, 进行类型审查语义分析将审查类型并报告错误:不能在表达式中使用一个数组变量,赋值语句的右端和左端的类型不匹配
token就是把程序的语句进行类似分词得到的单词。
它是下步语法分析的输入。
typedef struct Token
{
int label;
char name[buf];
int code;
}Token;
是一个结构体。
C语言中单词可以分为
保留字,就是int,while等。
标识符,例如int m;m就是标识符。
数字,有整数和小数
字符,+,-,,,;等字符,其中也包括++,--,!=等。
label应该标识token的类型。
name表示的就是程序中对应的字符序列。例如:int等。
最后code的意思,看不出来。。。,不过个人认为,上面的两项就可以表示
token的信息。
主要是类型和内容。
"int"|"else"|"return"|"void"|"if"|"while"
{Upper(yytext,yyleng);
printf("%d 行 %s reserved word\n ",lineno,yytext);
}
{num}
{
printf("%d 行 %s NUM\n",lineno,yytext);
}
","|";"|"("|")"|"{"|"}"|""|"/"|"+"|"-"|">"|"<"|">="|"<="|"=="|"!="|"="|"/"|"/"
{printf("%d 行 %s special symbol\n ",lineno,yytext);
}
{id}
{printf("%d 行 %s ID\n",lineno,yytext);
}
以上就是关于做一个简单的词法分析器, 一:要求能识别C程序中的部分关键字 int, char ,float if,else main, prin全部的内容,包括:做一个简单的词法分析器, 一:要求能识别C程序中的部分关键字 int, char ,float if,else main, prin、词法分析程序、编译原理中词法分析器的输入是单词符号串,为什么不是源程序这两者有什么区别等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)