我的词法分析器源代码

该博客展示了一个C语言编写的词法分析程序,包含accidence.c和accidence.h文件代码。程序读取关键字文件和待分析程序文件,进行词法扫描,将结果输出到token.txt和symbol.txt文件,同时处理错误信息并记录到error.txt文件,还给出了测试代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

accidence.c
///////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include "accidence.h"

extern Token token_String[4096];
extern pSymbol SymbolList[4096];

static char *p_KeyWord[256];
static char c_Temp[256];
static int row=0,col=0;
static FILE *fp_Error;

main(int argc,char *argv[])
{
   FILE *fp_Program,*fp_KeyWord,*fp_Token,*fp_SymbolList;

   int i=0;
   int temp;
   
   for(i=0;i<4096;i++) 
   {
      SymbolList[i]=NULL;
   }
   for(i=0;i<255;i++)
   {
      p_KeyWord[i]=NULL;
   }
/*   if (argc!=2)
   {
      printf("you forgot to type your programe name /n");
      exit(0);
   }
   if(!(fp_Program=fopen(argv[1],"r")))
   {
      printf("Can't open file %s!",argv[1]);
      exit(1);
   }*/
   if(!(fp_Program=fopen("efile.pas","r")))
   {
      printf("Can't open file rfile.pas!");
      exit(1);
   }
   if(!(fp_KeyWord=fopen("KeyWord.dat","rb")))
   {
      printf("Can't open file KeyWord.dat!");
      exit(1);
   }
   if(!(fp_Error=fopen("error.txt","w+")))
   {
      printf("Can't open file error.txt!");
      exit(1);
   }
   for(i=0;!feof(fp_KeyWord);i++)
   {
      if(!(p_KeyWord[i]=(char*)malloc(20*sizeof(char))))
      {
         printf("Allocation momory fail!!");
         exit(1);
      }
      fscanf(fp_KeyWord,"%s",p_KeyWord[i]);
   }
   free(p_KeyWord[i-1]);
   p_KeyWord[i-1]=NULL;

   while(!feof(fp_Program))
   {
      for(i=0;;i++)
      {
         if(i>255)
         {
            printerr(4);
            fprintf(fp_Error,"This line is too long.Please 255 charactor a Line!/n");
            c_Temp[i]='/n';
            do
            {
               temp=getc(fp_Program);
            }while(temp!=EOF&&temp!='/n');
            break;
         }
         c_Temp[i]=fgetc(fp_Program);
         if(c_Temp[i]=='/n')
            break;
         if(c_Temp[i]==EOF)
         {
            c_Temp[i]='/n';
            break;  
         }
      }
      scanner(c_Temp);
      row++;
   }
   fp_Token=fopen("token.txt","w+");
   fp_SymbolList=fopen("symbol.txt","w+");
   i=0;
   while(token_String[i].Kin_Cod)
   {
      if(token_String[i].Kin_Cod<=37 && token_String[i].Kin_Cod>=34)
      {
         if(SymbolList[token_String[i].Index]->Type==IND||
            SymbolList[token_String[i].Index]->Type==STRING)
            fprintf(fp_Token,"(%d,'%s')",token_String[i].Kin_Cod,
                  SymbolList[token_String[i].Index]->Addr);
         if(SymbolList[token_String[i].Index]->Type==INT)
            fprintf(fp_Token,"(%d,%d)",token_String[i].Kin_Cod,
                  SymbolList[token_String[i].Index]->lVal);
         if(SymbolList[token_String[i].Index]->Type==FLOAT)
            fprintf(fp_Token,"(%d,%f)",token_String[i].Kin_Cod,
                  SymbolList[token_String[i].Index]->dVal);
      }
      else
         fprintf(fp_Token,"(%d,_)",token_String[i].Kin_Cod);
      fprintf(fp_Token,"/n");
      i++;
   }
   i=0;
   while(SymbolList[i])
   {
      if(SymbolList[i]->Type==IND)
         fprintf(fp_SymbolList,"IND      %s/n",SymbolList[i]->Addr);
      if(SymbolList[i]->Type==INT)
         fprintf(fp_SymbolList,"INT      %ld/n",SymbolList[i]->lVal);
      if(SymbolList[i]->Type==FLOAT)
         fprintf(fp_SymbolList,"FLOAT    %f/n",SymbolList[i]->dVal);
      if(SymbolList[i]->Type==STRING)
         fprintf(fp_SymbolList,"STRING   %s/n",SymbolList[i]->Addr);
      i++;
   }
   for(i=0;p_KeyWord[i];i++) 
      free(p_KeyWord[i]);
   for(i=0;SymbolList[i];i++) 
      free(SymbolList[i]);
   fclose(fp_Token);
   fclose(fp_SymbolList);
   fclose(fp_Program);
   fclose(fp_KeyWord);
   fclose(fp_Error);
   system("edit token.txt");
   system("edit symbol.txt");
   system("edit error.txt");
}

