用c实现pascal词法分析器

#include "define.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
FILE *fp;

/*//
This is a pretreatment.
/*/
void readIntoBuffer(char buffer[256])
{
 char ch1;
 char temp;
 int i;

 for(i=0;i<256&&!feof(fp);i++)
 {
  ch1=fgetc(fp);
  if(ch1==' ')  
  {
   temp=ch1;
   while(ch1==' ')
    ch1=fgetc(fp);
   if(ch1!=EOF)
   {
    if(ch1!='/n'&&ch1!=' '&&ch1!='/t')
     fseek(fp,-1L,1);
    if(buffer[i-1]!=' ')
     buffer[i]=temp;
    else i=i-1;
   }
   else
    buffer[i]=ch1;
   continue;
  }
  if(ch1=='/n')
  {
   temp=ch1;
   while(ch1=='/n')
    ch1=fgetc(fp);
   if(ch1!=EOF)
   {
    if(ch1!='/n'&&ch1!=' '&&ch1!='/t')
     fseek(fp,-1L,1);
    if(buffer[i-1]!=' ')
     buffer[i]=' ';
    else i=i-1;
   }
   else
    buffer[i]=ch1;

   continue;
  }
  if(ch1=='/t')
  {

   while(ch1=='/t')
    ch1=fgetc(fp);
   if(ch1!=EOF)
   {
    if(ch1!='/n'&&ch1!=' '&&ch1!='/t')
     fseek(fp,-1L,1);
    if(buffer[i-1]!=' ')
     buffer[i]=' ';
    else i=i-1;
   }
   else buffer[i]=ch1;

   continue;
  }
  if(ch1=='{')
  {
   ch1=fgetc(fp);
   while(ch1!='}')
    ch1=fgetc(fp);
   fseek(fp,-1L,1);
  }

  else
  {
   buffer[i]=ch1;
   continue;
  }
      }

}
int insertid(char id[])
{
       int i;
     
       pid1=(struct Identifier*)malloc(LENID);
      if(idhead==NULL)
      {
           for(i=0;i<20;i++)
              pid1->str1[i]=id[i];
           pid1->next1=idhead;
           idhead=pid1;
           pid2=pid1;
      }
      else
      {
           for(i=0;i<20;i++)
              pid1->str1[i]=id[i];
           pid1->next1=pid2->next1;
           pid2->next1=pid1;
           pid2=pid1;
      }
   return count1++;
}
int insertint(char id[])
{
       int i;
      
       pint1=(struct Integer*)malloc(LENINT);
      if(inthead==NULL)
      {
           for(i=0;i<16;i++)
              pint1->str2[i]=id[i];
           pint1->next2=inthead;
           inthead=pint1;
           pint2=pint1;
      }
      else
      {
           for(i=0;i<16;i++)
              pint1->str2[i]=id[i];
           pint1->next2=pint2->next2;
           pint2->next2=pint1;
           pint2=pint1;
      }
      return count2++;
}
int insertreal(char real[])
{
       int i;
      
       preal1=(struct Real*)malloc(LENREAL);
      if(realhead==NULL)
      {
           for(i=0;i<32;i++)
              preal1->str3[i]=real[i];
           preal1->next3=realhead;
           realhead=preal1;
           preal2=preal1;
      }
      else
      {
           for(i=0;i<32;i++)
              preal1->str3[i]=real[i];
           preal1->next3=preal2->next3;
           preal2->next3=preal1;
           preal2=preal1;
      }
      return count3++;
}
void  getChar()
{

 if(isb1empty)
 {
  readIntoBuffer(buffer1);
  isb1empty=FALSE;
 }
 if(isb2empty)
 {
  readIntoBuffer(buffer2);
  isb2empty=FALSE;
 }
 if(buffer1[k1]==EOF)
 {
  EndFlag=0;
  ch=EOF;
 }
 if(buffer2[k2]==EOF)
 {
  EndFlag=0;
  ch=EOF;
 }
 if(flag==0&&buffer1[k1]!=EOF)
 {
  ch=buffer1[k1];
  k1++;
  if(k1==256)
  {
   flag=1;
   isb1empty=TRUE;
   k1=0;
  }

 }
 if(flag==1&&buffer2[k2]!=EOF)
 {
  ch=buffer2[k2];
  k2++;
  if(k2==256)
  {
   flag=0;
   isb2empty=TRUE;
   k2=0;
  }
 }

}
void retract()
{

 if(flag==0)
  k1=k1-1;
 if(flag==1)
        k2=k2-1;
}
void insert(char ch)
{
 strToken[j]=ch;
 j++;
}
int reserve()
{
 int k;
 for(k=0;k<8;k++)
 {
  if(strcmp(strToken,p[k])==0)
   return k+1;

 }
 return 0;
}
/*
词法分析器,从缓冲区中取出字符,识别出单词符号
///*/

