⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bianyi .txt

📁 一些编译原理词法分析和语法分析的源程序,比较深,因为编译本身比较难,所以适合学习编译有一定时间的人学习
💻 TXT
📖 第 1 页 / 共 3 页
字号:
   i++;
   ch=fgetc(fp);
  }
  TOKEN[i]='\0';
  fseek(fp,-1,1);
  out(INT,TOKEN);
 }
 else
  switch(ch)
  {
   case '<': ch=fgetc(fp);
      if(ch=='=') 
       out(LE," ");
      else if(ch=='>') 
       out(NE," ");
      else
      {
       fseek(fp,-1,1);
       out(LT," ");
      }
      break;
   case '=': out(EQ, " "); break;
   case '>': ch=fgetc(fp);
      if(ch=='=')
       out(GE," ");
      else
      {
       fseek(fp,-1,1);
       out(GT," ");
      }
      break;
   case ':': ch=fgetc(fp);
         if(ch=='=')              // := 为赋值语句
       out(FZ," ");
      else
      {
       fseek(fp,-1,1);
       report_error(ch);
      }
      break;
   case '/': ch=fgetc(fp);   //删除程序中的注释
      if(ch=='/')
      {
       do
       {
        ch=fgetc(fp);
       }while(ch!='\n');
       graphnum++;
      }
      else
      {
       fseek(fp,-1,1);
       out(DEV," ");
      }
      break;
   case ' ' : break;                 //删除程序中的空格              
   case '\n': graphnum++; break;   //删除程序中的回车,并记录程序编译到第几行            
   case ' ': break;      //删除程序中的横向制表符
   case -1 : break;      //删除文件尾符号
   default : report_error(ch);
     break;
  }

 }
 return;
}
void main(int argc,char *argv[])
{
 FILE *fp;

 try
 {
  if(argc!=2)
   throw argc;
  fp=fopen(argv[1],"r");
  if(!fp)
   throw argv[1];
  
 }
 
 catch(char *str)
 {
  cout<<"打开文件 : "<<str<<" 时发生错误!"<<endl;
  exit(1);
 }

 catch(int)
 {
  cout<<"请输入一个文件名!"<<endl;
  exit(1);
 }


 scanner_example(fp);

 fclose (fp);
}
----------------------------------

一个词法分析示意程序



    这里以开始定义的PASCAL语言子集的源程序作为词法分析程序的输入数据。在词法分析中,自文件头开始扫描源程序字符,一旦发现符合"单词"定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查填适当的信息表。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。
#include<stdio.h>
#include<string.h> 
#include<ctype.h>
#define NULL 0

char *key[8]={"DO","BEGIN","ELSE","END","IF","THEN","VAR","WHILE"};/*用于指向关键字表*/
char *border[6]={",",";",":=",".","(",")"}; /*用于指向符号表*/
char *arithmetic[4]={"+","-","*","/"}; /*,指向算术运算符表*/
char *relation[6]={"<","<=","=",">",">=","<>"}; /*指向关系运算符表*/
char *consts[20]; /*指向常数表*/
char *label[20]; /*指向标识符表*/
FILE *fp; /*指向要分析的PASCAL源程序*/
int constnum=0,labelnum=0; /*存放当前常数个数和标识符个数*/

char alphaprocess(char buffer); /*关键字和标识符处理子函数*/
char digitprocess(char buffer); /*数字处理函数*/
char otherprocess(char buffer); /*其他字符处理函数*/
int search(char searchcar[],int wordtype); /*查找子函数*/

/**********************************************************
*  主函数打开要分析的PASCAL源文件,若不能正确打开,则报错。
*  先从源程序中读入一个字符ch,然后进行如下处理:
*  ⒈ch是字符:转入关键字和标识符处理子函数;
*  ⒉ch是数字:转入数字处理函数;
*  ⒊ch是其他字符:转入其他字符处理子函数;
**********************************************************/
int main()
{
int i;
char cbuffer;
for (i=0;i<=20;i++)
  {
   label[i]=NULL;
   consts[i]=NULL;
  };
if (NULL==(fp=fopen("DEMO.PAS","r")))
 printf("error");
else
{
 cbuffer = fgetc(fp);
 while (cbuffer!=EOF)
 {
  if (isalpha(cbuffer))
     cbuffer=alphaprocess(cbuffer);
  else if (isdigit(cbuffer))
     cbuffer=digitprocess(cbuffer);
  else if ((cbuffer==' ')||(cbuffer=='\n')||(cbuffer=='\t'))
cbuffer=fgetc(fp);
  else cbuffer=otherprocess(cbuffer);
  };
 printf("Done\n");
 };
return 0;
}

