实验一 词法分析器+编译原理

Posted 日星月云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实验一 词法分析器+编译原理相关的知识,希望对你有一定的参考价值。

实验一 词法分析器+【编译原理】

前言

2023-4-2 20:04:46

以下内容源自《【编译原理】》
仅供学习交流使用

推荐

实验一 词法分析器【编译原理】

实验一 词法分析器+

书接上文

要求:代码的高级功能

更多的关键字(运算符)
需要编写keywords.txt

更多的常数(科学计数法 浮点数 字符串常量)
需要重写analyzer

更多的功能(过滤无效字符、数值转换、宏展开、预包含处理)
需要重写analyzer

还有
出错位置没有行数
需要修改loadInput()逻辑
使其每读入一行,就进行语法分析处理
并且需要row行数属性来配合

下面实现C语言的词法分析

keywords.txt

除了32个关键字,还有用户预编译单词
并把34种运算符拆开为符号
有可能仍有遗漏

1      include
2      define
3      ifdef
4      ifndef
5      auto
6      break
7      case
8      char
9      const
10     continue
11     default
12     do
13     double
14     else
15     enum
16     extern
17     float
18     for
19     goto
20     if
21     int
22     long
23     register
24     return
25     short
26     signed
27     sizeof
28     static
29     struct
30     switch
31     typedef
32     union
33     unsigned
34     void
35     volatile
36     while

此处没有了

identifierList
constantList

operators.txt

新建一个运算符表

注意:
虽然有重复的但是他们的功能不一样
需要根据上下文环境确定具体功能

1         #
2         $
345         \\
6         
7         
8         ;
9         (
10        )
11        [
12        ]
13        ->
14        .
15        !
16        ~
17        ++
18        --
19        +
20        -
21        *
22        &
23        *
24        /
25        %
26        +
27        -
28        <<
29        >>
30        <
31        <=
32        >
33        >=
34        ==
35        !=
36        &
37        ^
38        |
39        &&
40        ||
41        ?
42        :
43        =
44        +=
45        -=
46        *=
47        /=
48        %=
49        <<=
50        >>=
51        &=
52        ^=
53        |=
54        ,

测试

package s1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SeniorLexicalAnalyzer extends AbstractLexicalAnalyzer

    public List<Symbol> operatorList=new ArrayList<>();//运算符表

    //创建关键字表 根据表3.1实现
    
        File file = new File("operators.txt");
        if (file.exists()) 
            System.out.println("operators.txt文件存在");
            System.out.println("读取文件,加载运算符表");
            loadOperatorList();
         else 
            System.out.println("operators.txt文件不存在");
            System.out.println("采用默认的运算符表");
            initOperatorList();
        
    

    //读取operators.txt文件的内容加载到operatorList中
    public void loadOperatorList() 
        try 
            BufferedReader reader = new BufferedReader(new FileReader("operators.txt"));
            String line;
            while ((line = reader.readLine()) != null) 
                String[] arr = line.split("\\\\s+");
                operatorList.add(new Symbol(Integer.parseInt(arr[0]), arr[1]));
            
            reader.close();
         catch (IOException e) 
            e.printStackTrace();
        

    

    //默认的运算符表
    public void initOperatorList()
        keywordList.add(new Symbol(1,"="));
        keywordList.add(new Symbol(2,"+"));
        keywordList.add(new Symbol(3,"*"));
        keywordList.add(new Symbol(4,"**"));
        keywordList.add(new Symbol(5,","));
        keywordList.add(new Symbol(6,"("));
        keywordList.add(new Symbol(7,")"));
    

    //重写 状态转移图实现
    @Override
    public void analyzer() 

    

    //测试词法分析器
    private void testAnalyzers()

    

    //重写出错处理,跳过1下,继续分析
    @Override
    public void procError()
        System.out.println("词法分析出错"+"\\n"+"出错位置为"+position);
        System.out.println("跳过错误,继续分析");
        position++;
        if(ch!=EOF)
            ch=' ';
        
    
    //测试关键词表的赋值
    private void testKeywordList()

        for (Symbol s:keywordList) 
            System.out.println(s);
        
    
    
    //测试运算符表的赋值
    private void testOperatorList()
        for (Symbol s:operatorList) 
            System.out.println(s);
        
    


    public static void main(String[] args) 
        SeniorLexicalAnalyzer lex = new SeniorLexicalAnalyzer();
        //测试
        lex.testKeywordList();
        lex.testOperatorList();

        //测试