void lex()
{
 int code;
 getChar();
       
 if(isalpha((int)ch)||(int)ch==UNDERLINE)
 {

  while(isalpha((int)ch)||isdigit((int)ch)||(int)ch==UNDERLINE)
  {
   insert(ch);
   getChar();
  }
  retract();
  code=reserve();
  if(code==0)
  {
                       
          
   printf("(6,%d)/n",insertid(strToken));
   return;
  }
  else
  {
   printf("(%s,%d)/n",strToken,code);
   return;
  }
 }
 if(isdigit((int)ch))
 {

  while(isdigit((int)ch))
  {
   insert(ch);
   getChar();
  }

  if((int)ch==DOT)
  {
   getChar();
   if(isdigit((int)ch))
   {
    while(isdigit((int)ch))
    {
     insert(ch);
     getChar();
    }

    if((int)ch==EXP||(int)ch==exp)
    {
     getChar();
     if((int)ch==MINUS)
     {
      insert(ch);
      getChar();
     }
     if(isdigit((int)ch))
     {
      while(isdigit((int)ch))
      {
       insert(ch);
       getChar();
      }
      retract();
      printf("exponential/n");
      return;
     }
     else
     {
      retract();
      retract();
      retract();
      return;
     }
    }
    else
    {
     retract();
                                       
                   
     printf("(7,%d)/n",insertreal(strToken));
     return;
    }
   }
   
   else
   {
    retract();
    printf("(2,)/n");
    return;
   }
  }
  if((int)ch==EXP||(int)ch==exp)
  {
   getChar();
   if((int)ch==MINUS)
   {
    insert(ch);
    getChar();
   }
   if(isdigit((int)ch))
   {
    while(isdigit((int)ch))
    {
     insert(ch);
     getChar();
    }
    retract();
    printf("exponential/n");
    return;
   }
   else
   {
    retract();
    retract();
    retract();
    return;
   }
  }
        else if(isalpha((int)ch)||ch=='$'||ch=='#')
  {      
       insert(ch);
       getChar();
    while(isalpha((int)ch)||ch=='$'||ch=='#'||isdigit((int)ch))
    {
                    insert(ch);
     getChar();
    }
    retract();
    printf("idetifier %s error/n",strToken);return;
  }
  else
  {
  
   printf("(8,%d)/n",insertint(strToken));return;
  }

 }
 if((int)ch==PLUS)
 {
  printf("(3,10h)/n");
  return;
 }
 if((int)ch==MINUS)
 {
  printf("(3,11h)/n");
  return;
 }
 if((int)ch==MULTIPLY)
 {
  printf("(3,20h)/n");
  return;
 }
 if((int)ch==DEVIDE)
 {
  printf("(3,21h)/n");
  return;
 }
 if((int)ch==LBRACKET)
 {
  printf("(2,4)/n");
  return;
 }
 if((int)ch==RBRACKET)
 {
  printf("(2,5)/n");
  return;
 }
 if((int)ch==SEMICOLON)
 {
  printf("(2,2)/n");
  return;
 }
 if((int)ch==COLON)
 {
  getChar();
  if((int)ch==EQUAL)
  {
   printf("(2,3)/n");
   return;
  }
  else{printf("冒号/n");retract();return;}
 }
 if((int)ch==LESS)
 {
  getChar();
  if((int)ch==EQUAL)
  {
   printf("(4,01H)/n");
   return;
  }
  if((int)ch==MORE)
  {
   printf("(4,05H)/n");
   return;
  }
  else
  {
   retract();
   printf("(3,21h)/n");
   return;
  }
 }
 if((int)ch==MORE)
 {
  getChar();
  if((int)ch==EQUAL)
  {
   printf("(4,04H)/n");
   return;
  }

  else
  {
   retract();
   printf("(3,03h)/n");
   return;
  }
 }
 if((int)ch==EQUAL)
 {
  printf("(4,02H)/n");
  return;
 }
 if((int)ch==COMMA)
 {
  printf("(2,0)/n");
  return;
 }

}
void del()
{
 while(idhead!=NULL)
 {
  pid2=idhead->next1;
  free(idhead);
  idhead=pid2;
 }
 while(inthead!=NULL)
 {
  pint2=inthead->next2;
  free(inthead);
  inthead=pint2;
 }
 while(realhead!=NULL)
 {
  preal2=realhead->next3;
  free(realhead);
  realhead=preal2;
 }
}

