编译原理 - 词法分析器

样例输入:if num > 100 then num2 = 100 else num2 = 0 ; #

样例输出:

#include "cstdio"
#include "cstring"
#include "cctype"

const int ERROR = -1 ;
const int OVER = 0 ;

const int BEGIN = 1;
const int END = 2;
const int IF = 3;
const int THEN = 4;
const int WHILE = 5;
const int DO = 6;
const int CONST = 7;
const int VAR = 8;
const int CALL = 9 ;
const int PROCEDURE = 10;

const int ID = 11;
const int NUMBER = 12;

const int PLUS = 13;
const int SUB =14;
const int STAR = 15;
const int DIV = 16;
const int MOD = 17;
const int EQUAL = 18;//=
const int NE =19;//<>
const int LESS = 20;//<
const int MORE = 21;//>
const int LE = 22;//<=
const int ME = 23;//>=
const int ASSIGN = 24;//:=
const int LPAR = 25;//(
const int RPAR = 26;//)
const int COMMA = 27;//,
const int DOT = 28;//.
const int SEMICOLON = 29;//;

char buffer[200]= {‘\0‘};
char str[20];//存放构成单词符号的字符串*/
char ch;

int n;
int number;  //存放常量(整数)
int pstr,pbuffer;    

//关键字
int keyWordNum=10; //关键字
char keywords [10][10] = {"begin","end","if","then","while","do","const","var","call","procedure"};

//常数表
int numOfNumbers=0;
int numtab[100];

//变量表
int numOfVars=0;
char vartab[100][10];

//读取非空字符
void getBC()
{
    ch=buffer[pbuffer++];
    while(ch==‘ ‘)ch=buffer[pbuffer++];
}

//回退一个字符
void retract()
{
    ch=buffer[pbuffer--];
}

//对缓冲区的内容进行扫描
int scan()
{
    //初始化字符串
    pstr=0;
    for(int i=0; i<20; ++i)
    {
        str[i]=‘\0‘;
    }

    //初始化数字常量
    number=0;

    getBC();

    if( isalpha(ch) )
    {
        //读取标识符
        while( isalpha(ch) || isdigit(ch) )
        {
            str[pstr++]=ch;
            ch = buffer[pbuffer++];
        }
        str[pstr++]=‘\0‘;
        int syn=11;

        retract();//回退

        //判断是否是关键字
        for(int i=0; i<keyWordNum; ++i)
        {
            if(strcmp(str,keywords[i])==0)    //字符串的比较
            {
                syn=i+1;
                break;
            }
        }
        return syn;
    }
    else if( isdigit(ch) )
    {
        while( isdigit(ch) )
        {
            number = number*10 + ch-‘0‘;
            ch = buffer[pbuffer++];
        }
        retract();//回退
        return NUMBER;
    }
    else
    {
        switch(ch)
        {
        case‘+‘:
            //syn=13;
            str[0]=ch;
            return PLUS;
        case‘-‘:
            //syn=14;
            str[0]=ch;
            return SUB;
        case‘*‘:
            //syn=15;
            str[0]=ch;
            return STAR;
        case‘/‘:
            //syn=16;
            str[0]=ch;
            return DIV;
        case‘%‘:
            str[0]=ch;
            return MOD;
        case‘=‘:
            str[0]=ch;
            return EQUAL;
        case‘<‘:
            pstr=0;
            str[pstr++]=ch;
            ch=buffer[pbuffer++];
            if(ch==‘>‘)
            {
                str[pstr++]=ch;
                return NE;
            }
            else if(ch==‘=‘)
            {

                str[pstr++]=ch;
                return LE;
            }
            else
            {
                retract();
                return LESS;
            }
            break;
        case‘>‘:
            pstr=0;
            str[pstr++]=ch;
            ch=buffer[pbuffer++];
            if(ch==‘=‘)
            {
                str[pstr++]=ch;
                return ME;
            }
            else
            {
                retract();
                return MORE;
            }
            break;
        case‘:‘:
            pstr=0;
            str[pstr++]=ch;
            ch=buffer[pbuffer++];
            if(ch==‘=‘)
            {
                str[pstr++]=ch;
                return ASSIGN;
            }
            else
            {
                retract();
                return ERROR;
            }
            break;
        case‘(‘:
            str[0]=ch;
            return LPAR;
        case‘)‘:
            str[0]=ch;
            return RPAR;
        case‘,‘:
            str[0]=ch;
            return COMMA;
        case‘.‘:
            str[0]=ch;
            return DOT;
        case‘;‘:
            str[0]=ch;
            return SEMICOLON;
        case‘#‘:
            str[0]=ch;
            return OVER;
        default:
            return ERROR;
        }
    }

}

//插入变量,返回在变量表的位置
int insert_Var(const char * str)
{
    for(int i=0; i<numOfVars; i++)
    {
        if(strcmp(str,vartab[i])==0)    //字符串的比较
        {
            return i+1;
        }
    }
    strcpy(vartab[numOfVars++],str);
    return numOfVars;
}

//插入整数常量,返回位置
int insert_Num(int number)
{
    for(int i=0; i<numOfNumbers; i++)
    {
        if(numtab[i]==number)    //字符串的比较
        {
            return i+1;
        }
    }
    numtab[numOfNumbers++]=number;
    return numOfNumbers;
}