//        new SeniorLexicalAnalyzer().testAnalyzers();
    


重申:
关键词表中的code没有什么意义
只有单词表中的code有意义
所以运算符表中就没有设置code

测试结果

keywords.txt文件存在
读取文件,加载关键词表
operators.txt文件存在
读取文件,加载运算符表
Symbolid=1, value='include', code=0
Symbolid=2, value='define', code=1
Symbolid=3, value='ifdef', code=2
Symbolid=4, value='ifndef', code=3
Symbolid=5, value='auto', code=4
Symbolid=6, value='break', code=5
Symbolid=7, value='case', code=6
Symbolid=8, value='char', code=7
Symbolid=9, value='const', code=8
Symbolid=10, value='continue', code=9
Symbolid=11, value='default', code=10
Symbolid=12, value='do', code=11
Symbolid=13, value='double', code=12
Symbolid=14, value='else', code=13
Symbolid=15, value='enum', code=14
Symbolid=16, value='extern', code=15
Symbolid=17, value='float', code=16
Symbolid=18, value='for', code=17
Symbolid=19, value='goto', code=18
Symbolid=20, value='if', code=19
Symbolid=21, value='int', code=20
Symbolid=22, value='long', code=21
Symbolid=23, value='register', code=22
Symbolid=24, value='return', code=23
Symbolid=25, value='short', code=24
Symbolid=26, value='signed', code=25
Symbolid=27, value='sizeof', code=26
Symbolid=28, value='static', code=27
Symbolid=29, value='struct', code=28
Symbolid=30, value='switch', code=29
Symbolid=31, value='typedef', code=30
Symbolid=32, value='union', code=31
Symbolid=33, value='unsigned', code=32
Symbolid=34, value='void', code=33
Symbolid=35, value='volatile', code=34
Symbolid=36, value='while', code=35
Symbolid=1, value='#', code=0
Symbolid=2, value='$', code=0
Symbolid=3, value='‘', code=0
Symbolid=4, value='“', code=0
Symbolid=5, value='\\', code=0
Symbolid=6, value='', code=0
Symbolid=7, value='', code=0
Symbolid=8, value=';', code=0
Symbolid=9, value='(', code=0
Symbolid=10, value=')', code=0
Symbolid=11, value='[', code=0
Symbolid=12, value=']', code=0
Symbolid=13, value='->', code=0
Symbolid=14, value='.', code=0
Symbolid=15, value='!', code=0
Symbolid=16, value='~', code=0
Symbolid=17, value='++', code=0
Symbolid=18, value='--', code=0
Symbolid=19, value='+', code=0
Symbolid=20, value='-', code=0
Symbolid=21, value='*', code=0
Symbolid=22, value='&', code=0
Symbolid=23, value='*', code=0
Symbolid=24, value='/', code=0
Symbolid=25, value='%', code=0
Symbolid=26, value='+', code=0
Symbolid=27, value='-', code=0
Symbolid=28, value='<<', code=0
Symbolid=29, value='>>', code=0
Symbolid=30, value='<', code=0
Symbolid=31, value='<=', code=0
Symbolid=32, value='>', code=0
Symbolid=33, value='>=', code=0
Symbolid=34, value='==', code=0
Symbolid=35, value='!=', code=0
Symbolid=36, value='&', code=0
Symbolid=37, value='^', code=0
Symbolid=38, value='|', code=0
Symbolid=39, value='&&', code=0
Symbolid=40, value='||', code=0
Symbolid=41, value='?', code=0
Symbolid=