int main()
{
 char fName[20];
 int i;
 printf("Please intput the file name that you want to compile:    ");
 scanf("%s",fName);
    if((fp=fopen(fName,"r"))==NULL)
 {
  printf("cannot find thie file!");
 }
 while(EndFlag)
 {
  for(i=0;i<40;i++)
   strToken[i]='/0';
  j=0;
  lex();
 }
 fclose(fp);
 printf("/nOutput the keywords!/n");
 while(idhead!=NULL)
 {
  printf("<id,%s>/n",idhead->str1);
  idhead=idhead->next1;
 }
 printf("/nOutput the integer!/n");
 while(inthead!=NULL)
 {
  printf("<int,%s>/n",inthead->str2);
  inthead=inthead->next2;
 }
 printf("/nOutput the real!/n");
 while(realhead!=NULL)
 {
  printf("<real,%s>/n",realhead->str3);
  realhead=realhead->next3;
 }
 del();
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
⒈ 题目 编写前述PASCAL子集的词法分析程序。 1)主程序设计考虑,(参阅后面给出的程序框架) 主程序的说明部分为各种表格和变量安排空间。 数组k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字后面补空格。 P 数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在p表中(学生编程时,应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id 和ci 数组分别存放标识符和常数。 instring 数组为输入源程序的单词缓存。 outtoken 记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k 表;再输入分界符等造 p 表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。 2)词法分析过程考虑 该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符k表示关键字;i表示标识符;c 表示常数;p 表示分界符;s 表示运算符(学生编程时类号分别为1,2,3,4,5)。 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组 id 中,将常数变为二进制形式存入数组中 ci 中,并记录其在表中的位置。 lexical 过程中嵌有两个小过程:一个名为 getchar,其功能为从 instring 中按顺序取出一个字符,并将其指针 pint 加 1 ;另一个名为 error,当出现错误时,调用这个过程,输出错误编号。 将词法分析程序设计成独(入口)立一遍扫描源程序的结构。其流程图见图5-1。 图5-1 词法分析程序流程图 ⒉ 要求 ⑴ 所有识别出的单词都用两个字节的等长表示,称为内部码。第一个字节为 t ,第二个字节为 i 。 t 为单词的种类。关键字的 t=1;分界符的 t=2;算术运算符的 t=3;关系运算符的 t=4;无符号数的 t=5;标识符的 t=6。i 为该单词在各自表中的指针或内部码值。表 5-1 为关键字表;表 5-2 为分界符表;表 5-3 为算术运算符的 i 值;表 5-4 为关系运算符的 i 值。 表5-1 关键字表 表5-2 分界符表 指针1 关键字 指针1 分界符 0 BEGIN 0 , 1 DO 1 ; 2 ELSE 2 . 3 END 3 := 4 IF 4 ( 5 THEN 5 ) 6 VAR 7 WHILE 表5-3 算术运算符 表5-4 关系运算符 i 值 算术运算符 i 值 关系运算符 00H < 10H + 01H 21H / 04H >= 05H 常数表和标识符表是在编译过程中建立起来的。其 i 值是根据它们在源程序中出现的顺序确定的。 ⑵ 常数分析程序、关键字和标识符分析程序、其他单词分析程序请参阅范例自行设计。 ⑶ 本实践题可通过扩充下面给出的程序框架完成。 PROGRAM plexical(input,output); LABEL l; CONST keylen=10; identlen=10; TYPE //定义的类型 tstring=ARRAY[1..identlen] OF char; outreco=RECORD//记录为输出内部表示缓存。 ty: char; point: integer; END; {outreco} VAR cip,ip,pint,i,j,l,m,errorx:integer; charl:CHAR; ci:ARRAY[1..10] OF integer; k,id:ARRAY[1..keylen] OF tstring; token:tstring; //标志符 outtoken:outreco; instring:ARRAY[1..10]OF char; p:ARRAY[1..16] OF ARRAY [1..2] OF char; PROCEDURE lexical; VAR l,m,num:integer; b: boolean; PROCEDURE
C语言编写一个只包含部分保留字和单词符号(见语言子集L)的PASCAL语言的扫描器(词法分析器)。 1、该词法分析器的任务: (1)滤掉源程序中的无用成分,如空格; (2)输出分类记号供语法分析器使用,并产生两个表格:常数表和标识符表,表的数据结构和包含内容可参看书中第八章符号表; (3)识别非法输入,并将其标记为“出错记号”。 2、该词法分析器的功能: 以在下面段落中定义的PASCAL语言子集的源程序作为词法分析程序的输入数据。词法分析器打开该文件后,自文件头开始扫描源程序字符,发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查填适当的信息表,一旦发现不符合“单词”定义的源程序字符串时,给出错误提示。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。 3、PASCAL语言子集L----保留字不区分大小写 L={ VAR,BEGIN,ELSE,END,IF,THEN,REAL,INTEGER,=,:=,-,+,*,; ,. }∪{常数}∪{标识符} 4、实验要求: (1)词法分析器构造:正规式设计、DFA设计、代码编写; (2)进行词法分析器的测试:测试例程(一小段程序)、测试结果与测试结果分析。 (3)实验报告格式自拟;实验报告中要对实验要求中正规式设计、DFA设计、代码编写、测试例程(3中定义的PASCAL语言子集的源程序段)、测试结果与测试结果分析逐项给予说明。 例子: 本例中单词符号(记号)的种类: 1、保留字; 2、分隔符; 3、运算符; 4、等符 5、常数; 6、标识符 (单词符号的分类可以自己规定,只是要在实验报告中给出说明) 测试例程PASCAL程序清单如下: BEGIN IF I=1 THEN ^ A:=I+1 ELSE *& IF I=2 THEN A:=I+11; END. # 运行词法分析程序后,显示如下结果如下: BEGIN (1,1) IF (1,4) I (6,0) = (4,2) 1 (5,0) THEN (1,5) ^ error, not a word A (6,1) := (2,2) I (6,0) + (3,0) 1 (5,0) ELSE (1,2) * (3,2) & error, not a word IF (1,4) I (6,0) = (4,2) 2 (5,1) THEN (1,5) A (6,1) := (2,2) I (6,0) + (3,0) 11 (5,2) ; (2,1) END (1,3) . (2,3) # error, not a word over 常数表CT:1,2 标识符表LT:I,A

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值