关于简单c的词法分析器

这段源码能在linux下运行!!! 能识别小数

 

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
/*#define  NULL          0*/

/*    自定义变量      */
#define  sy_if         0
#define  sy_then       1
#define  sy_else       2
#define  sy_while      3
#define  sy_begin      4
#define  sy_do         5
#define  sy_end        6
#define  a             7
#define  semicolon     8
#define  e             9
#define  jinghao       10
#define  S             11
#define  L             12

#define  tempsy        15
#define  EA            18    /*E end*/
#define  EO            19    /*E or*/

#define  plus          34
#define  times         36
#define  becomes       38
#define  op_and        39
#define  op_or         40
#define  op_not        41
#define  rop           42

#define  lparent       48     //左括号
#define  rparent       49    //有括号
#define  ident         56     //变量
#define  intconst      57 

char ch='/0';  /*存储读入当前字符*/
int count=0;        //词法分析缓冲结果数
int count1=0;
static  char spelling[10]={""};    /*存放识别的字*/
static  char line[81]={""};        /*读入一行字符到缓冲区*/
char *pline;    /*字符缓冲区指针*/

/*struct array{
        int sy11;
        int pos11;
         }A[100]      cunfangcifajieguo*/

static char ntab1[100][10];  /*存放变量表*/

struct rwords{
        char sp[10];
        int  sy;    };   /*存放保留字,sp为保留字,sy为保留字种别*/

struct rwords reswords[10]={    {"if",sy_if},
                                {"do",sy_do},
                                {"else",sy_else},
                                {"while",sy_while},
                                {"then",sy_then},
                                {"begin",sy_begin},
                                {"end",sy_end},
                                {"and",op_and},
                                {"or",op_or},
                                {"not",op_not}  };

struct aa{   int sy1;     //种别
             int pos;     /*内码值*/
            }buf[1000];  /*词法分析结果的缓冲区  源程序*/

int nlength=0;  /*记录变量表的长度*/

int lnum=0;  /*源程序长度*/

int tt1=0;   /*变量表的起始位置*/
FILE *cfile;
FILE *mfile;

/*从文件读一行到缓冲区*/
void readline()
{
   char ch1;
   pline=line;
   ch1=getchar(cfile); //windows
  // ch1 = fgetc(cfile);          // Linux
   while(ch1!='/n')
   {   *pline=ch1;
       pline++;
       ch1=getchar(cfile);   // Windows
       //ch1 = fgetc(cfile);    // linux
   }
   *pline='/0';
   pline=line;
}                       /* read a line in the buffer */

/*从缓冲区读一个字符*/
void readch()
{  if(ch=='/0')
   {   readline();
       lnum++;
    }
    ch=*pline;
    pline++;
}                     /* read a char from buffer */

/*识别(标识符)字符串是否已收录进变量表 :若不存在就返回-1 反之 */
int find(char spel[])
{
    int ss1=0;
    int ii=0;
    while((ss1==0)&&(ii<nlength))
    {  if(!strcmp(spel,ntab1[ii]))
          ss1=1;
       ii++;   //顺序执行
    }
    if(ss1==1) return ii-1;
    else return-1;
}

