栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

编译原理:flex与bison--从0到1完成一个编译器(sample语言)①

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

编译原理:flex与bison--从0到1完成一个编译器(sample语言)①

编译原理:flex与bison–从0到1完成一个编译器(sample语言)

文章目录
  • 前言
  • 一、Sample语言简介
  • 二、项目内容
  • 三、原理与实现过程
    • 1.词法分析
    • 2.步骤
  • 四、项目演示
  • 总结
  • 源代码


前言 本系列文章共三部分,记述了我完成编译器的过程,供后来的学弟学妹参考借鉴。
本项目是我的编译原理作业,文章是由实验报告整理而来的,重在阐述,如果没有编译原理的相关知识,还要结合一些教程来看。
本项目实现的编译器包括词法分析,语法分析,语义分析与中间代码生成,目标代码生成共四个阶段,能将sample语言翻译成可执行的汇编语言。使用flex与bison工具辅助,通过C语言实现。本人能力有限,项目有许多不足和值得改进的地方,也请读者多多指正。

本文为本系列的第一部分,介绍sample语言的词法分析。

一、Sample语言简介

Sample语言是PASCAL语言的简化版本。具有一般高级语言的共同特征:它的字符集包括所有的大小写字母、数字和一些界符;有多种数据类型:整型、实型、字符型等;有变量说明和常量说明;包括顺序、条件和循环三种语句结构。
Sample语言的词法、语法定义见这里
需要注明的是,本项目中,八进制和十六进制数字并没有写在词法中,需要自己定义。

二、项目内容