main()
{
    freopen("in.txt","r",stdin);//从文件读入数据

    printf("\n\nThe explanation :\n"
           "1. 1 to 10 : Keyword\n"
           "2. 11 : Other indicators by user\n"
           "3. 12 : Numbers\n"
           "4. 13 to 29 : Operators\n");

    printf("\nPlease input string:\n");

    //输入到缓冲区
    pbuffer=0;
    do
    {
        ch=getchar();
        buffer[pbuffer++]=ch;
    }
    while(ch!=‘#‘);

    //词法分析
    pbuffer=0;
    int loc,syn;
    do
    {
        syn = scan();
        switch(syn)
        {
        case -1:
            printf(" ERROR\n");
            break;
        case 12:
            //常数
            loc = insert_Num(number);
            printf("( %2d,%2d ) %d\n",syn,loc,number);
            break;
        case 11:
            //用户变量
            loc = insert_Var(str);
            printf("( %2d,%2d ) %s\n",syn,loc,str);
            break;
        default:
            //关键字
            printf("( %2d, - ) %s\n",syn,str);
        }
    }
    while(syn!=0);

    return 0;
}

  

时间: 2024-11-12 03:09:30

编译原理 - 词法分析器的相关文章

2016.9.30 编译原理-词法分析器

词法分析程序的功能: 对用户输入的字符串从左到右进行扫描和分解,根据词法规则识别出一个一个具有独立意义的单词符号,并产生相应单词的种别码:若是发现词法错误,则返回出错信息. 符号与种别码对照表: 用文法描述词法规则: 代码如下: #include<stdio.h> int main() { char str[500]; int i; printf("请输入一个字符串(输入#结束):"); gets(str); puts(str); return 0; }

编译原理简单词法分析器(first,follow,分析表)源码下载

编译原理(简单词法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90%E5%99%A8.zip

编译原理(简单自动词法分析器LEX)

编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%BC%89.zip

词法分析器——哈工大编译原理课程(一)

词法分析器——哈工大编译原理课程(一) 程序输入:从code.txt文件中读取内容 程序输出:识别出的单词序列,格式为:(种别码,属性值) ①对于关键字和运算符.分隔符来说,输出格式为(种别码,0),因为每个种别码能唯一地标识出是哪个单词 ②对于标识符来说,输出格式为(id的种别码即36,在哈希桶中的位置) ③对于常量(整数.浮点数.字符串)来说,输出格式为(种别码,在数组中的位置) 1 #include<stdio.h> 2 #include<stdlib.h> 3 #inclu

编译原理 - 1 手撸状态机词法分析器

感谢vczh轮子叔的坑了的教程,我的编译原理第一次入了个门,词法分析写完了,今后可以看看书继续往下学了. http://www.cppblog.com/vczh/archive/2014/03/02/206014.html 词法分析,就是对于一段代码,把他们分割成一个个的token,同时记录他们的行列号,丢掉不必要的信息,这个词法分析器很简单,简单的状态机就能胜任,用正则就没有自己造轮子的快感了,所以要自己手撸状态机拆token出来. 模仿vczh的语言,我的语言包括了以下要素 标识符:大小写字

编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分析器

编译原理实战--使用Lex/Flex进行编写一个有一定词汇量的词法分析器 by steve yu 2019.9.30 参考文档:1.https://blog.csdn.net/mist14/article/details/486413492.https://wenku.baidu.com/view/1c6398903868011ca300a6c30c2259010202f3a4.html 1.Flex工具的概述 Flex工具是生成C语言的工具,我们在日常生活中,如果直接使用C语言进行编写词法分析

&lt;编译原理 - 函数绘图语言解释器(1)词法分析器 - python&gt;

<编译原理 - 函数绘图语言解释器(1)词法分析器 - python> 背景 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现 解释器分为三个实现块: 词法分析器:用于识别一条语句中的关键词是否符合预先定义的规则. 语法分析器:用来确定一条语句是否满足语法规则. 解释器:用来确定满足语法规则的句子,在意思上是否符合要求. 设计思路: 设计记号:词法分析器读取一个序列并根据构词规则把序列转化为记号流 定义一个字典:把所有符合一个模式的保留字.常量名.参数名.函数名等放进字

编译原理:C语言词法分析器

编译原理的实验:完成对C语言的词法分析 先说一下整体框架: 基类:Base  封装了一些基础的字符判断函数,如下: int charkind(char c);//判断字符类型 int spaces(char c); //当前空格是否可以消除 int characters(char c);//是否是字母 int keyword(char str[]);//是否是关键字 int signwords(char str[]);//是否是标识符 int numbers(char c);//是否是数字 in

学习编译原理

刚刚进入大二,初学习到编译原理,一门新的技术,而且学习起来会比较抽象,不过好在大一曾学习到VC这一门东西,在学习此门课程之前,已在网上了解到不少学习这门课该提前遇到道德东西,也了解到很多人学习这门课的问题,在他们的经验中知道了不少学习方法,希望自己能在日后中用得上.例如这个就觉得很不错:删繁就简,避重就轻.网上流传较广的一篇<编译原理学习导论>(作者四川大学唐良)就基本是这种思路,对于词法分析,作者避免了自动机理论和集合论推演的介绍,直接搬出源码来,大大降低了理解难度,对于语法分析,作者介绍了