(编译原理)实验一 PL/O语言的词法分析程序GETSYM

一. 实验目的

1.为了更好的配合《编译原理》有关词法分析章节的教学
2.加深和巩固学生对于词法分析的了解和掌握
3.让学生初步的认识PL/0语言的基础和简单的程序编写
4.学生通过本实验能够初步的了解和掌握程序词法分析的整个过程
5.高学生的上机和编程过程中处理具体问题的能力

二. 实验要求

1.做本实验之前要先阅读完总体的预备知识以及本实验相关的基础知识
2.实验要求自己独立的完成,不允许抄袭别人的实验结果
3.做本实验之前要先阅读完总体的预备知识以及本实验相关的基础知识
4.编写和调试过程中出现的问题最好做一下记录
5.实验程序调试完成后,提交给实验教师检查,并由老师给予相应的成绩
6.实验完成后,要上交实验报告。

三. 实验内容

词法分析程序GETSYM的功能包括:
1.滤空格,空格在词法分析时是一种不可缺少的界符,而在语法分析时是无用的,所以必须滤掉。
2.识别保留子:设有一张保留字表。对每个字母打头的字母、数字字符串要查此表。若查着则为保留字,对应的类别放在SYM中。如IF对应值为THENSYM。
3.识别标识符:对用户定义的标识符将IDENT放在SYM中,标识符本身的值放在ID中。
4.拼数:当所取单词是数字时,将树的类别NUMBER放在SYM中,数值本身的值放在NUM中。
5.拼复合词:对两个字符组成的算符如:>=、:=、<= 等单词,识别后将类别送SYM中。
6.打印源程序:为边读入字符边打印

实现代码:

#include <stdio.h>
#include <string.h>
#define norw 13         /*关键字个数*/
#define nmax 14         //number的最大位数
#define al 10           //符号的最的长度 符号就是+ - 神马的
#define cxmax 200       //最多的虚拟机代码数
/*
enum symbol {
    nul, ident, number, plus, minus, times, slash, oddsym, eql, neq,
    lss, leq, gtr, geq, lparen, rparen, comma, semicolon, period, becomes,
    beginsym, endsym, ifsym, thensym, whilesym, writesym, readsym, dosym,
    callsym, constsym, varsym, procsym,
};
*/
FILE* fa1;              //输出分析的文件和首地址 首地址是虚拟机指针
char ch;                //getch读取的字符
//enum symbol sym;
char id[al+1];          //当前的ident
int num;
int cc, ll;             //getch计数器
int cx;                 //虚拟机代码指针,取值范围0-cxmax-1
char line[81];
char a[al+1];           //读取一个符号 暂时存在这里
char word[norw][al];    //保留字13个 就是begin end if 什么的
//enum symbol wsym[norw]; //保留字对应的符号 begin对应beginsym
//enum symbol ssym[256];  //单字符的符号值
 
FILE* fin;
FILE* fout;
char fname[al];         //输入的文件名
int err;
 
#define getchdo         if(-1==getch()) return -1;
 
void error(int n);
 
void error(int n)
{
    char space[81];
    memset(space, 32, 81);
    space[cc-1] = 0;
    printf("****出现错误\n");
    fprintf(fa1, "****出现错误\n");
    err++;
}
int getch()
{
    if(cc == ll)
    {
        if(feof(fin))
        {
            printf("\n读完了!\n");
            return -1;
        }
        ll = 0;
        cc = 0;
        //printf("%d ", cx);
        //fprintf(fa1, "%d", cx);
        ch = ' ';
        while(ch != 10)
        {
            if(fscanf(fin, "%c", &ch) == EOF)
            {
                line[ll] = 0;
                break;
            }
            printf("%c", ch);
            line[ll] = ch;
            ll++;
        }
        printf("\n");
    }
    ch = line[cc];
    cc++;
    return 0;
}
 