int search(char searchchar[],int wordtype)
     {
     int i=0;
     switch (wordtype)
     {
       case 1:for (i=0;i<=7;i++)
  {
   if (strcmp(key[i],searchchar)==0)
     return(i+1);
  };

       case 2:{for (i=0;i<=5;i++)
  {
   if (strcmp(border[i],searchchar)==0)
      return(i+1);
  };
       return(0);
      }

       case 3:{for (i=0;i<=3;i++)
  {
   if (strcmp(arithmetic[i],searchchar)==0)
      {
       return(i+1);
      };
  };
      return(0);
      };
       case 4:{for (i=0;i<=5;i++)
  {
   if (strcmp(relation[i],searchchar)==0)
      {
       return(i+1);
      };
  };
       return(0);
      };
       case 5:{for (i=0;i<=constnum;i++)
  {
   if (strcmp(consts[i],searchchar)==0)
       {
return(i+1);
       };
  }
      consts[i-1]=(char *)malloc(sizeof(searchchar));
      strcpy(consts[i-1],searchchar);
      constnum++;
      return(i);
      };
       case 6:{for (i=0;i<=labelnum;i++)
  {
     if (strcmp(label[i],searchchar)==0)
       {
return(i+1);
       };
  }
      label[i-1]=(char *)malloc(sizeof(searchchar));
      strcpy(label[i-1],searchchar);
      labelnum++;
      return(i);
      };
      }
     }

/**********************************************************
*  ⒈将buffer送入临时数组alphatp[0],再读入一个字符至buffer;
*  ⒉判断buffer是否为字符或数字,若是,则alphatp[1]=buffer;
*  ⒊重复1,2,直到2判断为假;在alphatp末尾添加'\0';
*  ⒋调用search()子函数,在关键字表中匹配alphatp,若匹配成功,则返回序号;
*  ⒌否则调用search(),在标识符表中匹配alphatp,若匹配成功,则返回序号;
*  ⒍在标识符表中添加alphatp,并返回序号;
***********************************************************/
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-1);
      else
 {
 atype=search(alphatp,6);
 printf("%s (6,%d)\n",alphatp,atype-1);
 };
      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-1);
      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);
 return(buffer);
 };
      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);
 return(buffer);
 }
      else
 othertp[1]='\0';
 printf("%s (4,%d)\n",othertp,otype-1);
 return(buffer);
      };
      if (buffer==':')
      {
      buffer=fgetc(fp);
      if (buffer=='=')
 printf(":= (2,2)\n");
     buffer=fgetc(fp);
     return(buffer);
      }
else
     {
      if (otype=search(othertp,2))
 {
 printf("%s (2,%d)\n",othertp,otype-1);
 buffer=fgetc(fp);
 return(buffer);
 }
      };
printf("%c error,not a word\n",buffer);
buffer=fgetc(fp);
return(buffer);
     }
-----------------------

前些天写了个小语言的词法分析程序,因为前些天在VC知识库看到一个pascal词法分析的程序,觉得写得挺复杂的。其实词法分析程序的原理都是一样的,所以我想只要搞明白了简单的词法分析程序,再写复杂的就不难了,无非是多加几个关键字,多写几个条件判断语句而已。词法分析是编译程序的基础,也是最简单的。好,现在让我们看程序吧。
先让我们看看这个小语言的文法吧。