编译原理实验题

实验一 小型词法分析器的设计

一、实验原理
1、词法分析器
词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。词法分析是编译过程中的一个阶段,在语法分析前进行。词法分析作为一遍,可以简化设计,改进编译效率,增加编译系统的可移植性。也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
2、词法分析器的设计目标
(1)正确性;
(2)可读性;
(3)健壮性;
(4)高时间效率;
(5)高空间效率;

二、实验要求和目的
1、理解符号串的基本特点;
2、理解符号串切割的特点;
3、理解单词符号的特点与基本特点。

三、实验环境
环境不限。

四、作业要求
编写一个程序,对于输入的一段英语文本,可以统计:
(1)该文本中有多少英语单词,并把每个单词都列出来;
(2)该文本中有多少不同的英语单词,并把不同的单词都列出来。
如,输入 I am a good student. I am in Zhengzhou.
则可以统计出有9个英语单词、7个不同的英语单词。
实验二 小型词法分析器的设计

一、实验原理
1、词法分析器
词法分析器的功能输入源程序,按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包括关键字、标识符、运算符、界符和常量等。
(1) 关键字 是由程序语言定义的具有固定意义的标识符。例如,Pascal 中的begin,end,if,while都是保留字。这些字通常不用作一般标识符。
(2) 标识符 用来表示各种名字,如变量名,数组名,过程名等等。
(3) 常数? 常数的类型一般有整型、实型、布尔型、文字型等。
(4) 运算符 如+、-、*、/等等。
(5) 界符? 如逗号、分号、括号、等等。
2、词法分析器设计目标
(1) 正确性
(2) 可读性
(3) 健壮性
(4) 高时间效率
(5) 高空间效率

二、实验要求和目的
1、理解词法分析器的基本原理;
2、能够根据词法分析器的原理设计小型词法分析器,该词法分析器可以获取单词符号并判断符号的类别。

三、实验环境
环境不限。

四、作业要求
1、编写一个词法分析器,对于输入的算术表达式,可以获取该字符串中的所有运算数和运算符。
如,输入25.6 + 1752.9e10 -62^ 3
则要求得到输出如下,
25.6
+
17
*
52.9e10

6
*
2
^
3