// 识别标识符
void identifier()
{  int iii=0,j,k;
   int ss=0;
   k=0;
   do   //只识别了小写字母 和 数字
   {  spelling[k]=ch;
      k++;
      readch();
   }while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')));
   pline--;                 // 回退
   spelling[k]='/0';       // 由于do while 中 k已加了一个  1  所以这里用'/0'做结束符
   while((ss==0)&&(iii<10))    //确认是否在保留字中(查找)
     {  if(!strcmp(spelling,reswords[iii].sp)) //strcmp相等或小于 返回 0
  ss=1;   // 如果能找到保留字 则ss值变 1 ,跳出循环
      iii++;
   }
          /* guanjianzipipei*/
   if(ss==1)   //若为保留字         
   {    buf[count].sy1=reswords[iii-1].sy;   //把保留字放在分析结果缓冲区
   }
   else
   {  buf[count].sy1=ident;     //标识符的种别
      j=find(spelling);
      if(j==-1)            //若不存在
      {  buf[count].pos=tt1;   //这里用变量在变量表的位置 来标记内码值
         strcpy(ntab1[tt1],spelling); //复制
         tt1++;                  //位置加一
         nlength++;              // 变量表的长度加一
      }
      else buf[count].pos=j;  // 若已存在这样的变量 ,内码值为 第一个出现的变量的位置
   }
   count++;            //词法分析缓冲结果数 加一
   for(k=0;k<10;k++)  spelling[k]=' ';  //清空
}               /*shuzideshibie*/
/*
void number()  // 识别常数
{   int ivalue=0;
    int digit;
    // 字符转换为数字
 do
    {  digit=ch-'0';       // [0-9]的大小
       ivalue=ivalue*10+digit;   //常数的值
       readch();                  // 读下一个字符
    }while((ch>='0')&&(ch<='9')); 
    buf[count].sy1=intconst;   //常数的种别
    buf[count].pos=ivalue;      // 常数值
    count++; 
    pline--; // 回退
}            
*/

void number()
{ float invalue = 0.0,index = 0.0,digit = 0.0;
  int flag = 0;
    do
    { 
      if((ch == '.')&&(flag = 0))
 {
   flag++;
   readch();
   continue;
 }
      if((ch >= '0')&&(ch <= '9'))
 {
   if(flag)
     {
       index = index*0.1;
       digit = ch - '0';
       invalue = invalue + digit*index;
     }
   else
     {
       digit = ch - '0';
       invalue = invalue*10 + digit;
     }
 }
      readch();
    }while(((ch >= '0')&&(ch <= '9'))||(ch == '.'));
  buf[count].sy1 = intconst;
  buf[count].pos = invalue;
  count++;
  pline--;
}

//扫描主函数
void scan()
{
   while(ch!='~')
   {  switch(ch)
      {  case' ':break;
         case'a':
         case'b':
         case'c':
         case'd':
         case'e':
         case'f':
         case'g':
         case'h':
         case'i':
         case'j':
         case'k':
         case'l':
         case'm':
         case'n':
         case'o':
         case'p':
         case'q':
         case'r':
         case's':
         case't':
         case'u':
         case'v':
         case'w':
         case'x':
         case'y':
         case'z':
         identifier();
         break;
         case'0':
         case'1':
         case'2':
         case'3':
         case'4':
         case'5':
         case'6':
         case'7':
         case'8':
         case'9':
         number();
         break;
         case'<':
         readch();
         if(ch=='=')
            buf[count].pos=0;
         else
         {  if(ch=='>')buf[count].pos=4;
            else
            {  buf[count].pos=1;
               pline--;
            }
         }
         buf[count].sy1=rop;
         count++;
         break;
         case'>':
         readch();
         if(ch=='=')
         {  buf[count].pos=2;
         }
         else
         {  buf[count].pos=3;
            pline--;
         }
         buf[count].sy1=rop;
         count++;
         break;
         case'(':
         buf[count].sy1=lparent;
         count++;
         break;
         case')':
         buf[count].sy1=rparent;
         count++;
         break;
         case'#':
         buf[count].sy1=jinghao;
         count++;
         break;
         case'+':
         buf[count].sy1=plus;
         count++;
         break;
         case'*':
         buf[count].sy1=times;
         count++;
         break;
         case':':
         readch();
         if(ch=='=')
         buf[count].sy1=becomes;
         count++;
         break;
         case'=':
         buf[count].sy1=rop;
         buf[count].pos=5;
         count++;
         break;
         case';':
         buf[count].sy1=semicolon;
         count++;
         break;
      }
   readch();
   }
   buf[count].sy1=-1;
   buf[count].pos=-1;
}

void disp1()
{  int temp1=0;
   printf("/n*********cifafenxijieguo**********/n");
   for(temp1=0;temp1<=count;temp1++)
   {
      printf("%d/t%d/n",buf[temp1].sy1,buf[temp1].pos);
      if(temp1==20)
      {  printf("Press any key to continue..../n");
         getchar();
      }
   }
   getchar();
}

void disp4()

