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

📄 parse.c

📁 该程序能够实现简单的c语言词法
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************************************************************ 
* 
*   文件名:parse.c
* 
*   文件描述:简单C语言编译器前驱
* 
*   创建人:  哈工大2002级软件一班黄敬彬, 2004年12月
* 
*   版本号:1.0 
* 
*   修改记录:           
* 
************************************************************************/
#include"stdio.h"
#include"ctype.h"
#include"string.h"
#include <malloc.h>
#include"math.h"
#include"stdlib.h"
#include"float.h"
#define init_size 1000
#define add_size 100

#define ID 0
/*算术表达式中的符号*/
#define add 1
#define multy 2
#define leftpar 3
#define rightpar 4
#define minus 5
#define divide 6
/*代表字符串*/
#define word_string 7
/*分界符*/
#define word_divide 8
/*其他符号*/
#define word_other 9
/*关键字*/
#define word_key 10
/*逻辑与&&*/
#define and 11
/*逻辑或||*/
#define or 12
/*逻辑非 !*/
#define not 13
/*比较判断符号>,>=,<,<=,==,!=*/
#define great 14
#define great_equal 15
#define small 16
#define small_equal 16
#define equal_equal 17
#define not_equal  18
/*循环和条件语句关键字*/
#define symbol_if 19
#define symbol_else 20
#define symbol_while 21
#define symbol_do 22
#define symbol_for 23
/*声明语句关键字*/
#define symbol_int 24
#define symbol_float 25
#define symbol_char 26
/*单目运算符*/
#define add_add  27
#define minus_minus 28
/*左右大括号与左右中括号*/
#define leftbig 29
#define rightbig 30
#define leftmiddle 31
#define rightmiddle 32
/*=*/
#define equal 33
/*分号*/
#define  fenhao 34

#define NUM 35
#define symbol_void 36
#define symbol_long 37
#define symbol_double 38

#define ERRO 254
/*用来表示符号表中的mark项为ID*/
#define symbol_mark_ID 253
/*逻辑表达式中的非终结符*/
#define B 0
#define A 1
#define O 2