/////////////////////////////////////////////////////////////////////////////
accidence.h

#ifndef ACCIDENCE_H_
#define ACCIDENCE_H_

#include <stdio.h>
#include <string.h>
#include <ctype.h>

enum TYPE
{
   IND,
   INT,
   FLOAT,
   STRING,
   NUL
};

typedef struct{
   unsigned int Kin_Cod;
   int Index;
} Token,*pToken;

typedef struct{
   struct Name
   {
      int Head;
      int Tail;
   };
   enum TYPE Type;
//   unsigned int Kind;
   union
   {
      long lVal;
      double dVal;
   };
   char * Addr;
} Symbol,*pSymbol;

extern char *p_KeyWord[256];
extern char c_Temp[256];
extern int row,col;
extern FILE *fp_Error;

static Token token_String[4096];
static pSymbol SymbolList[4096];
static int tok_Curr=0,sym_Curr=0;


printerr();
int lookup(char *String,enum TYPE type);

identifier(char Line[])
{
   int i=0;
   int flag=0;
   char Temp[255];
   while(Line[col]==' ')
   {
      col++;
   }
   for(i=0;isalnum(Line[col]);i++,col++)
         Temp[i]=Line[col];
   Temp[i]='/0';
   
   for(i=1,flag=0;p_KeyWord[i]!=NULL;i++)
   {
      if(strncmp(Temp,p_KeyWord[i],255)==0)
      {
         token_String[tok_Curr].Kin_Cod=i+1;
         token_String[tok_Curr].Index=0;
         tok_Curr++;
         flag=1;
         break;
      }
   }
   if(flag==0)
   {
      token_String[tok_Curr].Kin_Cod=34;
      token_String[tok_Curr].Index=lookup(Temp,IND);
      tok_Curr++;
   }
   while(Line[col]==' ')
   {
      col++;
   }
}

remark(char Line[])
{
   char *Addr=NULL;
   while(Line[col]==' ')
   {
      col++;
   }
   if(Line[col+1]!='*')
   {
      token_String[tok_Curr].Kin_Cod=48;
      token_String[tok_Curr].Index=0;
      tok_Curr++;
      col++;
   }
   else
   {
      token_String[tok_Curr].Kin_Cod=-1;
      if(Addr=strstr(&Line[col+2],"*/"))
      {
         col+=(Addr-&Line[col]+2);
         token_String[tok_Curr].Kin_Cod=0;
      }
      else
      {
         printerr(2);
         fprintf(fp_Error,"The remark in this line is not matching !/n");
         token_String[tok_Curr].Kin_Cod=0;
         col=strlen(Line)-1;
      }
   }
   while(Line[col]==' ')
   {
      col++;
   }
}

const_data(char Line[])
{
   token_String[tok_Curr].Index=lookup(&Line[col],NUL);
   tok_Curr++;
}

