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#

结果:

相关推荐
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
java·开发语言·unity·c#·游戏引擎·里氏替换原则
@菜鸟进阶记@1 小时前
java根据Word模板实现动态填充导出
java·开发语言
卖芒果的潇洒农民1 小时前
Lecture 6 Isolation & System Call Entry
java·开发语言
AAA.建材批发刘哥1 小时前
Linux快速入门-Linux文件系统管理
linux·运维·服务器·c语言·学习方法
SomeB1oody1 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust
Kisorge2 小时前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
轻口味3 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学4 小时前
QT-简单视觉框架代码
开发语言·qt
威桑4 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略