/*算术表达式中的非终结符*/
#define E  0
#define T  1
#define F 2
#define acc 256
/*赋值语句非终结符*/
#define evaluate 0
int action1[12][6]={ /*算术表达式action表*/
{5,-1,-1,4,-1,-1},
{-1,6,-1,-1,-1,acc},
{-1,102,7,-1,102,102},
{-1,104,104,-1,104,104},
{5,-1,-1,4,-1,-1},
{-1,106,106,-1,106,106},
{5,-1,-1,4,-1,-1},
{5,-1,-1,4,-1,-1},
{-1,6,-1,-1,11,-1},
{-1,101,7,-1,101,101},
{-1,103,103,-1,103,103},
{-1,105,105,-1,105,105}
};
int goto1[12][3] ={   /*算术表达式goto表*/
{1,2,3},{0,0,0},{0,0,0},{0,0,0},{8,2,3},{0,0,0},{0,9,3},{0,0,10},
{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int action2[16][8] ={
      {1,-1,4,-1,5,-1,-1,-1},
      {-1,2,-1,101,-1,101,101,101},
      {3,-1,-1,-1,-1,-1,-1,-1},
      {-1,-1,-1,102,-1,102,102,102},
      {1,-1,4,-1,5,-1,-1,-1},
      {1,-1,4,-1,5,-1,-1,-1},
      {-1,-1,-1,104,-1,104,104,104},
      {1,-1,4,-1,5,-1,-1,-1},
      {1,-1,4,-1,5,-1,-1,-1},
      {105,-1,105,-1,105,-1,-1,-1},
      {107,-1,107,-1,107,-1,-1,-1},
      {-1,-1,-1,12,-1,9,10,-1},
      {-1,-1,-1,103,-1,103,103,103},
      {-1,-1,-1,acc,-1,9,10,acc},
      {-1,-1,-1,106,-1,9,10,106},
      {-1,-1,-1,108,-1,9,10,108}
};
int goto2[16][3] = {
{13,7,8},{0,0,0},{0,0,0},{0,0,0},{11,7,8},{6,7,8},{0,0,0},{14,7,8},{15,7,8},
{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};


struct keyword /*定义关键字结构体*/
{
        char * key[10];
}keywords[32];
struct symbolize
{
     int mark;
     char *variable;
     int type;
     int value;

};
struct symbolize *symbol;
int symbol_size;/*当前符号表大小*/
int index = 0;/*符号表索引*/
char operater[] = "><=+-!*%&^|";/*操作符数组*/
char letter[]= "`~!@#$%^&*()_+|{}\":?><,./;'[]\\=-";/*定义C语言所用到的符号数组*/
FILE *fp;
FILE *output,*erro,*chart;/*分别定义测试程序文件,输出文件,错误文件,符号表文件指针*/
int linenumber = 1;/*用来表示测试文件的行号 */
int lex_word[300];/*存放词法分析的结果*/
int lex_index=0;/*表示词法分析结果数组元素个数 */
int pointer=0;/*当前语法分析的指针 */
/*算术表达式的临时变量*/
int E_value = 0,T_value = 0,F_value = 0;

int iscreate = 0;/*判断是否产生四元式的标志值*/
struct quaternion /*四元式结构体*/
{
   char operate;
   int arg1;
   int arg2;
   int result;
}four_element[100];
int findex = 0; /*四元式结构索引*/
int temporary = 1; /*用来表示当前临时变量的个数*/
void init()/*初始化关键字结构体数组*/
{
     * keywords[0].key = "auto";
         * keywords[1].key = "break";
         * keywords[2].key = "case";
     * keywords[3].key = "char";
     * keywords[4].key = "const";
     * keywords[5].key = "continue";
     * keywords[6].key = "default";
         * keywords[7].key = "do";
         * keywords[8].key = "double";
         * keywords[9].key = "else";
         * keywords[10].key = "enum";
         * keywords[11].key = "extern";
         * keywords[12].key = "float";
         * keywords[13].key = "for";
         * keywords[14].key = "goto";
         * keywords[15].key = "if";
         * keywords[16].key = "int";
         * keywords[17].key = "long";
         * keywords[18].key = "register";
         * keywords[19].key = "return";
         * keywords[20].key = "short";
         * keywords[21].key = "signed";
         * keywords[22].key = "sizeof";
         * keywords[23].key = "static";
         * keywords[24].key = "struct";
         * keywords[25].key = "switch";
         * keywords[26].key = "typedef";
         * keywords[27].key = "union";
         * keywords[28].key = "unsigned";
         * keywords[29].key = "void";
         * keywords[30].key = "volatile";
         * keywords[31].key = "while";

}
int lookletter(char a)/*用来查找符号a是否在letter符号数组中,如果在返回0,否则返回-1*/
{
        int n;
        int k = strlen(letter);
        for(n=0;n<k;n++)
        {
                if(a == letter[n])
                        return 0;
        }
        return -1;

}
int findsymbol(char* b)/*用来查找标示符b[]是否在符号表中,如果在返回它的索引,否则返回-1*/
{
     int i;
     for(i=0;i<index; i++)
         {
                 if(strcmp(symbol[i].variable,b) == 0)
                         return i;
         }
     return -1;
}
int insert(char b[],int s)/*将指定的标示符插入符号表*/
{
    if(index>=symbol_size)
        {
                symbol_size+=add_size;
                symbol=(struct symbolize*)realloc(symbol,symbol_size*(sizeof(struct symbolize)));
                if(symbol==NULL)
                {
                        printf("realloc memery error,exit\n");
                        exit(1);
                }
        }
        symbol[index].variable=(char*)calloc(strlen(b),sizeof(char));
        strcpy(symbol[index].variable,b);
        symbol[index].mark = s;  /*用于表示标示符是ID还是NUM */
        symbol[index].type = 0;
        symbol[index].value =0;
        if(symbol[index].variable==NULL)
        {
                        printf("malloc memery error,exit\n");
                        /*exit(1); */
        }
        return index++;
}
int lookoperater(char a)/*用来查找符号a是否在operater符号数组中,如果在返回0,否则返回-1*/
{
        int n;
        int k = strlen(operater);
        for(n=0;n<k;n++)
        {
                if(a == operater[n])
                        return 0;
        }
        return -1;

}
int lookkey(char keys[])/*用来判断字符串是否为关键字*/
{
     int i;
     for(i=0;i<32; i++)
         {
                 if(strcmp(keys,* keywords[i].key) == 0)
                         return i;
         }
         return -1;
}

int lex()
{
        char ch;
        ch = fgetc(fp);/*从文件中读出一个字符  */
        while(1)
        {
                if(ch == ' '||ch == '\t')/*当字符为空格或制表符是,跳过*/
                    ;
                else if(ch == '\n')/*当字符为换行符时,行号加一 */
                     linenumber++;
                else if (isdigit(ch))/*当字符为数字时,执行以下操作*/
                {
                        char tokenval[100] = {'\0'};/*定义一个字符串数组用来存放数字*/
                        int k = 0;
                        int type =0;/*用来判断该常数的数值类型*/
                        int p;
                        tokenval[0] = ch;/*将第一个数字存入数组 */
                        ch = fgetc(fp);
                        k++;
                        while(isdigit(ch)||ch == '.')/*当接着读入的字符为数字,小数点,用来表示实数的l或L后缀时 */
                        {
                            if(ch=='.')
                               type = 1;

                            tokenval[k] = ch;/*否则将后继字符存入数组中 */
                            ch = fgetc(fp);
                            k++;
                        }
                        if(isalpha(ch)||ch == '_'||ch == '@'||ch == '#'||ch == '$'||ch == '?'||ch == '\\')
                        {/*当数字后面紧接着字母或其他不规范的符号是,输出表示符不规范的错误信息到错误文件中*/
                            tokenval[k] = ch;
                            printf("erro: 标识符命名错误,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,tokenval);
                            fprintf(erro,"erro: 标识符命名错误,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,tokenval);
                            while(ch != ' '&&ch!='\n')
                                 ch = fgetc(fp);

                        }
                        else/*最后回退一个字符,并将相关信息输出到输出文件中  */
                        {
                            fseek(fp,-1L,1);
                        printf("(num,%s)\n",tokenval);
                        fprintf(output,"(num,%s)\n",tokenval);
                        }
                         p = findsymbol(tokenval);/*判断该标示符是否在符号表中,p用来表示符号表索引*/
                         if(p==-1)
                         {
                              p = insert(tokenval,NUM);
                              fprintf(chart,"%d\t%s\t\t\tnull\n",index-1,tokenval);
                         }
                         if(type ==1)
                            symbol[p].type = symbol_float;
                         else
                            symbol[p].type = symbol_int;
                         return p+1000;
                }
                else if(isalpha(ch)||ch == '_')/*当字符为字母或下划线时,执行以下操作*/
                {
                   char sign[128]={'\0'};/*定义一个字符串数组用于存放标示符 */
                   int b = 0;
                   while(isalnum(ch)||ch == '_')/*当读入的字符为字母,数字或下划线时,持续将字符读入并存放到数组中  */
                   {
                      sign[b] = ch;
                      ch = fgetc(fp);
                      b++;
                      if(b>127)/*当标示符的长度超过128时,报错,并将错误信息输出   */
                      {
                            printf("erro: 操作符长度过长,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,sign);
                            fprintf(erro,"erro: 操作符长度过长,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,sign);
                            break;
                      }
                   }
                   if(ch == '@'||ch == '#'||ch == '$'||ch == '?'||ch == '\\')
                   {
                         printf("erro: 标识符命名错误,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,sign);
                         fprintf(erro,"erro: 标识符命名错误,出错地方在第%d行,出错单词是:(num,%s)\n",linenumber,sign);

⌨️ 快捷键说明

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