const_string(char Line[])
{
   char *Addr=NULL;
   char Temp[255];
   while(Line[col]==' ')
   {
      col++;
   }
   if(Addr=strstr(&Line[col+1],"'"))
   {
      strncpy(Temp,&Line[col+1],Addr-1-&Line[col]);
      Temp[Addr-1-&Line[col]]='/0';
      token_String[tok_Curr].Kin_Cod=37;
      token_String[tok_Curr].Index=lookup(Temp,STRING);
      tok_Curr++;
      col+=(Addr-&Line[col]+1);
   }
   else
   {
      printerr(3);
      fprintf(fp_Error,"The quotation mark in this line is not matching !/n");
      col=strlen(Line)-1;
   }
   while(Line[col]==' ')
   {
      col++;
   }
}

del_code(char Line[])
{
   while(Line[col]==' ')
   {
      col++;
   }
   switch (Line[col])
   {
   case '(':token_String[tok_Curr].Kin_Cod=39;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case ')':token_String[tok_Curr].Kin_Cod=40;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case '*':token_String[tok_Curr].Kin_Cod=41;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case '+':token_String[tok_Curr].Kin_Cod=43;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case ',':token_String[tok_Curr].Kin_Cod=44;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case '-':token_String[tok_Curr].Kin_Cod=45;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case 92: token_String[tok_Curr].Kin_Cod=46;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case '/':token_String[tok_Curr].Kin_Cod=48;
          token_String[tok_Curr].Index=0;
          tok_Curr++;
          col++;
          break;
   case ':':
          if(Line[col+1]=='=')
          {
             token_String[tok_Curr].Kin_Cod=51;
             token_String[tok_Curr].Index=0;
             col+=2;
             tok_Curr++;
          }
          else
          {
             token_String[tok_Curr].Kin_Cod=50;
             token_String[tok_Curr].Index=0;
             col++;
             tok_Curr++;
          }
          break;
   case '<':
          if(Line[col+1]=='=')
          {
             token_String[tok_Curr].Kin_Cod=54;
             token_String[tok_Curr].Index=0;
             col+=2;
             tok_Curr++;
          }
          else if(Line[col+1]=='>')
          {
             token_String[tok_Curr].Kin_Cod=55;
             token_String[tok_Curr].Index=0;
             col+=2;
             tok_Curr++;
          }
          else
          {
             token_String[tok_Curr].Kin_Cod=53;
             token_String[tok_Curr].Index=0;
             col++;
             tok_Curr++;
          }
          break;
   case '=':
          token_String[tok_Curr].Kin_Cod=56;
          token_String[tok_Curr].Index=0;
          col++;
          tok_Curr++;
          break;
   case '>':
          if(Line[col+1]=='=')
          {
             token_String[tok_Curr].Kin_Cod=58;
             token_String[tok_Curr].Index=0;
             col+=2;
             tok_Curr++;
          }
          else
          {
             token_String[tok_Curr].Kin_Cod=57;
             token_String[tok_Curr].Index=0;
             col++;
             tok_Curr++;
          }
          break;
   case '[':
          token_String[tok_Curr].Kin_Cod=59;
          token_String[tok_Curr].Index=0;
          col++;
          tok_Curr++;
          break;
    case ']':
          token_String[tok_Curr].Kin_Cod=60;
          token_String[tok_Curr].Index=0;
          col++;
          tok_Curr++;
          break;
    case ';':
          token_String[tok_Curr].Kin_Cod=61;
          token_String[tok_Curr].Index=0;
          col++;
          tok_Curr++;
          break;
    case 13:
           break;
    case 10:
          break;
    default:
           printerr(1);
          fprintf(fp_Error,"There have a illegal word '%c'.I have skip it now!/n",Line[col]);
          col++;
   }
   while(Line[col]==' ')
   {
      col++;
   }
}

printerr(int id)
{
   fprintf(fp_Error,"Lin=%d,Col=%d  Error(%d) :",row+1,col+1,id);
}

