編譯原理詞法分析
/*
編譯原理實驗一:詞法分析練習
作者:lqf
時間:2013-9-28
*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define TOKENMAX 100
#define PROGMAX 1000
#define K_ESC 27
void analytics(); //詞法分析
void scanner(); //輸入掃描
bool isLetter(char ch);//判斷字符是否為字母
bool isDigit(char ch);//判斷字符是否為數字
bool concat(char token[],char ch);//將ch連接在token後麵
int reserve(char token[]);//對token中字符串查關鍵字表,若是關鍵字返回其編碼,否則返回標識符種別碼10
double ezhishu(int x,double e);//求以e為底的指數
bool isZheng11();//11正規式判斷,判斷是否是(+|-)d+(.d+)(ed+)的科學計數
//全局變量
char prog[PROGMAX],token[TOKENMAX];
char ch;
int syn,ptrp,ptrt;//ptrp是緩衝區prog的指針//ptrt是token的指針
double sum;
char *rwtab[6]={"begin","if","then","while","do","end"};
int main(){
int key=0;
do{
fflush(stdin);//清空輸入流
analytics();
printf("\n按Esc退出,其他鍵繼續...\n");
if(!kbhit()){
key=getch();
}
}while(key!=K_ESC);
return 0;
}
//輸入字符串並進行詞法分析,返回二元組
void analytics(){
ptrp=0;
printf("請輸入字符串,以#結尾:\n");
do{
ch=getchar();
prog[ptrp++]=ch;
}while(ch!='#');
ptrp=0;
do{
scanner();
switch(syn){
case 1:printf("(%2d,%8s)\n",syn,token);break;
case 2:printf("(%2d,%8s)\n",syn,token);break;
case 3:printf("(%2d,%8s)\n",syn,token);break;
case 4:printf("(%2d,%8s)\n",syn,token);break;
case 5:printf("(%2d,%8s)\n",syn,token);break;
case 6:printf("(%2d,%8s)\n",syn,token);break;
case 10:printf("(%2d,%8s)\n",syn,token);break;
case 11:printf("(%2d,%lg)\n",syn,sum);break;
case 13:printf("(%2d,%8s)\n",syn,token);break;
case 14:printf("(%2d,%8s)\n",syn,token);break;
case 15:printf("(%2d,%8s)\n",syn,token);break;
case 16:printf("(%2d,%8s)\n",syn,token);break;
case 17:printf("(%2d,%8s)\n",syn,token);break;
case 18:printf("(%2d,%8s)\n",syn,token);break;
case 20:printf("(%2d,%8s)\n",syn,token);break;
case 21:printf("(%2d,%8s)\n",syn,token);break;
case 22:printf("(%2d,%8s)\n",syn,token);break;
case 23:printf("(%2d,%8s)\n",syn,token);break;
case 24:printf("(%2d,%8s)\n",syn,token);break;
case 25:printf("(%2d,%8s)\n",syn,token);break;
case 26:printf("(%2d,%8s)\n",syn,token);break;
case 27:printf("(%2d,%8s)\n",syn,token);break;
case 28:printf("(%2d,%8s)\n",syn,token);break;
case 0:break;//#
case -1:printf("輸入有誤!");break;
default:printf("(%2d,%8s)\n",syn,token);
}
}while(syn!=0 && syn!=-1);
}
void scanner(){
int n;
for(n=0;n<TOKENMAX;n++) token[n]=NULL;
ch=prog[ptrp++];
n=0;
while((ch==32 || ch==10) && n++<PROGMAX)ch=prog[ptrp++];
if(isLetter(ch)){
//文法10
int temp=ptrp;
while(isDigit(ch) || isLetter(ch)){
concat(token,ch);
ch=prog[ptrp++];
}
ptrp--;
for (n=0;n<6;n++){
if(strcmp(token,rwtab[n])==0)
{
switch(n){
case 0:syn=1;return;
case 1:syn=2;return;
case 2:syn=3;return;
case 3:syn=4;return;
case 4:syn=5;return;
case 5:syn=6;return;
}
}
}
if(temp<=ptrp){
syn=10;
return;
}
}
else {
if(isDigit(ch))
{
int temp=ptrp;
if(isZheng11()){
syn=11;
return;
}
ptrp=temp;
}
switch(ch){
case '<':
ptrt=0;
token[ptrt++]=ch;
ch=prog[ptrp++];
if (ch=='>')
{ syn=21;
token[ptrt++]=ch;
}
else if (ch=='=')
{
syn=22;
token[ptrt++]=ch;
}
else
{
syn=20;
ptrp--;
}
break;
case '>':
ptrt=0;
token[ptrt++]=ch;
ch=prog[ptrp++];
if (ch=='=')
{ syn=24;
token[ptrt++]=ch;
}
else
{
syn=23;
ptrp--;
}
break;
case '+':
ptrt=0;
token[ptrt++]=ch;
ch=prog[ptrp++];
if(isDigit(ch)){
if(isZheng11()){
syn=11;
return;
}
}
else{
syn=13; token[0]='+';ptrp--; return;
}
case '-':
ptrt=0;
token[ptrt++]=ch;
ch=prog[ptrp++];
if(isDigit(ch)){
if(isZheng11()){
syn=11;
sum-=2*sum;
return;
}
}
else{
syn=14; token[0]='-';ptrp--; return;
}
case '*':syn=15; token[0]=ch; return;
case '/':syn=16; token[0]=ch; return;
case ':':
ptrt=0;
token[ptrt++]=ch;
ch=prog[ptrp++];
if (ch=='=')
{ syn=18;
token[ptrt++]=ch;
}
else
{
syn=17;
ptrp--;
}
return;
case '(':syn=27; token[0]=ch; return;
case ';':syn=26; token[0]=ch; return;
case '=':syn=25; token[0]=ch; return;
case ')':syn=28; token[0]=ch; return;
case '#':syn=0; token[0]=ch; return;
default:
syn= -1; token[0]=ch;return ;
}
}
}
bool isLetter(char ch){
return ((ch >64 && ch <91) || (ch >96 && ch <123));
}
bool isDigit(char ch){
return (ch >47 && ch <58);
}
bool concat(char token[],char ch){
int i=0;
while(i< TOKENMAX){
if(token[i] == NULL){
token[i]=ch;
return true;
}
i++;
}
return false;
}
bool isZheng11(){
int temp1=ptrp;
int temp2=ptrp;
sum=0;
while(isDigit(ch)){
sum=sum*10+ch-'0';
ch=prog[ptrp++];
}
temp1=--ptrp;
if(ch=='.'){
//xiaoshu
ch=prog[++temp1];
double dot=0.1;
while(isDigit(ch)){
sum=(ch-'0')*dot+sum;
ch=prog[++temp1];
dot*=0.1;
}
if(ch=='e'){//kexue
ch=prog[++temp1];
temp2=temp1;
int tempsum=0;
if(isDigit(ch)){
while(isDigit(ch)){
tempsum=10*tempsum+ch-'0';
//sum=sum*ezhishu((ch-'0'),10);
ch=prog[++temp1];
}
if(temp2<temp1){
sum=sum*ezhishu(tempsum,10);
ptrp=temp1;
return true;
}
ch='e';
}
else if(ch=='+'){
ch=prog[++temp1];
temp2=temp1;
int tempsum=0;
while(isDigit(ch)){
tempsum=tempsum*10+ch-'0';
//sum=sum*ezhishu(ch-'0',10);
ch=prog[++temp1];
}
if(temp2<temp1){
sum=sum*ezhishu(tempsum,10);
ptrp=temp1;
return true;
}
ch='+';
}
else if(ch=='-'){
ch=prog[++temp1];
temp2=temp1;
int tempsum=0;
while(isDigit(ch)){
tempsum=tempsum*10+ch-'0';
//sum=sum*ezhishu(ch-'0',0.1);
ch=prog[++temp1];
}
if(temp2<temp1){
sum=sum*ezhishu(tempsum,0.1);
ptrp=temp1;
return true;
}
ch='-';
}
else{
}
ptrp=temp2-1;
}
else if(temp1>=ptrp){
ptrp=temp1;
return true;
}
else{
}
}
else if(ch=='e'){
//kexue jishu
ch=prog[++temp1];
temp2=temp1;
int tempsum=0;
if(isDigit(ch)){
while(isDigit(ch)){
tempsum=10*tempsum+ch-'0';
//sum=sum*ezhishu((ch-'0'),10);
ch=prog[++temp1];
}
if(temp2<temp1){
sum=sum*ezhishu(tempsum,10);
ptrp=temp1;
return true;
}
ch='e';
}
else if(ch=='+'){
ch=prog[++temp1];
temp2=temp1;
int tempsum=0;
while(isDigit(ch)){
tempsum=tempsum*10+ch-'0';
//sum=sum*ezhishu(ch-'0',10);
ch=prog[++temp1];
}
if(temp2<temp1){
sum=ezhishu(tempsum,10)*sum;
ptrp=temp1;
return true;
}
ch='+';
}
else if(ch=='-'){
ch=prog[++temp1];
temp2=temp1;
while(isDigit(ch)){
sum=sum*ezhishu(ch-'0',0.1);
ch=prog[++temp1];
}
if(temp2<temp1){
ptrp=temp1;
return true;
}
ch=temp1-2;
ch='-';
}
else{
}
ch='e';
}
else{
//zhengshu
}
return true;
}
double ezhishu(int x,double e){
double sum=1;
for(;x-->0;sum*=e);
return sum;
}
編譯原理課後練習,詞法分析的題目。要求分析一個科學計數的正規式,實在不會化簡,就直接寫了
最後更新:2017-04-03 15:22:11