词法分析

一笑奈何 提交于 2019-12-03 23:20:41

我的博客

要求

输入:源程序文件
输出:二元组(syn,token或sum)构成的序列(文件),其中:syn为单词种别码,token为存放的单词自身字符串,sum为整型常量。
已知待分析的C语言子集的词法:
1、关键字: main if else int while char 均为小写。
2、专用符号: = + - * / < <= > >= == != ; , { } ( )
3、其他标记ID和NUM通过以下正则式定义:

ID: letter(letter|digit)*
NUM: digit digit*
letter→a|b|c|d…|z|A|B|C…|Z
digit →0|1|2|3|4|5|6|7|8|9

4、空格由空白、制表符、换行符组成,用来分隔ID、NUM、专用符号与关键字,词法分析阶段常被忽略。
各种单词符号对应的种别码如下表:

源程序

程序中涉及两个文件:
input.txt 程序测试数据
output.txt 输出测试结果

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

char TOKEN[20];
char TABLE[6][10] = {{"main"},{"int"},{"char"},{"if"},{"else"},{"while"}};

int lookup(char arr[]) {
    int i;
    for (int i = 0; i < 6; ++i) {
        if (!strcmp(arr,TABLE[i]))
            return i+1;
    }
    return 0;
}
// 扫描器
void scanner(FILE* fp) {
    char ch, tmp;
    int i, c;
    FILE* wfp = fopen("output.txt","w");

    while (ch != EOF) { // 一次循环即扫描一个词 
        i = 0;
        ch = getc(fp);

        if (isalpha(ch)){   // 字母开头 
            TOKEN[i++] = ch;
            while (isalpha(ch=getc(fp))|| isdigit(ch)) {
                TOKEN[i++] = ch;
            }
            TOKEN[i] = '\0';
            fseek(fp,-1,1);
            c = lookup(TOKEN);
            if (c != 0)
                fprintf(wfp,"(%d,%s)\n",c,TOKEN);   // 关键字 
            else
                fprintf(wfp,"(10,%s)\n",TOKEN);  // 标识符 
        } else if (isdigit(ch)) {   // 数字开头 
            TOKEN[i++] = ch;
            while (isdigit(ch=getc(fp))) {
                TOKEN[i++] = ch;
            }
            TOKEN[i] = '\0';
            fseek(fp,-1,SEEK_CUR);
            fprintf(wfp,"(20,%s)\n",TOKEN);    // 数字
        } else {    // 其它符号开头 
            switch (ch) {
                case ' ': break;
                case '\n': break;
                case '\t': break;
                case EOF: break;
                case '=': ch=getc(fp);
                    if (ch == '=') {
                        fprintf(wfp,"(36,==)\n"); break;
                    }
                    else {
                        fprintf(wfp,"(21,=)\n"); break;
                    } 
                case '+': fprintf(wfp,"(22,+)\n"); break;
                case '-': fprintf(wfp,"(23,-)\n"); break;
                case '*': fprintf(wfp,"(24,*)\n"); break;
                case '/': fprintf(wfp,"(25,/)\n"); break;
                case '(': fprintf(wfp,"(26,()\n"); break;
                case ')': fprintf(wfp,"(27,))\n"); break;
                case '{': fprintf(wfp,"(28,{)\n"); break;
                case '}': fprintf(wfp,"(29,})\n"); break;
                case ',': fprintf(wfp,"(30,,)\n"); break;
                case ';': fprintf(wfp,"(31,;)\n"); break;
                case '>': ch=fgetc(fp);
                    if (ch == '=') {
                        fprintf(wfp,"(34,>=)\n"); break;
                    }
                    else {
                        fprintf(wfp,"(32,>)\n"); break;
                    }
                case '<': ch=fgetc(fp);
                    if (ch == '=') {
                        fprintf(wfp,"(35,<=)\n"); break;
                    }
                    else {
                        fprintf(wfp,"(33,<)\n"); break;
                    }
                case '!': tmp = ch;
                    ch=getc(fp);
                    if(ch == '=')
                    {
                        fprintf(wfp,"(37,!=)\n"); 
                        break;
                    }
                    else 
                    {
                        fprintf(wfp,"error:(0,%c)\n",tmp); 
                        fseek(fp,-1,1);
                        break;
                    }
                default:
                    fprintf(wfp,"error:(0,%c)\n",ch); break;
            }
        }
    }
    fclose(wfp); 
}

int main(){
    FILE* fp;
    char ch;
    if ((fp=fopen("input.txt","r")) == NULL){
        printf("文件打开错误!\n");
        return 0;
    }
    scanner(fp);
    fclose(fp);

    return 0;
}

运行结果截图

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!