G[<程序>]:
<程序>∷=<程序首部>;<分程序>.
<程序首部>∷=program<标识符> 
<分程序>∷=<复合语句> 
<复合语句>∷=begin<语句序列>end 
<语句序列>∷=<语句>{;<语句>}
<语句>∷=<赋值语句>|<复合语句>|<条件语句> 
<赋值语句>∷=<标识符>:=<表达式>
<条件语句>∷=if <布尔表达式> then <语句> else <语句>
<表达式>∷=<项>{(+|-)<项>}
<项>∷=<因式>{(*|/)<因式>}
<因式>∷=<标识符>|<无正负号常量>|’(’<表达式>’)’
<布尔表达式>∷=<表达式><关系运算符><表达式>
<关系运算符>∷= =|<|<=|>|>=|<>
<标识符>∷=<字母>{<字母>|<数字>}
<无正负号常量>∷=<数字>{<数字>}[.<数字>{<数字>}]
<字母>∷=a|b|c|d|e|f|g|……|u|v|w|x|y|z
<数字>∷=0|1|2|3|4|5|6|7|8|9

根据此文法,构造一词法分析程序。输入以“#”为结束符
按照这个文法,找出该语言的关键字,如program,begin,end ,if,then,else,以及其他一些特殊符号,然后再构造一个分析表,如下表:

单词符号   类别编号 
标识符 1 
常数 2 
if 3 
then 4 
else 5 
program 6 
begin 7 
end 8 
+ 9 
- 10 
* 11 
/ 12 
( 13 
) 14 
> 15 
>= 16 
< 17 
<= 18 
<> 19 
:= 20 
; 21 
. 22 
, 23 

根据这个表来构造程序,程序的核心是下面的这个函数,

