精华内容
下载资源
问答
  • 词法分析器的设计与实现

    千次阅读 2018-04-19 10:40:05
    词法分析器的设计与实现词法分析器介绍 词法分析是从左到右扫描每行源程序的符号,拼成单词,换成统一的机内表示形式——TOKEN字,送给语法分析程序。 TOKEN字是一个二元式:(单词种别码,自身值)。单词自身值按...

    词法分析器的设计与实现


    词法分析器介绍

    词法分析是从左到右扫描每行源程序的符号,拼成单词,换成统一的机内表示形式——TOKEN字,送给语法分析程序。

    TOKEN字是一个二元式:(单词种别码,自身值)。单词自身值按如下规则给出:

    ​ 1.标识符的自身值是他在符号表的入口位置。

    ​ 2.常数的自身值是常数本身(或者其他二进制数值)。

    ​ 3.关键字和界限符的自身值为本身。

    词法分析器功能

    1.输入:字符串(带进行词法分析的源程序),可从键盘直接输入或从文件读入。

    输出:由(种别码,自身值)所组成的二元组序列。

    单词的种别码是语法分析需要的信息,可用整数编码表示,例如:标识符的种别码为1,常数为2,保留字为3,运算符为4,界符为5。

    单词的自身值是编译其他阶段需要的信息,标识符的自身是标识符在符号表入口,其他类型单词的自身值是其本身。

    例如:输入:if i >= 15 then x := y ;

    ​ 输出:

    ​ (3,if)

    ​ (1,0)//i符号的入口为0

    ​ (4,>=)

    ​ (2,15)

    ​ (3,then)

    ​ (1,1)//x符号的入口为1

    ​ (4,:=)

    ​ (1,2)//y符号的入口为2

    ​ (5,;)

    2.功能:

    a.滤过空格。

    b.识别保留字:if then else while do 等。

    c.识别标识符:<字母>(<字母>|<数字>)。

    d.识别整数:0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)。

    e.识别典型的运算符和分隔符,例如:+ - * / > >= <= ( ) ;

    3.具有一定的错误处理功能,例如:能检查出程序语言的字符集以外的非法字符。

    源码附带注释

    #include<string>
    #include<stdlib.h>
    #include<stdio.h>
    using namespace std;
    
    bool isLetter(char ch){//isLetter 标识符
        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) return true;
        else return false;
    }
    
    bool isDigit(char ch){//isDigit 常数
        if (ch >= '0' && ch <= '9') return true;
        else return false;
    }
    
    bool isOperators(char ch){// isOperators 运算符
        if (ch == '+' || ch == '*' || ch == '-' || ch == '/' || ch == '=' || ch == ':' || ch == '<' || ch == '>') return true;
        else return false;
    }
    bool isDelimiter(char ch){// isDelimiter 界符
        if (ch == ',' || ch == ';' || ch == '.' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}' || ch == '#') return true;
        else return false;
    }
    bool isBlank(char ch){
        if (ch == ' ' || ch == '\t') return true;
        else return false;
    }
    char  key[34][10] = { "main",
    "auto", "short", "int", "long", "float", "double", "char", "struct"
    , "union", "enum", "typedef", "const", "unsigned", "signed", "extern", "register"
    , "static", "volatile", "void", "if", "else", "switch", "case", "for"
    , "do", "while", "goto", "continue", "break", "default", "sizeof", "return","then"};
    
    
    void main()
    {
    back:
        char Sourcecode[100] = "";
        int number=0;
        int h=0;
        char hh[100][10]={'\0'};
        //声明变量
        printf("请输入程序段,标识符为1,常数为2,关键字为3,运算符4,界符5\n");
        gets(Sourcecode);
        //读入程序段放入firstcode
        
        for (int i = 0; i < 100; i){
            //char delimiter[2] = "";
            int j = 0;  //letter  标识符
            int l = 0;   //digit  常数
            int k = 0;   //operators  运算符
    
            int b = 0;   //类型编号
            char num[10] = "";
            char word[10] = "";  
            if (isBlank(Sourcecode[i]) == 1){
                i += 1;
            }//去空格
            else{
                if (isLetter(Sourcecode[i]) == 1)         //是否为字母
                {                                             //是
                    
                    do
                    {
                        if (j < 10){
                            word[j] = Sourcecode[i];
                            j++;
                        }
                    } while (isDigit(Sourcecode[++i]) == 1|| isLetter(Sourcecode[i]) == 1);//常数||标识符
    
                    //*~~~*
                    int a = 0;
                    while (a < 34){
                        if (strcmp(key[a], word) == 0){
                            b = 3;
                            a++;
                            break;
                        }
                        else {
                            b = 1;
                            a++;
                            //否
                        }
                    }
                    if (b == 3){
                        printf("(3,%s)\n", word);
                    }//~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    if (b == 1){
                        int q=0;
                        for(int qq=0;strcmp(hh[qq],"")!=0;qq++){
                            if(strcmp(word,hh[qq])==0){
                                q=1;break;
                            }
                        }
                        if(q==1){
                            printf("(1,%d)\n",qq);
                            q=0;
                        }else{
                            for(qq=0;qq<j;qq++){
                                hh[h][qq]=word[qq];
                            }
                            printf("(1,%d)\n",h);
                            h++;
                        }
                    /*  int qq,yy=0;
                        if(h==0){
                            for(qq=0;qq<j;qq++){
                                hh[0][qq]=word[qq];
                            }
                            printf("(1,%d)\n",h);
                            h++;
                        }else{
                            for(qq=0;qq<h;qq++){
                                if(strcmp(hh[qq], word)==0){
                                    yy=1;
                                    break;
                                }
                            }
                            if(yy==0){
                                for(qq=0;qq<j;qq++){
                                    hh[h][qq]=word[qq];
    
                                }
                                printf("(1,%d)\n",h);
                                h++;
                                yy=0;
                            }
                            else{
                                for(qq=0;qq<h;qq++){
                                    if(strcmp(hh[qq], word)==0)
                                        printf("(1,%d)\n",qq);
                                    yy=0;
                                }
                            }
                        }*/
                        //
                    }
                    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                }
                else if (isDigit(Sourcecode[i]) == 1)//常数
                {int c = 0;
                    while (isDigit(Sourcecode[i])){
                        
                        num[c] = Sourcecode[i];
                        i += 1;
                        c++;
                    }
                    printf("(2,%s)\n", num);
                }
                else if (isDelimiter(Sourcecode[i]) == 1){//界符
                    
                    printf("(5,%c)\n", Sourcecode[i]);
                    i++;
                }
                else if (isOperators(Sourcecode[i]) == 1){//运算符
    
                    if (Sourcecode[i] == ':' || Sourcecode[i] == '>' || Sourcecode[i] == '<'&&Sourcecode[i + 1] == '='){
                        printf("(4,%c%c)\n", Sourcecode[i], Sourcecode[i + 1]);
                        i += 2;
                    }
                    else{
                        printf("(4,%c)\n", Sourcecode[i]);
                        i+= 1;
                    }
                }
                else{
                    if(Sourcecode[i]!='\0')
                        printf("(error,%c)\n",Sourcecode[i]);
                    if(Sourcecode[i+1]!='\0'){
                        
                        i+=1;}
                    else
                        i=100;
                }
            }
    
        
        }
    
        goto back;
    
    }
    

    编程感悟

    1.需要对是否为标识符、常数、保留字、运算符、界符进行判断,应用布尔类型完美的解决这个问题。

    2.++i与i++都是i=i+1的含义,但是++i表示执行前i=i+1,而i++表示执行后i=i+1。

    3.用一维数组来表示字符串,二维数组用来表示字符串的集合,并且用strcmp(string_1,string_2)来进行字符串内容的比较,相同返回0。

    4.对于相同的标识符来说,入口应该相同,所以在对这里进行处理的时候,声明一个二维数组用来存放各个标识符(字符或者字符串),根据二维数组中的行下标进行入口标记。

    5.好好学习一维数组、二维数组的应用场景以及应用原理。

    展开全文
  • C语言词法分析器的设计与实现

    千次阅读 2019-07-10 20:29:08
    程序设计语言与编译实验:C语言词法分析器的设计与实现 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流...

    程序设计语言与编译实验:C语言词法分析器的设计与实现
    一、实验目的及要求
    本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
    运行环境:
    硬件:windows 10
    软件:Code::Blocks 17.12

    二、实验步骤
    1.查询资料,了解词法分析器的工作过程与原理。
    2.分析题目,整理出基本设计思路。
    3.实践编码,将设计思想转换成C语言编码实现,编译运行。
    4.测试功能,自己选取C 语言的一个适当大小的子集,多次测试,查看运行结果,检测改分析器的分析结果是否正确。

    三、实验内容
    1.源代码

    #include<string.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<ctype.h>
    //定义关键字
    char *Key[10]={"main","void","int","char","printf","scanf","else","if","return"};
    char Word[20],ch;      //存储识别出的单词流
    int IsAlpha(char c)      //判断是否为字母
    {              
         if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A')))
             return 1;
        else 
            return 0;
    }
    
    int IsNum(char c)           //判断是否为数字
    {               
         if(c>='0'&&c<='9') 
             return 1;
        else 
             return 0;
     }
    
    int IsKey(char *Word)                 //识别关键字函数
    {         
         int m,i;
         for(i=0;i<9;i++)
         {
            if((m=strcmp(Word,Key[i]))==0)
          {
            if(i==0)
                return 2;
            else
                return 1;
           }
        }
         return 0;
    }
    
    void scanner(FILE *fp)     //扫描函数
    {        
    char Word[20]={'\0'};
    char ch;
    int i,c;
    ch=fgetc(fp);       //获取字符,指针fp并自动指向下一个字符
    if(IsAlpha(ch))            //判断该字符是否是字母{            
    Word[0]=ch;
    ch=fgetc(fp);
    i=1;
    while(IsNum(ch)||IsAlpha(ch))   //判断该字符是否是字母或数字{  
    Word[i]=ch;
    i++;
    ch=fgetc(fp);
    }
    Word[i]='\0';      //'\0' 代表字符结束(空格)
    fseek(fp,-1,1);                       
    c=IsKey(Word);     //判断是否是关键字                     
    if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字
    else if(c==2)     printf("%s\t$主函数\n\n",Word);
    else    printf("%s\t$关键字\n\n",Word);      //输出关键字
    }
    
    else              //开始判断的字符不是字母
    {
       if(IsNum(ch))                //判断是否是数字
       {                
            Word[0]=ch;
            ch=fgetc(fp);
            i=1;
            while(IsNum(ch))
            {
               Word[i]=ch;
                i++;
                ch=fgetc(fp);
            }
            Word[i]='\0';
            fseek(fp,-1,1);    //回退
            printf("%s\t$无符号实数\n\n",Word);}
    
            else        //开始判断的字符不是字母也不是数字
          {
             Word[0]=ch;
             switch(ch)
             {
               case'[':
    
              case']':
    
              case'(':
    
              case')':
    
              case'{':
    
              case'}':
    
              case',':
    
              case'"':
    
              case';':printf("%s\t$界符\n\n",Word); break;
    
             case'+':ch=fgetc(fp);
    
            Word[1]=ch;
    
             if(ch=='=')
             {
                 printf("%s\t$运算符\n\n",Word);//运算符“+=”
              }
    
             else if(ch=='+')
            {
                printf("%s\t$运算符\n\n",Word); //判断结果为“++”
            }
    
             else
            {
               fseek(fp,-1,1);
               printf(“%s\t$运算符\n\n”,Word); //判断结果为“+”
             }
             break;
    
             case'-':ch=fgetc(fp);
             Word[1]=ch;
             if(ch=='=')
             {
                 printf(“%s\t$运算\n\n”,Word);                     
             }
            else if(ch=='-')
            {
               printf("%s\t$运算符\n\n",Word); //判断结果为“--”
            }
           else
            {
               fseek(fp,-1,1);
               printf("%s\t$运算符\n\n",Word); //判断结果为“-”
            }
            break;
            case'*':
            case'/':
            case'!':
            case'=':ch=fgetc(fp);
            if(ch=='=')
            {
               printf("%s\t$运算符\n\n",Word);
            }
            else 
            {
                 fseek(fp,-1,1);
                 printf("%s\t$运算符\n\n",Word);
           }
           break;
    
          case'<':ch=fgetc(fp);
          Word[1]=ch;
          if(ch=='=')
          {
             printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”
          }
    
            else if(ch=='<')
            {
               printf("%s\t$运算符\n\n",Word); //判断结果为“<<”
            }
    
            else
             {
                fseek(fp,-1,1);
                printf("%s\t$运算符\n\n",Word); //判断结果为“<”
              }
             break;
    
           case'>':ch=fgetc(fp);
           Word[1]=ch;
           if(ch=='=') printf("%s\t$运算符\n\n",Word);
           else 
           {
              fseek(fp,-1,1);
              printf("%s\t$运算符\n\n",Word);
            }
            break;
    
           case'%':ch=fgetc(fp);
           Word[1]=ch;
           if(ch=='='){printf("%s\t$运算符\n\n",Word);}
           if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);
           else
          {
             fseek(fp,-1,1);
             printf("%s\t$取余运算符\n\n",Word);
           }
              break;
              default:printf("无法识别字符!\n\n"); break;}
        }
    }
    
    main()
    {
    char in_fn[30];  //文件路径              
    FILE *fp;
    printf("\n请输入源文件名(包括路径和后缀名):");
    while(1){
    gets(in_fn);
    scanf("%s",in_fn);
    if((fp=fopen(in_fn,"r"))!=NULL)  break;  //读取文件内容,并返回文件指针,该指针指向文件的第一个字符
    
    else printf("文件路径错误!请重新输入:");}
        printf("\n******************* 词法分析结果下 *******************\n");
    do{
    ch=fgetc(fp);
    if(ch=='#')  break;      //文件以#结尾,作为扫描结束条件
    
    else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行
    else{
    fseek(fp,-1,1);          //回退一个字节开始识别单词流
    scanner(fp);
    }}while(ch!='#');return0;} 
    

    四、实验结果
    1.解析源文件
    int main()
    {
    float b;
    float a=5;
    b=a++;
    printf("%c",b);
    return;
    }#

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

    展开全文
  • 词法分析器的设计与实现 二级 学院:信息科学与技术学院 专 业:计算机科学与技术 班 级: xxxx 姓 名: 梦阳辰 学 号: xx 指导 老师: xx 成 绩: 词法分析器的设计与实现 目 录 摘 要---------------------------...

    “生活充满了选择,而生活的态度就是一切。”

    词法分析器的设计与实现

    二级 学院:信息科学与技术学院
    专 业:计算机科学与技术
    班 级: xxxx
    姓 名: 梦阳辰
    学 号: xx
    指导 老师: xx
    成 绩:

    词法分析器的设计与实现

    目 录
    摘 要---------------------------------------------------3
    前 言---------------------------------------------------3
    1.总体设计----------------------------------------------5
    2.功能设计----------------------------------------------9
    2.1 单词的分类---------------------------------------9
    2.2 各类别字符的识别过程-----------------------------9
    3.各类别字符的识别过程的详细设计------------------------13
    4.运行与测试--------------------------------------------16
    5.总结与展望--------------------------------------------20
    参考文献------------------------------------------------21
    致谢----------------------------------------------------21

    词法分析器的设计与实现

    摘 要:词法分析器是编译器的第一个组成部分,是后续部分的基础,同时,词法分析也广泛应用在很多软件中,所以理解词法分析器的构造原理比较重要。设计并实现的模拟器能够以表格或图形的方式展示词法分析器的构造过程,并可以形象模拟词法分析器从源程序中识别单词的过程。

    关键字:词法分析 词法分析设计 词法分析器实现

    前 言

    编译原理是计算机专业的一项重要基础的课程,是研究软件是什么,为什么可以运行,以及怎么运行的学科,编译系统的改进将会直接对其上层的应用程序的执行效率,执行原理产生深刻的影响。编译原理的目的是将源语言翻译成目标语言。

    词法分析的任务是输入源程序,对构成源程序的字符串进行扫描和分解,识别出一个个单词符号。完成词法分析的程序简称为词法分析器。计算机高级语言的单词通常包括保留字、标识符、运算符、常量、界符。例如表达式i=5+3*j,经词法分析结果如下表:

    单词符号是源程序的基本组成成分,是人们理解和编写程序的基本要素。识别和理解这些要素无疑也是翻译基础。与把英语翻译成中文的情形一样,如果你对英语单词不理解,那就谈不上进行正确的翻译。在词法分析阶段的工作中所依循的是语言的词法规则。描述此法规则的有效工具是正规式和有限自动机。

    编译的目的就是将编译出来的语言用目标机的指令系统执行,一般而言是翻译到汇编语言的层次,但也有特例,比如JVM,Java虚拟机是将高级语言编译到中间语言环节,对于任何的高级语言,都翻译成相同的自己可以识别的中间语言,这样就可以在不同的机型上运行了,这种独特的创意造就了与平台无关的语言识别器——虚拟机的出现,从本质上来说也是用到了编译原理。

    通过这次词法分析器的分析与设计,你将进一步熟悉词法分析过程,加深对词法分析器的了解。实现一些重要的算法,或设计一个完整的编译程序模型,能够进一步加深理解和掌握所学知识,对提高自己的软件设计水平具有十分重要的意义。并且巩固了编译原理课程中学到的知识,学习程序设计语言编译程序的一般原理、基本设计方法、主要实现技术,加深对词法分析、语法分析的理解和认识,通过编程给出具体的实现,进而掌握词法分析和语法分析的基本思想。

    编译原理的内容非常丰富,技术非常成熟,有着几十年的研究历史。我一直相信这个时代最伟大的一种变革就是交流和共享,因为有沟通,有彼此的相互了解,相互学习才能打破人类历史几千年来的闭门造车、敝帚自珍,人人都献出一点有用的、精华的信息,随着时代的发展,几十年,上百年之后,文明将会变得更加的璀璨和瑰丽,这个世界将变得更加美好!

    1. 总体设计

    操作系统:window10

    编程语言:Java

    开发环境:eclipse 2020.03

    本次实现的是java词法分析器,能够识别:标识符,关键字,数字常量(包括整数,小数及如-1.3e-3格式的指数)、运算符(包括算数运算符、关系运算符、逻辑运算符、复合赋值运算符和位运算符)、赋值符号,界符以及其它的符号(如?:、,、.[]等)。

    注意为了便于观察,对于返回结果我直接采用中文输出单词类型,比如:
    对于不同的输入,它的输出不同,其输出表示为:

    标识符:<标识符,ID,标识符的属性值>

    关键字:<关键字,keyword,关键字属性值>

    数字常量:<数值,dight,常量的属性值>

    单目运算符:<单目运算符,单目运算符对应的编号,对应符号的属性值 >

    双目运算符:<双目运算符,双目运算符对应的编号,对应符号的属性值 >

    复合赋值运算符:<复合赋值运算符, 复合赋值运算符对应的编号,复合赋值运算符对应的属性值>

    赋值符号:<赋值符号,FZF ,赋值符的属性值>

    界符:<界符,界符对应的编号,界符对应的属性值>

    其它的符号:< 其它的符号, 其它的符号对应的编号,其它的符号对应的属性值>

    对于无法识别的其他字符会有错误提示输出:无法识别
    注意:对于不同的符号会有不同的符号编号加以区分。

    详情请看下面的图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.1单词的分类

    单词分为关键字,标识符,数字常量(包括整数,小数及如-1.3e-3格式的指数),运算符,分界符,赋值符和其它符号。

    2.2 各类别字符的识别过程

    如对于赋值符:我采取这种方式。(含逻辑运算符“==”)

    分界符:

    其它符号:

    关键字、标识符和运算符:

    本次实验采用了一个输入缓冲,一个输出缓冲。读入(readin)操作是从输入缓冲取出第一个字符放入输出缓冲的最后;读出(readout)操作是从输出缓冲取出最后一个字符放入输入缓冲的第一个位置。

    每次从输入缓冲读入一个字符,从state=0开始,判断下一个状态。对于每一个终态,就将输入缓冲区的字符读取出来,另外由于终态是处理工作,没有后继状态,不应该再读入,所以为了补偿在进入终态的又一次读入,在终态的前一状态,改变了state的值之后还要一次读出操作。对于有标记的终态,则是由于它需要通过多读的字符来判断是否是状态结束,例如:对于状态35,它要读入下一字符,判断是否是=,如果不是=,则要读出该字符,把它放回输入缓冲区。因此进入带状态,要先进行一次读出操作。

    3.各类别单词识别过程的详细设计
    步骤:

    1.从输入文件中读取一行串,将该串存入list1。

    2.从list1中取出第一个字符放到list2的最后,根据state的值进入相应的case。

    3.对于非终态的状态,根据DFA改变状态,如果它的下一个状态是终态,则它需要进行一次从list2取出最后一个字符放回list1的第一个位置。

    对于终态,它将构造token,并将相应的token写入输出文件中,清除list2里的所有字符,使state=0。如果这个终态是有*标记的终态,则它还需要在刚进入这个case时,要进行一次从list2取出最后一个字符放回list1的第一个位置的操作。

    如果判断是标识符或常量,要和已经在常量表或标识符表里的值比较。如果已经存在该标识符或常量,则不插入新的,从表中查找,返回对应的位置;否则,进行插入操作,在返回位置。
    4. 当list1里不为空时,重复2-3
    6. 当输入文件里还有没有读的行时,重复1-4
    如下图:

    对于输入和输出缓冲,采用的是LinkedList类来实现的。它们可以用poll和offer方法,在从输入缓冲(list1)读取字符到输出缓冲(list2)时,list1实现弹出第一个字符(pollFirst()),弹出最后一个字符(pollLast()),加入字符到第一个(offerFirst()),加入字符到最后一个(offerLast())。

    另外,我还新建了一个常量类(NumTye)和标识符(IDType)类,它们分别有一个Vector和num,用来记录当前的标识符或常量以及它们的个数。另外,在标识符类里面有一个关键字表,每次获取标识符之后就和关键字表比较,确定它到底是关键字还是标识符。

    实验中自定义了一个token类,它是有name,type和location三个属性的一个类。它一个toString方法,可以输出<name,type,location>格式的字符串。

    关键字和标识符:将Java的所有关键字存储在IDType类的静态数组keywords中。每次获取标识符之后就和关键字表比较,确定它到底是关键字还是标识符。Java关键字如下图:

    数字常量:判断取出的单词是否是数字类型:如果是数常量,并且之前已经插入了该数字则不插入新的,从表中查找,返回对应的位置,这里为了分辨字符结果,我输出的是字符的类型编号;否则,进行插入操作,在返回位置。如国没有插入该常量,则将该数字常量插入向量类Vector中。并且会将单词类型设置位dight类型。并将其输出到控制台和文件output.txt中。
    对于运算符,分界符,复值符和其它符号,我采取的是逐个击破的方法。将其解决。如下图所示(部分符号):

    4.运行与测试

    测试一:
    在input.txt中输入下列java语句

    结果一:
    Console的结果:

    Output.txt结果:

    可以看到两个地方都可以观察结果。
    测试二:

    测试结果二:

    测试三:

    测试结果三:

    5.总结与展望

    整个设计过程持续两个周的时间,包括前期的搜集资料,整理思路,到后面一个周的编写程序,调试代码,优化代码。这样的设计过程很是锻炼我的编程能力和对词法分析、语法分析的理解。让我熟悉了词法分析过程,加深了对词法分析器的理解。通过这次词法分析器的分析与设计,我进一步加深理解和掌握所学知识。并且巩固了编译原理课程中学到的知识,学习程序设计语言编译程序的一般原理、基本设计方法、主要实现技术,加深对词法分析、语法分析的理解和认识,通过编程给出具体的实现,进而掌握词法分析和语法分析的基本思想。

    对于此次词法分析器的分析与设计,由于时间短暂,对用户图形界面还不够友善,希望下次可以用Java中的两个图形类库AWT和SWing类库实现图形界面操作,这样用户就有更好的使用体验了。

    参考文献:
    《编译原理教程(第4版)》习题解析与上机指导。作 者 :胡元义主编。出版发行 : 西安:西安电子科技大学出版社 , 2017.02。

    《编译原理》作 者 :陈光建主编;贾金玲,黎远松,罗玉梅,万新副主编。出版发行 : 重庆:重庆大学出版社 , 2013.10

    《编译原理及编译程序构造 第2版》作者薛联凤,秦振松编著。出版社南京:东南大学出版社。

    《编译原理学习与实践指导》作者金登男主编。出版社上海:华东理工大学出版社。

    《编译原理》作 者 :鱼滨,侯红,龚晓庆编。出版发行 : 西安:西安交通大学出版社 , 2007.08。

    致谢:首先非常感谢指导老师xx对此次设计的要求指导,并且感谢平时上课的辛苦指导,同时也感谢在中国大学MOOC上课哈尔滨工业大学的陈鄞老师。感谢对此次设计有所帮助的所有人,谢谢!

    关注公众号【轻松玩编程】回复关键字“电子书”,“计算机资源”,“Java从入门到进阶”,”JavaScript教程“,“算法”,“Python学习资源”,“人工智能”等即可获取学习资源。

    能坚持别人不能坚持的,才能拥有别人不能拥有的。

    源码资源:https://download.csdn.net/download/jiahuan_/12610616

    在这里插入图片描述

    展开全文
  • 词法分析器的设计与实现 词法分析是编译过程的第一步,也是编译过程必不可少的步骤。编译过程中执行词法分析的程序称为词法分析器。构造词法分析器有两种方法:一种是用手工方式,即根据识别语言的...

    本节书摘来自华章计算机《编译与反编译技术实战》一书中的第3章,第3.1节,作者 刘晓楠 陶红伟 岳峰 戴超,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

    第3章

    词法分析器的设计与实现

    词法分析是编译过程的第一步,也是编译过程必不可少的步骤。编译过程中执行词法分析的程序称为词法分析器。构造词法分析器有两种方法:一种是用手工方式,即根据识别语言的状态转换图,使用某种高级语言直接编写词法分析器;另一种是利用自动生成工具(如LEX)自动生成词法分析器。本章分别介绍如何手动和自动构造词法分析器。

    3.1 词法分析器的设计

    本节首先介绍词法分析器的功能及其输出的单词符号的表示方式,然后介绍其输入和处理。

    3.1.1 词法分析器的功能

    词法分析器又叫作扫描器,其功能是从左往右逐个字符地对源程序进行扫描,然后按照源程序的构词规则识别出一个个单词符号,把作为字符串的源程序等价地转化成单词符号串的中间程序。单词符号是程序设计语言中基本的语法单元,通常分为5种:

    1)关键字(又称基本字或保留字):程序设计语言中定义的具有固定意义的英文单词,通常不能用作其他用途,比如C语言中的while、if、for等都是关键字。

    2)标识符:用来表示名字的字符串,如变量名、数组名、函数名等。

    3)常数:包括各种类型的常数,如整型常数386、实型常数0.618、布尔型常数TRUE等。

    4)运算符:又分为算术运算符,如+、-、*、/等;关系运算符,如=、>=、>等;逻辑运算符,如 or、not、and等。

    5)界符:如“,”“;”“(”“)”“:”等。

    在上面所给出的5种单词符号中,关键字、运算符和界符是程序设计语言提前定义好的,因此它们的数量是固定的,通常只有几十个或者上百个。而标识符和常数是程序设计人员根据编程需要按照程序设计语言的规定构造出来的,因此数量即便不是无穷,也是非常大的。

    词法分析器输出的单词符号通常用二元式(单词种别,单词符号的属性值)表示。其中:

    1)单词种别。单词种别表示单词种类,常用整数编码,这种整数编码又称为种别码。至于一种程序设计语言的单词如何分类、怎样编码,主要取决于技术上的方便。一般来说,基本字可“一字一种”,也可将其全体视为一种;运算符可“一符一种”,也可按运算符的共性分为几种;界符一般采用“一符一种”分法;标识符通常统归为一种;常数可统归为一种,也可按整型、实型、布尔型等分为几种。

    2)单词符号的属性值。单词符号的属性值是反映单词特征或者特性的值,是编译中其他阶段所需要的信息。如果一个种别只含有一个单词符号,那么其种别编码就完全代表了自身的值,因此相应的属性值就不需要再单独给出。如果一个种别含有多个单词符号,那么除了给出种别编码之外还应给出单词符号自身的属性值,以便把同一种类的单词区别开来。例如,对于标识符,可以用它在符号表的入口指针作为它自身的值;而常数也可用它在常数表的入口指针或者其二进制值作为它自身的值。

    3.1.2 输入及其处理

    词法分析器的结构如图3-1所示。词法分析器首先将源程序文本输入到一个缓冲区中,该缓冲区称为输入缓冲区,单词符号的识别可以直接在输入缓冲区中进行。但通常情况下为了识别单词的方便,需要对输入的源程序字符串进行预处理。对于许多程序语言来说,空格、制表符、换行符等编辑性字符只有出现在符号常量中时才有意义;注释几乎可以出现在程序中的任何地方。但编辑性字符和注释的存在一般只是为了改善程序的易读性和易理解性,不影响程序本身的语法结构和实际意义,通常在词法分析阶段可以通过预处理将它们删除。因此可以设计一个预处理子程序来完成上述工作,每当词法分析器调用预处理子程序时,其便处理一串固定长度的源程序字符串,并将处理结果放在词法分析器指定的缓冲区中,称为扫描缓冲区。接下来单词符号的识别就可以直接在该扫描缓冲区中进行,而不必考虑其他杂务。


    image

    扫描器对扫描缓冲区进行扫描时通常使用两个指针,即开始指针和搜索指针,其中,开始指针指向当前正在识别的单词的起始位置,搜索指针用于向前搜索以寻找该单词的终点位置,两个指针之间的符号串就是当前已经识别出来的那部分单词。刚开始时,两个指针都指向下一个要识别的单词符号的开始位置,然后,搜索指针向前扫描,直到发现一个单词符号为止,一旦发现一个单词,搜索指针指向该单词的右部,在处理完这个单词以后,两个指针同时指向下一个要识别的单词符号的起始位置。

    为了解决程序设计语言中某些单词符号可能存在公共前缀的问题,在进行词法分析时需采用所谓超前搜索技术,也即词法分析器在读取单词时,为了判断是否已读入整个单词的全部字符,常采取向前多读取字符并通过读取的字符来判别的方式。

    展开全文
  • 内含代码无法运行。原理包括词法分析例图、标识符表结构构造例图、类型位向量构造说明。此报告不够严谨、细节不明确,但做上交报告应付足矣。
  • 本节书摘来自华章社区《编译与反编译技术实战》一书中的第3章词法分析器的设计与实现,作者刘晓楠 陶红伟 岳峰 戴超,更多章节内容可以访问云栖社区“华章社区”公众号查看 第3章词法分析器的设计与实现词法分析...
  • 实验一 简易C语言词法分析器的设计与实现 2.实验目的 (1)掌握C语言单词符号的类别、正规式,会构造识别单词符号的状态转换图; (2)能利用状态转化图构造C语言词法分析器; (3)掌握词法分析程序的作用。 3.实验...
  • C语言词法分析器的设计与实现       姓名 LFY 学号 2016   专业   班级 ...
  • 本节书摘来自华章出版社《编译与反...词法分析器的设计与实现 词法分析是编译过程的第一步,也是编译过程必不可少的步骤。编译过程中执行词法分析的程序称为词法分析器。构造词法分析器有两种方法:一种是用手工方...
  • 2 功能需求配置文件配置用于发送邮箱信息邮件发送功能日志窗口输出显示3 界面接口邮件列表框标题内容输入框发送按钮日志输出框4 技术选型.Net 4.0 C# Winform5 实现5.1 新建项目项目命名为 SimpleEmailSenderimage...
  • 特性简介:支持整数四则运算支持小括弧提升优先级支持临时变量保存结果安装和使用(需要有GCC环境):$gogetgithub.com/chai2010/calculator$calculator1+2*3=7x=3-(2-1)=2x*2=4词法符号先创建tok.h文件,包含词法符号...
  • 2.设计思想: 基于java语言hashmap结构: 3.Java hashmap特点: 存储时:他们会找到相同bucket位置,发生碰撞,因为HashMap使用链表存储对象(每个Map.Entry都有一个next指针),这个Entry会存储在链表中。 ...
  • > C 语言词法分析器设计与实现 C 语言词法分析器的设计与实现 一实验目的 强化对系统软件综合工程实现能力规划能力的训练 加强对词法分析原理方法和基本实现技术的理解 二实验内容 用 C 语言(或 C++ )作为宿主语言...
  • package BYYL; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class CFFX { public int ch; public int code;...
  • TTCN3词法分析器与语法分析器的设计与实现,刘超,黄小红,研究了TTCN-3编译系统的词法和语法分析器的实现,对TTCN3中的终结符号的处理、语法树节点的设计和语法树打印子程序等关键技术作了介�
  • 词法分析器的实现方法手工编码实现法相对复杂,且容易出错当能够对各个部分进行相当好的控制,效率高是目前非常流行的实现方法GCC, LLVM,...词法分析器的生成器可快速原型、代码量少但较难控制细节如下是手工编码...
  • 输入source.tny文件,输出:token[40]、tokenstring[40][30]。具体包括: ①已经能够识别样例程序:变量、数、赋值号、分号。 ②修改代码使其能够识别:...③通过使用TINY语言实现词法分析中运算符号(+-*/)识别。
  • 过了个五一小假期,调整了一下心情做完了前久积攒的作业,感觉甚是轻松。前久困扰我的事情已经尘埃落定了,也有了新的发展目标。开这个专栏本意就是把本科期间...MFC程序的设计需要遵循面向对象的原则,简单来说就是...
  • 编译原理的词法分析器设计与实现

    千次阅读 2018-04-24 11:27:13
    int wordanalysis()//词法分析,分为3部分,完整项目在下面 { if ((a[i] &amp;gt;= 'A'&amp;amp;&amp;amp;a[i] &amp;lt;= 'Z')||(a[i]&amp;gt;='a'&amp;amp;&amp;amp;a[i]&amp;lt;...
  • 以下内容转载自...通过那一篇,我们知道了编译器至少要包括词法分析其和语法分析器,而本篇,我将集中时间和精力,用来介绍和讲解Lua词法分析器的设计与.
  • 词法分析器设计与实现 待分析简单词法 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是...
  • 【编译原理】实验一 词法分析器设计与实现

    万次阅读 多人点赞 2019-04-14 21:44:05
    设计、编制并调试一个词法分析程序,加深对词法分析原理理解。 二、实验内容 2.1 待分析简单词法 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符 : = + - * / ...
  • 中文脚本编译器的设计与实现(一)词法分析器
  • 编译原理课程设计报告 课题名称 编译原理课程设计 C-语言词法语法分析器的实现 C-词法语法分析器的实现 1.课程设计目标 1题目实用性 C-语言拥有一个完整语言的基本属性通过编写C-语言的词法分析和语法分析对于...
  • c#词法分析器

    2013-12-25 15:30:24
    C#词法分析器的设计与实现,简单易用的代码。
  • 本节书摘来自华章出版社《编译反编译技术》一书中的第2章,第2.2节词法分析器的设计,作者庞建民,陶红伟,刘晓楠,岳峰,更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.2 词法分析器的设计 下面...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 160
精华内容 64
关键字:

词法分析器的设计与实现