2、编写一个词法分析器,对于输入的一段程序,可以获取该程序的单词符号。单词符号的类别有基本字、标识符、常数、算符和界符。关键字为基本字,由字母组成,如int、for和while;变量名和函数名为标识符,由字母和数字构成,如fun1和age;固定不变的数值为常数,如12、13.86和25e8(科学计数法);算符如+、-、、/ 、%、&&;界符如 {、[、(、 ;和:等。
如,若输出源程序如下,
public?static?void?main (String []?args)?{
???double sum5 = 0.0;
for ( int?i=1;i<=5;i++)?{
sum5=sum5+(i+10);
sum5=sum5+(i
2);
???}
}

则要求得到输出如下,
public 基本字
static?基本字
void?基本字
main 标识符
( 界符
String基本字
[ 界符
] 界符
args标识符
)? 界符
{ 界符
double基本字
sum5标识符
= 算符
0.0 常数
; 界符
for基本字
( 界符
int?基本字
i标识符
=算符
1常数
; 界符
i标识符
<=算符
5常数
; 界符
i标识符
++算符
)? 界符
{ 界符
sum5 标识符
= 算符
sum5 标识符

  • 算符
    (界符
    i标识符
  • 算符
    10常数
    ) 界符
    ; 界符
    sum5 标识符
    = 算符
    sum5 标识符
  • 算符
    (界符
    i 标识符
  • 算符
    2常数
    ) 界符
    ;? 界符
    }界符
    }界符

作业步骤:
(1) 了解该语言的单词符号
(2) 为单词符号构造对应的状态转换图。状态转换图的构造可以参考课本P41(图3.2)和P43(图3.3)
(3) 根据状态转图的结构进行计算机实现。

注:
数字52.9e10为一个数据,切记不可将其分开为52.9和10; <=为一个操作符,切记不可将其分开为< 和 =

作业二 (选做)
flex 是- fast lexical analyzer generator 的简称,即快速词法分析器。
给出的“lex_实验”是一个通过flex得到的词法分析器及相关文件,该词法分析器可以统计源程序的行数及字符数。
(一) 目录介绍
参考 “lex_实验”,在完成实验后,实验目录中包括两个子目录。
1、子目录 flex
它包含了 flex.exe, flex.hlp, libfl.lib 三个文件,另外还有一个例子文件 example.l 及该例子生成的 lex.yy.c。
2、子目录 lex_yy
这个目录是为 lex.yy.c 建立的一个项目(如,使用 VC6)。它包含有 lex.yy.c, libfl.lib (拷贝自目录 flex),以及相关的项目文件。在debug 子目录中是已经生成的 词法分析器 lex.yy.exe, 利用它可以进行词法分析。

(二)实验示范
生成“lex_实验”的各文件的步骤如下:
1、编写 lex 程序,如 example.l 文件所示
2、调用 flex 以生成 lex.yy.c, DOS命令格式: flex < example.l
3、新建一个目录(如 lex_yy), 把lex.yy.c 及 libfl.lib 拷贝到该目录下。
4、用VC6或其它的C语言集成开发环境,打开lex.yy.c,并生成一个新项目。
5、编译并链接libfl.lib, 得到词法分析器 debug/ley.yy.exe。
6、验证词法分析器的功能:
1)编写一输入文件(如lex_yy/debug/12.txt)
2) 调用 lex.yy.exe(DOS 命令格式 lex.yy.exe < 12.txt )
3) 观察输出结果是否与预想的相符(实际是有点不相符的)。
注意:flex.exe, flex.hlp, libfl.lib 三个文件是flex工具,自带的。
实验三 小型语法分析器的设计

一、实验原理
语法分析器通常是作为编译器或解释器的组件出现的,它的作用是进行语法检查、并构建由输入的单词组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。
语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“单词”,并将单词流作为其输入。实际开发中,语法分析器可以手工编写,也可以使用工具(半)自动生成

二、实验要求和目的
1、加深对语法分析器工作过程的理解;
2、加强对递归下降法实现语法分析程序的掌握;
3、能够采用一种编程语言实现简单的语法分析程序;
4、能够使用自己编写的分析程序对简单的程序段进行语法翻译。

三、实验环境
环境不限。

四、作业要求
在实验2的基础上,用递归下降分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程工具。
编写的分析程序能够进行正确的语法分析;对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;

给定文法
E E + T | E – T | T
T T * F | T / F | F
F (E) | i
取消左递归后,改为:
E TE’
E’ +TE’ | -TE’ |ε
T FT’
T’ *FT’ | /FT’|ε
F (E) | i
该文法为LL(1)方法。

请根据第4.4节的递归下降分析程序构造方法,为该文法构造程序,对于给定的输入,程序按照先后顺序将使用的产生式输出。
如,输入25.6 * 14.5 + 2, 首先经过词法分析器,得到五个单词符号 i * i + i
经过语法分析,则输出
E TE’
T FT’
F i
T’*FT’
F i
T’ε
E’+TE’
T FT’
F i
T’ε
E’ε

提示:
(1) 该程序应该为每个非终结符( E、E’、T、T’、F)分别写一个函数,写函数时,需要考虑first集和follow集。
(2) 在验证程序正确性时,要考虑语法正确的串和语法不正确的串。
如: 正确的串有 25.6 * 14.5 + 2 ( i * i + i), 2 / 5.2 + 78 - 6 ( i / i + i - i)
错误的串有 2 / 5.2 + 78 – ( i / i + i - ) +56 * 7 ( + i * i)
对于给定的输入,大家可以通过手写推导过程,然后再核对计算机输出的产生式顺序的方法,检验程序写的对错。
实验四 小型语法分析器的设计