int lookup(char *String,enum TYPE type)
{
   int i=0;
   char *end=NULL;
   long lTemp=0;
   double dTemp=0;
   if(isalpha(String[0]))
   {
      i=0;
      while(SymbolList[i])
      {
         if(SymbolList[i]->Type==IND&&!strncmp(String,SymbolList[i]->Addr,255))
            return i;
         i++;
      }
      SymbolList[sym_Curr]=malloc(sizeof(Symbol));
      SymbolList[sym_Curr]->Type=type;
      SymbolList[sym_Curr]->Addr=malloc(sizeof(String[0])*
                                strlen(String)+1);
      strcpy(SymbolList[sym_Curr]->Addr,String);
      return sym_Curr++;
   }
   if(isdigit(String[0]))
   {
      if(!strstr(String,"."))
      {
         lTemp=strtol(String,&end,10);
         col+=(end-&String[0]);
         i=0;
         while(SymbolList[i])
         {
            if(lTemp==SymbolList[i]->lVal&& 
               SymbolList[i]->Type==INT)
               return i;
            i++;
         }
         SymbolList[sym_Curr]=malloc(sizeof(Symbol));
         SymbolList[sym_Curr]->lVal=lTemp;
         SymbolList[sym_Curr]->Type=INT;
         token_String[tok_Curr].Kin_Cod=35;
         return sym_Curr++;
      }
      else
      {
         dTemp=strtod(String,&end);
         col+=(end-&String[0]);
         i=0;
         while(SymbolList[i])
         {
            if(dTemp==SymbolList[i]->dVal&& 
               SymbolList[i]->Type==FLOAT)
               return i;
            i++;
         }
         SymbolList[sym_Curr]=malloc(sizeof(Symbol));
         SymbolList[sym_Curr]->dVal=dTemp;
         SymbolList[sym_Curr]->Type=FLOAT;
         token_String[tok_Curr].Kin_Cod=36;
         return sym_Curr++;
      }
   }
   else
      return -1;
}

scanner(char Line[])
{
   col=0;
   while(Line[col]!=13&&Line[col]!=10)
   {
      while(Line[col]==' ')
         col++;
      if(isalpha(Line[col]))
         identifier(Line);
      while(Line[col]==' ')
         col++;
      if(Line[col]=='/')
         remark(Line);
      while(Line[col]==' ')
         col++;
      if(isdigit(Line[col]))
         const_data(Line);
      while(Line[col]==' ')
         col++;
      if(Line[col]==39)
         const_string(Line);
      while(Line[col]==' ')
         col++;
      if(!isalpha(Line[col])||Line[col]==' ')
         del_code(Line);
      while(Line[col]==' ')
         col++;
   }
   col=0;
}

#endif //ACCIDENCE_H_


keyword.dat


and
array
begin
bool
call
case
char
constant
do
else
end
false
for
if 
input
integer
not
of
or
output
procedure
program
read
real
repeat
set
then
to
true
until
var
while
write


错误测试代码

efile.pas

program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)program prochar (input,output)
/*chu li zi fu 
var
456456666666664564555555555645
  ordch:integer;
  ch,predch,succch:char;
begin
  /*input words*/
  read(ch);
  writeln('ch=,ch);
  /*count the ID*/
  ordch:=ord(ch);
  predch:=pred(ch);
  succch:=succ(ch);
  324344.656
  123123.2.313.213
2312sdfd
  /*output*/
  writelin('ordch=',ordch,'predch=',predch,'succch=',succch);
end

正确测试代码
rfile.pas

program prochar (input,output);
/*chu li zi fu */
var
  ordch:integer;
  ch,predch,succch:char;
begin
  /*input words*/
  read(ch);
  writeln('ch=',ch);
  /*count the ID*/
  ordch:=ord(ch);
  predch:=pred(ch);
  succch:=succ(ch);
  324344.656
  /*output*/
  writelin('ordch=',ordch,'predch=',predch,'succch=',succch);
end


你的错误并没有改彻底,我个人认为应当改成如下方式:
SymbolList[sym_Curr]=malloc(sizeof(Symbol));
SymbolList[sym_Curr]->Type=type;
SymbolList[sym_Curr]->Addr=malloc(sizeof(String[0])*(
  strlen(String)+1));
这样合理一点。
不过大部分操作系统char的长度都是量个单位。
但现在流行的双字节字符可能不同。
 
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值