SCAU 编译原理 实验1 词法分析实验

实验内容:参考附录C.1

设计一个简单语言的词法分析程序,要求能够正确处理关键字、运算符(单个符号的和复合的运算符如>、>=)、分界符、标识符、常数等单词,以及不是单词的换行回车、注释。

c 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define _KEY_WORD_END "waiting for your expanding"

typedef struct
{
    int typenum;
    char *word;
} WORD;
char input[255];
char token[255]="";
int p_input;
int p_token;

int hang=1;//行数
char ch;
bool flag = true; //正常输出

char * rwtab[]= {"begin","if","then","while","do","end",_KEY_WORD_END};
WORD * scaner();

int main()
{
    int over=1;
    WORD* oneword=new WORD;
    printf("Enter Your words(end with #):");
    scanf("%[^#]s",input);
    p_input=0;
    printf("\nYour words:");
    printf("\n-------------------------------\n");
    printf("% s \n",input);
    printf("-------------------------------\n\n");
    while(over<1000&&over!=-1)
    {
        oneword=scaner();//词扫描函数
        if(oneword->typenum<1000&&flag)//正常输出
        {
            printf("line:%d  (% d,% s )\n",hang,oneword->typenum,oneword->word);
        }
        flag=true;//置为默认正常输出
        over=oneword->typenum;
    }
    printf("\npress # to exit:");
    scanf("% [^#]s",input);
}

//从输入缓冲区读取一个字符到ch
char m_getchar()
{
    ch=input[p_input];
    p_input=p_input+1;
    return (ch);
}

//去掉空白字符
void getbc()
{
    while(ch==' '||ch==10)
    {
        if(ch=='\n')
            hang++;
        ch=input[p_input];
        p_input=p_input+1;
    }
}

//拼接单词
void concat()
{
    token[p_token]=ch;
    p_token=p_token+1;
    token[p_token]='\0';
}

//判断是否为字母
int letter()
{
    if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
        return 1;
    else
        return 0;
}

//判断是否为数字
int digit()
{
    if(ch>='0'&&ch<='9')
        return 1;
    else
        return 0;
}

//检索关键字表格
int reserve()
{
    int i=0;
    while(strcmp(rwtab[i],_KEY_WORD_END))
    {
        if(!strcmp(rwtab[i],token))
            return i+1;
        i=i+1;
    }
    return 10;
}

//回退一个字符
void retract()
{
    p_input=p_input-1;
}

//数字转化成二进制,未补全
char* dtb()
{
    return NULL;
}

//词法扫描程序
WORD* scaner()
{
    WORD *myword=new WORD;
    myword->typenum=10;
    myword->word="";
    p_token=0;

    m_getchar();

    getbc();

    if(letter())
    {
        while(letter()||digit())
        {
            concat();//拼接单词
            m_getchar();//从输入缓冲区读取一个字符到ch
        }
        retract();//回退一个字符
        myword->typenum=reserve();//检索关键字表格
        myword->word=token;
        return(myword);
    }
    else if(digit())
    {
        while(digit())
        {
            concat();
            m_getchar();
        }
        retract();
        myword->typenum=20;
        myword->word=token;
        return(myword);
    }
    else if(ch=='/'){
        m_getchar();
        if(ch=='/'){ //单行注释
            while(ch!='\n'){ //如果不是换行
                m_getchar();//一直读取下一个字符
            }
            flag=false;//不输出
            retract();//回退字符,不然行数无法++
            return(myword);
        }
        else if(ch=='*'){ //多行注释开始符号
            while(1){
                m_getchar();//一直读取下一个字符
                if(ch=='\n'){
                    hang++;//读到换行行数++
                }
                if(ch=='*'){ //多行注释结束符号
                    m_getchar();
                    if(ch=='/'){
                        flag=false;//不输出
                        return(myword);
                    }
                }
            }
        }
        else{
            retract();
            myword->typenum=25;
            myword->word="/";
            return(myword);
        }
    }
    else switch(ch)
        {
        case '=':
            m_getchar();
            if(ch=='=')
            {
                myword->typenum=39;
                myword->word="==";
                return(myword);
            }
            retract();
            myword->typenum=21;
            myword->word="=";
            return(myword);
            break;
        case '+':
            myword->typenum=22;
            myword->word="+";
            return(myword);
            break;
        case '-':
            myword->typenum=23;
            myword->word="-";
            return(myword);
            break;
        case '*':
            myword->typenum=24;
            myword->word="*";
            return(myword);
            break;
        case '(':
            myword->typenum=26;
            myword->word="(";
            return(myword);
            break;
        case ')':
            myword->typenum=27;
            myword->word=")";
            return(myword);
            break;
        case '[':
            myword->typenum=28;
            myword->word="[";
            return(myword);
            break;
        case ']':
            myword->typenum=29;
            myword->word="]";
            return(myword);
            break;
        case '{':
            myword->typenum=30;
            myword->word="{";
            return(myword);
            break;
        case '}':
            myword->typenum=31;
            myword->word="}";
            return(myword);
            break;
        case ',':
            myword->typenum=32;
            myword->word=",";
            return(myword);
            break;
        case ':':
            myword->typenum=33;
            myword->word=":";
            return(myword);
            break;
        case ';':
            myword->typenum=34;
            myword->word=";";
            return(myword);
            break;
        case '>':
            m_getchar();
            if(ch=='=')
            {
                myword->typenum=37;
                myword->word=">=";
                return(myword);
            }
            retract();
            myword->typenum=35;
            myword->word=">";
            return(myword);
            break;
        case '<':
            m_getchar();
            if(ch=='=')
            {
                myword->typenum=38;
                myword->word="<=";
                return(myword);
            }
            retract();
            myword->typenum=36;
            myword->word="<";
            return(myword);
            break;
        case '!':
            m_getchar();
            if(ch=='=')
            {
                myword->typenum=40;
                myword->word="!=";
                return(myword);
            }
            retract();
            myword->typenum=-1;
            myword->word="ERROR";
            return(myword);
            break;
        case '\0':
            myword->typenum=1000;
            myword->word="OVER";
            return(myword);
            break;
        default:
            myword->typenum=-1;
            myword->word="ERROR";
            return(myword);
        }
}

测试数据:

c 复制代码
begin x:=9;
if x>0 then x:=2*x+1/3;
/*
aaaaaaaaaaaaa
bbbbbbbbbbbbb
*/
//ccccccccccc
//ddddddddddd
/*eeeeeeeee*/
end#

结果:

相关推荐
浪子明X9 小时前
十六位账本怎样发现传输差错:Internet Checksum 生活类比
开发语言
xiangyun6112 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun6112 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法
白远山13 小时前
家政服务家政社区派单实战:调度系统架构设计与实现指南
java·开发语言·小程序·架构·需求分析
Logic10114 小时前
C语言/数据结构数组题解:数字列表加一(Plus One)——进位处理与数组扩展
c语言·数据结构·模拟·数组·时间复杂度·算法题·进位
Escalating_xu14 小时前
【C语言常见概念】从第一行代码到字符串结束标志:一次打通编译、main、ASCII、转义字符与注释
c语言·c++
DevRay14 小时前
Java 21虚拟线程深度实战:告别线程池焦虑,百万并发吞吐量直接翻倍(原理+代码+避坑)
java·开发语言
Navigator_Z14 小时前
LeetCode //C - 1250. Check If It Is a Good Array
c语言·算法·leetcode
free-elcmacom14 小时前
C++学习<1>程序分区
开发语言·c++
醉颜凉14 小时前
Java 必看:如何彻底避免 HashMap 多线程死循环问题?
java·开发语言