int getsym()
{
    int i, j, k;
    while(ch == ' ' || ch == 10 || ch == 9||ch== 13)
    {
        getchdo;
    }
    if(ch >= 'a' && ch <= 'z')
    {
        k = 0;
        do
        {
            if(k < al)
            {
                a[k] = ch;
                k++;
            }
            getchdo;
        }while(ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9');
        a[k] = '\0';
        strcpy(id, a);
        i = 0;
        j = norw-1;
        do
        {
            k = (i+j)/2;
            if(strcmp(id, word[k]) <= 0)
                j = k-1;
            if(strcmp(id, word[k]) >= 0)
                i = k+1;
        }while(i <= j);
 
        if(i-1 > j)
        {
            printf("保留字 (1,'%s')\n", id);
        }
        else
        {
            printf("标识符 (3,'%s')\n", id);
        }
    }
    else
    {
        if(ch >= '0' && ch <= '9')
        {
            k = 0;
            num = 0;
            //sym = number;
            do
            {
                num = num * 10 + ch - '0';
                k++;
                getchdo;
            }while(ch >= '0' && ch <= '9');
            k--;
            if(k > nmax)
            {
                error(30);
            }
            printf("整  数 (2,'%d')\n",num);
        }
        else
        {
            if(ch == ':')
            {
                getchdo;
                //k=0;
                //b[k]=ch;
                if(ch == '=')
                {
                    //sym = becomes;
                    printf("运算符 (4,':=')\n");
                    getchdo;
                }
                else
                {
                     printf("error!不允许单独使用’:‘\n");
                }
            }
            else
            {
                if(ch == '<')
                {
                    getchdo;
                    if(ch == '=')
                    {
                        printf("运算符 (4,'<=')\n");
                        getchdo;
                    }
                    else
                    {
                        printf("运算符 (4,'<')\n");
                    }
                }
                else
                {
                    if(ch == '>')
                    {
                        getchdo;
                        if(ch == '=')
                        {
                            printf("运算符 (4,'>=')\n");
                            getchdo;
                        }
                        else
                        {
                            printf("运算符 (4,'>')\n");
                        }
                    }
                    else
                    {
                        if(ch=='+')
                        {
                            printf("运算符 (4,'+')\n");
                            getchdo;
                        }
                        else if(ch=='-')
                        {
                            printf("运算符 (4,'-')\n");
                            getchdo;
                        }
                        else if(ch=='*')
                        {
                            printf("运算符 (4,'*')\n");
                            getchdo;
                        }
                        else if(ch=='/')
                        {
                            printf("运算符 (4,'/')\n");
                            getchdo;
                        }
                        else if(ch=='#')
                        {
                            printf("运算符 (4,'#')\n");
                            getchdo;
                        }
                        else if(ch=='(')
                        {
                            printf("分界符 (5,'(')\n");
                            getchdo;
                        }
                        else if(ch==')')
                        {
                            printf("分界符 (5,')')\n");
                            getchdo;
                        }
                        else if(ch=='{')
                        {
                            printf("分界符 (5,'{')\n");
                            getchdo;
                        }
                        else if(ch=='}')
                        {
                            printf("分界符 (5,'}')\n");
                            getchdo;
                        }
                        else if(ch=='\"')
                        {
                            printf("分界符 (5,'\"')\n");
                            getchdo;
                        }
                        else if(ch=='\!')
                        {
                            printf("分界符 (5,'\!')\n");
                            getchdo;
                        }

                        else if(ch==',')
                        {
                            printf("分界符 (5,',')\n");
                            getchdo;
                        }
                        else if(ch==';')
                        {
                            printf("分界符 (5,';')\n");
                            getchdo;
                        }
                        else if(ch=='.')
                        {
                            printf("分界符 (5,'.')\n");
                            getchdo;
                        }
                        else
                        {
                            printf("error!请检查代码是否拼写正确!\n");
                            return -1;
                        }
                    }
                }
            }
        }
    }
    return 0;
}
void init()
{
    /*
    int i;
    for(i = 0; i < 256; i++)
        ssym[i] =  nul;
    ssym['+'] = plus;
    ssym['-'] = minus;
    ssym['*'] = times;
    ssym['/'] = slash;
    ssym['('] = lparen;
    ssym[')'] = rparen;
    ssym['='] = eql;
    ssym[','] = comma;
    ssym['.'] = period;
    ssym['#'] = neq;
    ssym[';'] = semicolon;
*/
    strcpy(&(word[0][0]), "begin");
    strcpy(&(word[1][0]), "call");
    strcpy(&(word[2][0]), "const");
    strcpy(&(word[3][0]), "do");
    strcpy(&(word[4][0]), "end");
    strcpy(&(word[5][0]), "if");
    strcpy(&(word[6][0]), "odd");
    strcpy(&(word[7][0]), "procedure");
    strcpy(&(word[8][0]), "read");
    strcpy(&(word[9][0]), "then");
    strcpy(&(word[10][0]), "var");
    strcpy(&(word[11][0]), "while");
    strcpy(&(word[12][0]), "write");
/*
    wsym[0] = beginsym;
    wsym[1] = callsym;
    wsym[2] = constsym;
    wsym[3] = dosym;
    wsym[4] = endsym;
    wsym[5] = ifsym;
    wsym[6] = oddsym;
    wsym[7] = procsym;
    wsym[8] = readsym;
    wsym[9] = thensym;
    wsym[10] = varsym;
    wsym[11] = whilesym;
    wsym[12] = writesym;
*/
 
}
int main()
{
    printf("请输入要分析的文件名:\n");
    scanf("%s", fname);
    fin = fopen(fname, "r");
    if(fin)
    {
        /*
        printf("请输入要保存的文件名\n");
        scanf("%s", fname);
        fa1 = fopen(fname, "w");
        */
 
        init();
        printf("\n分析完毕!\n\n");
        err = 0;
        cc = cx = ll = 0;
        ch = ' ';
        while(getsym() != -1)
        {
            //printf("111\n");
        }
 
 
    }
    else
    {
        printf("找不到文件\n");
    }
    printf("\n");
    return 0;
}

001.txt文档内容:

#include <stdio.h>
int main()
{
	printf("hello,world!");
	return 0; 
} 

实验结果:
在这里插入图片描述

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 合肥工业大学编译原理实验1是一个词法分析程序实验,使用Python语言进行编写。 词法分析编译原理中的一个重要内容,主要负责将源代码文件中的字符序列分割成有意义的词法单元,如标识符、关键字、运算符、分隔符等,为后续的语法分析和语义分析做好准备。 Python语言由于其简洁易学和强大的功能,成为许多编译原理实验的首选语言之一。在这个实验中,我们将使用Python编写一个词法分析程序,实现对源代码的分析。 首先,我们需要读取源代码文件,将其转换为字符流,传递给词法分析程序程序会逐个读取字符,并根据事先定义好的正则表达式进行匹配,识别出相应的词法单元。 实验中可能会用到的一些正则表达式包括:匹配标识符的正则表达式、匹配关键字的正则表达式、匹配运算符的正则表达式、匹配数值常量的正则表达式等。 在识别出词法单元后,程序会生成一个词法单元表,记录下每个词法单元的类型和对应的值。该词法单元表将作为语法分析的输入。 在编写这个词法分析程序时,需要注意处理多种可能的错误情况,如不合法的字符、不符合规范的标识符等。可以通过添加捕获异常的机制来处理这些错误情况,并及时进行提示。 综上所述,通过本次实验,我们可以学习到编译原理词法分析的基本概念和原理,并通过实践来深入理解。通过使用Python语言编写词法分析程序,我们能够更好地掌握Python语言的特性和应用。 ### 回答2: 编译原理实验一是词法分析程序实验,要求使用Python语言编写程序。本实验的主要目的是通过实现词法分析器,能够将输入的源代码分解成一个个的词法单元。在合肥工业大学编译原理实验一的词法分析程序实验中,我们需要实现以下功能: 1. 识别并分类各种类型的词法单元,比如标识符、数字、关键字、运算符、界符等。 2. 跳过空格、换行符和注释等不影响程序执行的字符。 3. 输出每个词法单元的类型和值,方便后续程序分析和处理。 为了完成这个实验,我们可以使用Python语言提供的字符串处理函数和正则表达式库来帮助我们实现上述功能。下面是一个简单的实现示例: ```python import re def lexer(code): # 定义正则表达式,用于识别各种类型的词法单元 keywords = ['if', 'else', 'while', 'for', 'int', 'float', 'char'] # 关键字 operators = ['+', '-', '*', '/', '=', '==', '!=', '<', '>', '<=', '>='] # 运算符 delimiters = [';', '(', ')', '{', '}'] # 界符 pattern_keywords = '|'.join(keywords) pattern_operators = '|'.join(re.escape(op) for op in operators) pattern_delimiters = '|'.join(re.escape(dl) for dl in delimiters) pattern = f'({pattern_keywords})|({pattern_operators})|({pattern_delimiters})|\w+|\d+' # 开始词法分析 tokens = re.findall(pattern, code) for token in tokens: if token[0]: print(f'关键字:{token[0]}') elif token[1]: print(f'运算符:{token[1]}') elif token[2]: print(f'界符:{token[2]}') elif token[3]: print(f'标识符:{token[3]}') elif token[4]: print(f'数字:{token[4]}') # 测试代码 code = ''' int main() { int a = 10; if (a > 0) { a = a - 1; } return 0; } ''' lexer(code) ``` 以上是一个简单的词法分析程序实验的实现示例,通过使用正则表达式来识别各种词法单元,并打印出每个词法单元的类型和值。实验中可以根据具体需求扩展代码,添加更多的词法单元类型和识别规则。 ### 回答3: 合肥工业大学编译原理实验1是关于词法分析程序实验词法分析是编译过程中的第一个步骤,主要任务是将源代码分解为一个个的词法单元。在这个实验中,使用Python编写词法分析程序。 在开始编写程序之前,首先需要明确程序的功能和输入输出要求。根据实验要求,我们需要编写一个可以识别并输出源代码中的各个词法单元的程序。 编写词法分析程序的基本思路如下: 1. 读取源代码文件,将其按照字符进行分解; 2. 针对每一个字符,判断其所属的词法单元类型; 3. 将每个词法单元及其类型输出。 在Python中,可以利用正则表达式来匹配词法单元的模式。通过定义适当的正则表达式,可以方便地判断当前字符所属的词法单元类型。可以考虑使用re模块来处理正则表达式。 实验的输入是一个源代码文件,首先需要使用Python的文件操作来读取源文件的内容。之后,可以利用re模块的正则表达式相关函数,对每个字符进行匹配和识别。最后,将每个词法单元及其类型输出到一个文件中。 编写完程序后,可以使用一些示例的源代码文件进行测试,验证程序的正确性。如果发现有问题,可以通过调试和修改代码来改进程序的逻辑和功能。 总之,合肥工业大学编译原理实验1词法分析程序实验使用Python编写,通过正则表达式对源代码进行分析和识别,并将每个词法单元及其类型输出到一个文件中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值