本项目编写了一个对于Sample语言源代码的词法分析,并打印分析结果。使用词法分析工具Flex,并结合C语言完成。根据Sample语言文档写出了所有单词的正则表达式,利用Flex工具和C语言进行判断和分析,输出单词的行号、种别码,并能够给出错误信息。

  1. 单词识别
    扫描源程序,根据词法规则,识别单词,填写相应的 token 表。

  2. 错误处理
    如果产生词法错误,则输出出错的位置(源程序行号)以及相关的说明文字。本程序能够查出源代码中可能包含的词法错误,即出现 Sample 词法中未定义的字符以及任何不符合 Sample 词法单元定义的字符。

  3. 常量和注释识别要求
    a. 识别八进制数和十六进制数。若输入文件中包含符合词法定义的八进制数(如 0123)和十六进制数(如 0x3F),本程序能够得出相应的词法单元;若输入文件中包含不符合 词法定义的八进制数(如 09)和十六进制数(如 0x1G),本程序需要给出输入文件有词法错误的提示信息。
    b.识别指数形式的浮点数。若输入文件中包含符合词法定义的指数形式的浮点数 (如 1.05e-4),本程序需要得出相应的词法单元;若输入文件中包含不符合词法定义的指数形式的浮点数(如 1.05e),本程序需要给出输入文件有词法错误的提示信息。
    c.识别“//”和“//”形式的注释。若输入文件中包含符合定义的“//” 和“//”形式的注释,本程序能够滤除这样的注释;若输入文件中包含不符合定义的注释 (如“//”注释中缺少“"记录注释的行数注释“//”.*/特殊判断[0-9]+[a-zA-Z]+[a-zA-Z0-9]*报错

    部分常数的正则表达式如下。

    数字类别正则表达式
    八进制数0[0-7]+
    十六进制数0x[0-9A-F]*
    指数形式的浮点数{DIGIT}+"."{DIGIT}+“e”(""|"-"){DIGIT}+

    对于要求三,本程序写出了八进制数、十六进制数、指数形式浮点数的正则表达式。对于注释“//”,本程序匹配以“//”开头、以’n’结尾的所有字符串并只输出“//”。对于注释“/……/”,本程序匹配以“/”开头以“/”结尾的所有字符串。值得提出的是,当此类注释只有“/”或只有“/”时,程序会识别成运算符“/”和“”。解决方案为对“/”和“*/”进行单独匹配,若能够单独匹配到这两个单词,说明该注释缺失符号。
    关于本程序的出错处理,本程序将无法识别的单词和它的行号记录下来,词法分析完成后一起输出。

    四、项目演示

    下面是对几个Sample语言片段的词法分析输出
    片段1

    program example;
    var
    a:integer;
    begin
    x:=3+3.5+3.5e4;
    end
    


    片段2(对于单词α,由于激活了中文显示,α不能正常输出)

    program example;
    var
    3a:real;
    3a=0x1G;
    α:integer;
    

    片段3(注释缺失)

    /*balabala
    //asdfo
    

    总结

    本实验中完成了一个对于Sample语言源代码的词法分析,并打印分析结果。使用词法分析工具Flex,并结合C语言完成。根据Sample语言文档写出了所有单词的正则表达式,利用Flex工具和C语言进行判断和分析,输出单词的行号、种别码,并能够给出错误信息。
    当时完成这样一个词法分析程序还是蛮有成就感的,第一次使用flex工具进行编程,我也感受到了编译原理这门课程的魅力。当时我就想一定要完成自己的编译器。

    源代码
    %{
    #include 
    #include 
    #include 
    #include
    int row=1;
    char faults[100][100];
    int cnt_fault=0;
    %}
    HDIGIT  [1-9]
    DIGIT   [0-9]
    ID      [a-zA-Z][a-zA-Z0-9]*
    EIGIT   [0-7]
    SDIGIT  [0-9A-F]
    BAOLIUZI    and|begin|bool|char|const|do|else|end|for|if|input|integer|not|or|output|program|read|real|repeat|then|to|until|var|while|write
    DANJIEFU    [+|-|*|/|=|<|>|||:|,|_|.]
    SHUANGJIEFU ""|"<="|">="|"<>"|":="
    BOOL    true|false
    FENHAO  ;
    %%
    n {row++;}
    ""  {            
    
        int len=strlen(yytext);
        int num=0;
        for(int i=0;i"         { printf("%4dt35t运算符: %sn",row,yytext); }
    "<="        { printf("%4dt36t运算符: %sn",row,yytext); }
    ">="        { printf("%4dt37t运算符: %sn",row,yytext); }
    "="         { printf("%4dt38t运算符: %sn",row,yytext); }
    ":="        { printf("%4dt39t运算符: %sn",row,yytext); }
    "<>"        { printf("%4dt40t运算符: %sn",row,yytext); }
    ":"         { printf("%4dt41t运算符: %sn",row,yytext); }
    ","         { printf("%4dt42t运算符: %sn",row,yytext); }
    
    "//".*      { printf("%4dt44t注释: //n",row); }
    
    
    ";"         { printf("%4dt47t分号:%sn",row, yytext); }
    
    "("         { printf("%4dt48t界符:%sn",row, yytext); }
    ")"         { printf("%4dt49t界符:%sn",row, yytext); }
    "."         { printf("%4dt50t界符:%sn",row, yytext); }
    "{"         { printf("%4dt51t界符:%sn",row, yytext); }
    "}"         { printf("%4dt52t界符:%sn",row, yytext); }
    "["         { printf("%4dt53t界符:%sn",row, yytext); }
    "]"         { printf("%4dt54t界符:%sn",row, yytext); }
    
    {ID}        { printf("%4dt58t标识符:%sn", row,yytext); } 
    [0-9]+[a-zA-Z]+[a-zA-Z0-9]*  { sprintf(faults[cnt_fault++],"%4dt不能识别的字符:%sn", row,yytext); } 
    [tx20]+          
    .           { sprintf(faults[cnt_fault++],"%4dt不能识别的字符:%sn", row,yytext); } 
    %%
    
    int main(int argc, char *argv[])
    {
        system("chcp 65001");
        ++argv; --argc;
        if (argc>0) yyin = fopen(argv[0],"r");
        //else yyin = stdin;
        else
        {
            char file[100];
            printf("输入你的文件:n");
            scanf("%s",file);
            yyin=fopen(file,"r");
        }
        yylex();
        if(cnt_fault>0)
        {
            printf("错误n");
            for(int i=0;i
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/330145.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号