{  int temp1=0;
   mfile=fopen("cf.txt","w");
   printf("/n******zidongshenchengwenjian*****/n");
   for(temp1=0;temp1<count;temp1++)
       fprintf(mfile,"%d/t%d/n",buf[temp1].sy1,buf[temp1].pos);
   fprintf(mfile,"~/n");
}


void disp3()
{
   int tttt;
   mfile=fopen("bl.txt","w");
   printf("/n/n%d,%d/n",lnum,count);
   getchar();
   printf("/n*********bianliaangbiao**********/n");
   for(tttt=0;tttt<tt1;tttt++)
   {   printf("%d/t%s/n",tttt,ntab1[tttt]);
       fprintf(mfile,"%d/t%s/n",tttt,ntab1[tttt]);
   }
   fprintf(mfile,"~/n");
   getchar();
}

int main()
{
   if((cfile=fopen("2.txt","r"))!=NULL)
      printf("open/n");
   else
      printf("close/n");
   readch();
      printf("%c/n",ch);
   scan();
   disp1();
   disp4();
   disp3();
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C-Minus 的词法规则 (1)关键字: if else int return void while (2)专用符号: + - * / < >= == ~= = ; , ( ) [ ] { } /* */ (3)其他标记为 ID 和 NUM ,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 (4)空格由空白、换行符、制表符组成。 (5)注释由 /*...*/ 围起来,不能嵌套。 C-Minus 的语法规则 C-Minus 的 BNF 语法如下: 1. program -> declaration_list 2. declaration_list -> declaration_list declaration | declaration 3. declaration -> var_declaration | fun_declaration 4. var_declaration -> type_specifier ID; | type_specifier ID [ NUM ]; 5. type_specifier -> int | void 6. fun_declaration -> type_specifier ID ( params ) compound_stmt 7. params -> param_list | void 8. param_list -> param_list , param | param 9. param -> type_specifier ID | type_specifier ID [ ] 10. compound_stmt -> { local_declarations statement_list } 11. local_declarations -> local_declarations var_declaration | empty 12. statement_list -> statement_list statement | empty 13. statement -> expression_stmt | compound_stmt | selection_stmt | iteration_stmt | return_stmt 14. expression_stmt -> expression ; | ; 15. selection_stmt -> if ( expression ) statement | if ( expression ) statement else statement 16. iteration_stmt -> while ( expression ) statement 17. return_stmt -> return | return expression 18. expression -> var = expression | simple_expression 19. var -> ID | ID [ expression ] 20. simple_expression -> additive_expression relop additive_expression | additive_expression 21. relop -> <= | | >= | == | ~= 22. additive_expression -> additive_expression addop term | term 23. addop -> + | - 24. term -> term mulop factor | factor 25. mulop -> * | / 26. factor -> ( expression ) | var | call | NUM 27. call -> ID ( args ) 28. args -> arg_list | empty 29. arg8list -> arg_list , expression | expression 对以上每条文法规则,给出了相关语义的简短解释。 1. program -> declaration_list 2. declaration_list -> declaration_list declaration | declaration 3. dec
1. 课程设计目标 实验建立C-编译器。只含有扫描程序(scanner)和语法分析(parser)部分。 2. 分析与设计 C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。 2.1 、扫描程序scanner部分 2.1.1系统设计思想 设计思想:根据DFA图用switch-case结构实现状态转换。 惯用词法: ① 语言的关键字:else if int return void while ② 专用符号:+ - * / < >= == != = ; , ( ) [ ] { } /* */ ③ 其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 大写和小写字母是有区别的 ④ 空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM关键字。 ⑤ 注释用通常的C语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套 说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。初始状态设置为START,当需要得到下一个token时,取得次token的第一个字符,并且按照DFA与对此字符的类型分析,转换状态。重复此步骤,直到DONE为止,输出token类型。当字符为“/”时,状态转换为SLAH再判断下一个字符,如果为“*”则继续转到INCOMMENT,最后以“*”时转到ENDCOMMENT状态,表明是注释,如果其他的则是字符停滞于当前字符,并且输出“/”。 2.1.2程序流程图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值