一、实验原理
1、语法分析器
语法分析器通常是作为编译器或解释器的组件出现的,它的作用是进行语法检查、并构建由输入的单词组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。
语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“单词”,并将单词流作为其输入。实际开发中,语法分析器可以手工编写,也可以使用工具(半)自动生成
2、算符优先分析
对于一个算符优先文法,只要能构造出它的算符优先表,就可以利用算符优先分析方法,分析一个句子是否符合这个文法的定义。在算符优先文法中,仅存在终结符号之间的优先关系,完全不考虑非终结符号。我们根据算符优先关系,给句型寻找一个被归约的最左素短语。一旦发现最左素短语,即可规约。

二、实验要求和目的
1、加深对语法分析器工作过程的理解;
2、加强对终结符之间的优先关系的掌握;
3、能够采用一种编程语言实现简单的算符优先分析过程。

三、实验环境
环境不限。

四、作业要求
1、在实验2的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程工具。
编写的分析程序能够进行正确的语法分析;对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程。
给定文法及其优先关系表,如下:

(1)输入正确的表达式,则给出详细的操作步骤。如,给出表达式T+T*F+i,则输出
符号栈 优先关系 剩余输入串 动作

T+T*F+i# 移进

#T < +TF+i# 移进
#T+ T
F+i# 移进
#T+T > F+i# 移进
#T+T
F+i# 移进
#T+TF > +i# 归约TF
#T+N > +i# 归约T+N
#N < +i# 移进
#N+ < i# 移进
#N+i > # 归约i
#N+N > # 归约N+N
#N = # 接受

(2)输入错误的表达式,如 i+i *, 则报错。

2、选做
请设计一个小型公式编辑器的上下文无关文法,并进行自上而下分析的实现。
实验五 小型编译程序的设计

一、实验原理
(1) 词法分析
(2) 语法分析
(3) 语义分析

二、实验要求和目的
1、加深对词法分析器的理解;
2、加深对语法分析器的理解;
3、加深对属性文法的理解;

三、实验环境
环境不限。

四、作业要求
1、请大家在实验2和实验3的基础之上,利用翻译模式制作可编程计算器,如图1所示。要求:在这里插入图片描述

图1 可编程计算器界面
(1)点击 25.6 * 14.5 + 2 这11个符号,按‘=’,可输出结果373.2
(2)点击2 / (5.2 + 78) – 6这12个符号, 按‘=’,可输出结果 -5.97596
(3)若输入语法错误的串,如2 / 5.2 + 78 –, 则需报错。
(4)考虑整型和浮点型问题。对于浮点型,还需考虑精度问题。
(5)考虑除0问题。
(6)考虑键盘操作问题。

本题翻译模式的提示如下,请补充以下三个空之后,参考图2所示的代码,写出计算器。

E TE’{E.val = T.val + E’.val}
E’ +TE’ {E’.val = T.val + E’.val}
E’ -TE’ {}
E’ ε {E’.val = 0}
T FT’{T.val = F.val * T’.val}
T’ *FT’ {T’.val = F.val * T’.val}
T’ /FT’ {
}
T’ ε {_________________}
F (E) {F.val = E.val}
F i {F.val = i.lexval}

E TE’{E.val = T.val + E’.val}, 其代码经过更改如下:

图2 翻译模式代码
在这里插入图片描述

2、选做
请将语义分析纳入到小型公式编辑器中,并将小型公式编辑器实现出来。

以上是关于实验一 词法分析器+编译原理的主要内容,如果未能解决你的问题,请参考以下文章

编译原理实验题

编译原理实验题

编译原理 实验一 java语言实现对C语言词法分析

编译原理 实验一 java语言实现对C语言词法分析

编译原理课程设计词法分析程序设计

编译原理--词法分析--实验报告(此文章在管理-发表文章 里也有)