/*******************************************************************
以下为主分析函数
从输入文件里面读,把分析结果写到输出文件中
参数:fpin :输入文件指针  fpout: 输出文件指针
*******************************************************************/
void parse(FILE* fpin,FILE* fpout)
{
  char arr[MAXBUF];//读出的最长的字符串不超过MAXBUF,MAXBUF定义为255
                           //够长了我想
  int i=0;//分析含字母的字符串用
  int j=0;//分析纯数字的字符串用
     

  while(1)
  {
    fscanf(fpin,"%c",&ch);//从输入文件中读入一个字符
    if( ch=='' ''|| ch ==''\t'')//过滤掉空格和tab
      ;
    else if( ch==''\n'')//回车换行符,为下面进行错误判断
      lineno++;
    else if( IsDigit(ch))//读入的是数字
    {
      while(IsDigit(ch))
      {
        arr[j] = ch;
        j++;
        fscanf(fpin,"%c",&ch);
      }

      fseek(fpin,-1L,SEEK_CUR);//文件指针后退一个字节

      char* temp1 =(char*)malloc(j+1);/
      memcpy(temp1,arr,j);
      temp1[j] =''\0'';//把数组里面的内容拷贝到连外一个数组里面,因为我定义的
                            //arr为255个字节,实际上写不到那么多,
                           //所以只拷贝实际上有数据的

      j=0;//恢复初始状态,以备下次使用
      fprintf(fpout,"%s\t\t%d\n",temp1,2);//常数

      free(temp1);//释放内存
    }
    else if(IsAlpha(ch))//是字母开头的
    {
      while(IsAlpha(ch) || IsDigit(ch))
      {
        arr[i] =ch;
        i++;
        fscanf(fpin,"%c",&ch);
      }
      fseek(fpin,-1L,SEEK_CUR);

      char* temp = (char*)malloc(i+1) ;
      memcpy(temp,arr,i);
      temp[i] =''\0'';

      i=0;
      /*基本思想同处理数字的*/

      if(FindOK(temp))//FindOK函数在关键字表中查找和temp字符串相同的,
                             //找到就返回类别编号
      {
        fprintf(fpout,"%s\t\t%d \n",temp,FindOK(temp));
      }
      else
      {
        fprintf(fpout,"%s\t\t%d\n",temp,1);//标示符号
      }
      free(temp);
    }

    //以下为2字节的运算符号
    else if( ch=='':'')//符号“:=”
    {
      fscanf(fpin,"%c",&ch);
      if(ch==''='') 
        fprintf(fpout,"%s\t\t%d\n",":=",20);
      else  
        fprintf(fpout,"error in compileing %d lines unknown character %c \n",lineno,ch);//出错了
    }
    else if(ch==''>'')//符号 “> “ 和”>=”
    {  
      fscanf(fpin,"%c",&ch);
      if(ch==''='')
        fprintf(fpout,"%s\t\t%d\n",">=",16);
      ellse
        fprintf(fpout,">\t\t15\n");
    }
    else if( ch==''<'') //符号 “< “ 和”<=”
    {
      fscanf(fpin,"%c",&ch);
      if(ch==''='')
      {fprintf(fpout,"<=\t\t18\n");}
      else if( ch==''>'')
      {fprintf(fpout,"<>\t\t19");}
      else 
      {fprintf(fpout,"<\t\t19\n");}
    }
    else {
      //以下为一个字节的运算符号
      if(ch==''-'') {fprintf(fpout,"%s\t\t%d\n",''-'',10);continue;}//在文件中输出为“-   10”
      if(ch=='';'') {fprintf(fpout,";\t\t21\n");continue;}
      if(ch==''+'') {fprintf(fpout,"+\t\t9\n");continue;}
      if(ch==''*'') {fprintf(fpout,"*\t\t11\n");continue;}
      if(ch==''/'') {fprintf(fpout,"/ \t\t12\n");continue;}
      if(ch==''('') {fprintf(fpout,"(\t\t13\n");continue;}
      if(ch=='')'') {fprintf(fpout,")\t\t14\n");continue;}
      if(ch==''.'') {fprintf(fpout,".\t\t22\n");continue;}
      if(ch=='','') {fprintf(fpout,",\t\t23\n");continue;}
      if(ch==''#'') break;//分析结束
      else fprintf(fpout,"error in compileing %d lines unknown character %c \n",lineno,ch);//出错了,输出出错信息
    }
  }
}

    其他请看源代码,注释很详细,但是肯定有不足的地方,请大家吝赐教。有什么问题,可以给我发邮件。这是我第一次向VC知识库投稿,以后将会陆续写一些VC方面的程序来和大家共享。我的email:brilliant_zhang@21cn.com,QQ:110902663, 谢谢大家。
------------------------

词法分析是编译程序的第一步,是以后编译步骤:语法分析,语义分析以及代码生成的基础.目前可以利用LEX进行词法分析程序的编写,如果所要翻译的语言比较庞大则应该使用LEX,这就需要学习LEX的使用了,本文不使用该工具,而自己手工编写一个,旨在解除大家对编译系统的神秘感,也希望能给大家一个提示吧.网上有些词法分析程序的原代码,觉得写的挺复杂的。其实词法分析程序的原理都是一样的,所以我想只要搞明白了简单的词法分析程序,再写复杂的就不难了,无非是多加几个关键字,多写几个条件判断语句而已。词法分析是编译程序的基础,也是最简单的。好,现在让我们开始吧。

       先让我们看看这个小语言的文法吧。

G[<程序>]:

        <程序>∷=<程序首部>;<分程序>.

        <程序首部>∷=program<标识符> 

        <分程序>∷=<复合语句>     

        <复合语句>∷=begin<语句序列>end  

        <语句序列>∷=<语句>{;<语句>}

         <语句>∷=<赋值语句>|<复合语句>|<条件语句>   

         <赋值语句>∷=<标识符>:=<表达式>

         <条件语句>∷=if <布尔表达式> then <语句> else <语句>

         <表达式>∷=<项>{(+|-)<项>}

         <项>∷=<因式>{(*|/)<因式>}

         <因式>∷=<标识符>|<无正负号常量>|’(’<表达式>’)’

         <布尔表达式>∷=<表达式><关系运算符><表达式>

         <关系运算符>∷= =|<|<=|>|>=|<>

         <标识符>∷=<字母>{<字母>|<数字>}

         <无正负号常量>∷=<数字>{<数字>}[.<数字>{<数字>}]

         <字母>∷=a|b|c|d|e|f|g|……|u|v|w|x|y|z

         <数字>∷=0|1|2|3|4|5|6|7|8|9

    根据此文法,构造一词法分析程序。输入以“#”为结束符

按照这个文法,找出该语言的关键字,如program,begin,end ,if,then,else,以及其他一些特殊符号,然后再构造一个分析表,如下表:

单词符号
 类别编号
 单词符号
 类别编号
 
标识符
 1
 )
 14
 
常数
 2
 >
 15
 
if
 3
 >=
 16
 
then
 4
 <
 17
 
else
 5
 <=
 18
 
program
 6
 <>
 19
 
 
  
 
   评论(条)  关闭页面  打印
 
---------------------




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -