Pre-Course Survey
![image-20220114183629932](https://img-blog.csdnimg.cn/img_convert/69c925812b32281b729a41ca6cd4464e.png)
一个小调查,无伤大雅
实验所需虚拟机
链接: https://pan.baidu.com/s/16KXICHhpBb22v4CyNQugMg 提取码: n44a
Navigation Your Course
课程导览
属性bar用的
![image-20220114183851092](https://img-blog.csdnimg.cn/img_convert/28bb8f1fd7b309b3141734ac7effe23b.png)
介绍了 课程模块,大纲模块,讨论模块,测评模块,测评模块会打分
![image-20220114184149658](https://img-blog.csdnimg.cn/img_convert/f344502c23125d69f2754ddaa6a7a854.png)
讨论模块要遵守规则,不发一些不必要的内容,淫秽色情,垃圾邮件,抄袭的内容
01-01: Introduction (8m20s)
![image-20220114184612313](https://img-blog.csdnimg.cn/img_convert/670753137087e902c835bb8a5ea5a44d.png)
编程语言又两种实现,也就是编译器和解释器
解释器做了啥
![image-20220114184845505](https://img-blog.csdnimg.cn/img_convert/13e5f00bddf4f0d7e1ec2f24bd9999f1.png)
我们将数据和程序发送给了解释器,解释器开始运行,有了输出,解释器相当于是一个在线的
![image-20220114185018915](https://img-blog.csdnimg.cn/img_convert/5e0e7b647bb11966d3144ccc640e2105.png)
写一个程序,产生了一个可执行文件,当然不只是可执行文件
可能是汇编,字节码之类的,
现在你不需要输入数据,就能得到输出
在结构中就是线下,
当然是相对于解释器的,解释器需要结合一个数据进行执行,而编译器不需要
![image-20220114185325263](https://img-blog.csdnimg.cn/img_convert/00699daddbd98d0fc80a20a5d35811f4.png)
因此,我们不需要对程序进行重编译或者做其他处理,我们就能对可执行程序传入很多不同的值或数据集进行处理
编译器开发历史:
IBM 704软件成本超过了硬件成本
![image-20220114185938859](https://img-blog.csdnimg.cn/img_convert/0328988c77ca5ecd776ac3e5e961128e.png)
![image-20220114190037039](https://img-blog.csdnimg.cn/img_convert/df28b69e23fe854eaa5e56fedb62f3f6.png)
用解释器比你直接跑代码会慢很多,10-20倍
fortran
直接翻译成机器可执行的,会快很多
formulas translated 公式翻译
![image-20220114190246583](https://img-blog.csdnimg.cn/img_convert/f74afd1aaf90ca0c0a71b84500e8b54d.png)
![image-20220114190625171](https://img-blog.csdnimg.cn/img_convert/e732cc5237ca6445608af22e11074abc.png)
有些仍然保留了FORTRAN 1的框架
什么是fortran 1 框架呢
lexical Analysis 词法分析
parsing 解析
这两个共同关注语言的语法部分syntactic
semantic analysis 语义分析,关注语义方面,包括类型和作用域
optimization 优化 运行的更快,更节省
code generation 也就是translation 转换,转换结果可以是字节码,机器码,或者是另一种高级语言
![image-20220114191008501](https://img-blog.csdnimg.cn/img_convert/a8ee339f3c2fd97c8a6e7eeff8028885.png)
01-02: Structure of a Compiler (13m53s)【编译器结构】
first step:recognize words
对单词的认识/理解
![image-20220114214214204](https://img-blog.csdnimg.cn/img_convert/134c88bbdba4905528a2949670f489cb.png)
![image-20220114214239789](https://img-blog.csdnimg.cn/img_convert/c0cbd89c196a20961015778de733d9fa.png)
this is a sentence
你需要理解 大小写,空格,句点才能够正确的理解这个意思
如果给我们一个其他的
ist his ase nte nce
is this a sentence
我们也无法很容易得到结果
![image-20220114214432046](https://img-blog.csdnimg.cn/img_convert/489e8f5bc34d539e817c99251d7dc7a3.png)
词法分析的目标,就是将程序代码文本按照他的方式进行分词,
也就是对词的一个区分
这个句子,分为几个token呢(词法单元)
if,then,else,
x,y,z
1,2
=,空格
,
同时,我们仍然要区分一个等于号和两个等于号
句法分析
![image-20220114214723666](https://img-blog.csdnimg.cn/img_convert/4233e254b23d435cba78353d22d8a1dd.png)
![image-20220114214749082](https://img-blog.csdnimg.cn/img_convert/08bd438f8bf9ebf2b7b6d306c71f7617.png)
分析词的意思后(名词,动词,形容词),我们就会有句法
(主语subject,谓语verb,宾语object)
![image-20220114214856668](https://img-blog.csdnimg.cn/img_convert/c01aea118f087c6655eae151c3da9953.png)
![image-20220114214906888](https://img-blog.csdnimg.cn/img_convert/94ae39a4fca216957967815b435a6348.png)
共同构成了一个句子树,这就是一个英文句子进行语法分析的例子
代码也同理
![image-20220115120728962](https://img-blog.csdnimg.cn/img_convert/42197786a88a32629b74098aa311fd06.png)
针对if then else进行分析
if-then-else就是解析树的树根
如下为if-then-else的分析树
![image-20220115120852555](https://img-blog.csdnimg.cn/img_convert/35d5fdccaf533ad34ddac30ee704cc2e.png)
if then else
分成了三个部分,断言部分,then部分,else部分
if包含了 x == y
then包含了 z = 1
else 包含了 z = 2
句意分析
![image-20220115121122792](https://img-blog.csdnimg.cn/img_convert/156d40e502eaf38d42d10c6fc9425276.png)
当理解句子结构厚,我们就要去理解这句话写了什么内容
编译器只能做有限的语义分析,找到自相矛盾的地方,
![image-20220115121401909](https://img-blog.csdnimg.cn/img_convert/9a4625ab0614200b566a41ac515c91b2.png)
example
jack said jerry left his assignment at home
这里的his 我们无法知道他是指定jack还是jerry
![image-20220115121713821](https://img-blog.csdnimg.cn/img_convert/40723df83c30163f14e6bba3f8e05aa3.png)
worse
jaca said jack left his assignment at home
这个更糟糕的情况,我们不知道有几个人,jack是两个人,his是一个人?
可能性很多
![image-20220115121826017](https://img-blog.csdnimg.cn/img_convert/1ea92211aa5aba498eb1840c2ffe1a72.png)
![image-20220115121900533](https://img-blog.csdnimg.cn/img_convert/15577e68121f07ee47a02bde468d5c68.png)
编程语言中,为了避免这种尴尬,就有了变量绑定
非常严格的规则,防止歧义
如上的程序,会输出4
外层的定义jack会被隐藏
![image-20220115122012038](https://img-blog.csdnimg.cn/img_convert/18e0d4519f8cf8cc7004f26610288f4c.png)
编译器执行文本的语义分析时,不需要考虑对变量进行作用域的绑定分析
jack和her的类型不匹配,肯定不是一个人
optiimization(优化)
![image-20220115123507823](https://img-blog.csdnimg.cn/img_convert/b0720ba31d3a55026a78a74c5f9962ce.png)
比较像一个专业的编辑在一定的字数范围内对文章长度做删减
but a little bit like editing
替换为
but akin to editing
意思没变,但是词变少了,节省了资源
run faster,use less memory,lower power,database,network
一个需要优化的程序
![](https://img-blog.csdnimg.cn/img_convert/f96a30154ed079ab4e554d71892a5546.png)
y*0 和给x赋值为0 是一致的,因此我们比起乘法,仅仅做赋值即可
但是这个不是一个正确的规则
仅仅对integer有效
![image-20220115123941638](https://img-blog.csdnimg.cn/img_convert/2b77fa3a14e3e9de6cd586d28d2b1cc4.png)
浮点数无效,
finally code Gen
![image-20220115124119383](https://img-blog.csdnimg.cn/img_convert/b46e4994e9f90b1d13840055e2fe0404.png)
也就是翻译成其他语言,编译器把高级语言转换为汇编语言
![image-20220115124227579](https://img-blog.csdnimg.cn/img_convert/5fcd163e750f7b5bbd2854358dbe87d6.png)
最基本的fortran对于语义分析会很小
而现代的编译器,优化会占据很大
![image-20220115124308263](https://img-blog.csdnimg.cn/img_convert/607c67d7fbb3dd6cc1920d2ba03d3483.png)
01-03: The Economy of Programming Languages (19m51s)【编译器性价比】
![image-20220115180537506](https://img-blog.csdnimg.cn/img_convert/af28e4743033005fab6f5ca0ce5dcac2.png)
本节课,将会谈论这三个问题,
为什么这么多的语言
为什么又新的语诞生
什么是一个好的编程语言
首先第一个
why are there so many progamming languages
![image-20220115181057596](https://img-blog.csdnimg.cn/img_convert/5fae0a264a6086439c19e21cecc8f111.png)
首先我们是有三个大概的范围,应用领域不同
他们的优势不同,作用域不同,语言不同
科学研究:需要好的浮点数运算,FP,好的数组支持,大并行支持(parallelism)FORTRAN语言 (公式 翻译)fomulate translate
商业领域:需要好的稳定性,防止丢失数据,而且要可靠,需要报告的生成,数据分析,数据处理之类的, 也就是SQL比较常用
系统编程:也就是嵌入式,控制设备之类的,我们需要控制一些底层的资源,细粒度控制,需要能够预判时间(实时控制),在一定时间内做出反应,或者对网络进行大量的响应 广泛的就是c和c++
why are there new programming languages?
为什么需要设计一个新的语言
![image-20220115181648133](https://img-blog.csdnimg.cn/img_convert/fa243d9763657288c50df2c5236134e1.png)
培养程序员以及培养某种语言程序员的成本 这个比较重要,如何教会他们去使用
因为去开发,去开发一个新的编译器的成本并不是很高
有如下的预测
有两点,也就是
第一个预测是 广泛使用的编程语言改变的很慢,会越来越保守
第二个预测是 很容易的去开发一个新的语言,培训成本为0,新的编程语言进化的会很快。
productivity > tranning cost
生产力要大于学习耗费
就会选择新的语言
![image-20220115184117460](https://img-blog.csdnimg.cn/img_convert/efb4bd127a1a6092ae1f44b4531f2aeb.png)
什么时候呢?
需要一种语言去填补空白的时候(新的应用领域),往往 会选择新的语言
旧的语言不一定能够支持新的应用领域
新的语言有时候会看起来像旧的语言,就比如java很像c++
猜测:为了降低培训成本,通过学过的语言更轻松的去解除
![image-20220115184353195](https://img-blog.csdnimg.cn/img_convert/b504f8deadd89805b7db96643b980f98.png)
what is a good programming language?
从语言设计的通用性来说,没有一个好的编程语言
![image-20220115184510989](https://img-blog.csdnimg.cn/img_convert/4d712e914b98d855b2e6471aa09f463d.png)
讨论这个问题,无法达成共识,关于什么是好的语言,也没有普遍接受的共识,
讲师的猜测:
是大众的接受度/使用度,可以作为是一个好的语言的标准
![image-20220115184637859](https://img-blog.csdnimg.cn/img_convert/cc672c69e08556a28d5bb606fc742276.png)
Summarize
![image-20220115182920040](https://img-blog.csdnimg.cn/img_convert/5792ddb1ed86e3cbd7c49957bc084c21.png)
很难设计出一个整合你所有想要功能的语言
培养程序员花费了大量成本
02-01: Cool Overview (19m58s)【cool语言概述】
classroom object oriented language = cool
课堂专用面向对象语言
被设计短期内/一个学期内写出编译器,需要易于编写
![image-20220115191815059](https://img-blog.csdnimg.cn/img_convert/e8a99a8c8cf2bf0ab1b1215183d2369d.png)
本课程的目的:完整的编译器编写,包括MIPS 指令集
![image-20220115192007173](https://img-blog.csdnimg.cn/img_convert/e1f70a1ea0cfaca10c070442ab109bca.png)
我们可以运行编译器,也可以生成mips汇编语言,然后可以在你能访问的任何机器上模拟mips汇编语言
分为五个任务,编译器本身包含四个阶段
词法分析
语法分析
语义分析
代码生成
我们编写如上模块采用的是 插件兼容
也就是,我们可以使用模板填充其他几个,然后我们只是去编写词法分析,然后和标准输出进行比对,保证自己编写的足迹按没问题
![image-20220115192358338](https://img-blog.csdnimg.cn/img_convert/ac694ef88cc1151c8383b2d031a967b7.png)
优化可以当一个可选的作业
![image-20220115192530573](https://img-blog.csdnimg.cn/img_convert/41110e2755ed09611d021a60c7113fb1.png)
开始编写程序
1- 每个cool程序必须要有一名为main的class
class main{
};
class 后面跟名字,然后花括号带分号结尾
一个程序包含若干类
main类中,main方法必须存在,这个方法用来启动程序,此外,这个方法必须无参,main方法永远无参
class Main{
main():Int{
1
};
};
在main类中,有一个main方法
cool中,需要对方法指明返回值的类型,这里写int
cool是一种表达式语言,也就是一段代码
表达式可以写的随意一点,即这个表达式对于这个方法的表达而言没有显示的返回语句
() -> a+b ,返回a+b的值
上面那个方法体中只有一个数字1 所以运行程序的时候,返回的就是这个方法的值
那么如何编译?
coolc就是cool的编译器,
coolc 1.cl
就会生成1.s的新文件,
我们尝试运行,spim(mips模拟器)
接着出现了一些数据,例如 执行了多少条指令,load指令,store指令,和一些分支的数量
![image-20220115201325968](https://img-blog.csdnimg.cn/img_convert/8876864b96477d69a3a0b0cec2c4cc6b.png)
![image-20220115201354908](https://img-blog.csdnimg.cn/img_convert/7353b489715612ba2cde4dbdcf5c08cb.png)
spim 1.s
![image-20220115201413073](https://img-blog.csdnimg.cn/img_convert/105af166a4067e9670b5c000f7e22e0e.png)
stat里面的参数是为了让我们进行优化使用的,现在我们不需要考虑
如果在cool程序中打印出某些内容,则必须对此操作进行明确声明
cool中有特殊的类,也就是IO原始类
可以为main这个类进行属性的声明,我们声明一个属性为IO的i变量,同时给i分配一个新的对象,之后就能用它进行IO操作了
class Main{
i : IO <- new IO;
main():Int{
1
};
};
在main方法中,添加out_string的调用,
i.out_string()
就是我们调用方法的方式
我们尝试输出helloworld
![image-20220115205628141](https://img-blog.csdnimg.cn/img_convert/f617fe6dc99f179041703e51e610b073.png)
class Main{
i : IO <- new IO;
main():Int{
{
i.out_string("Hello World\n");
1;
};
};
方法中语句块由用分号分隔的一系列表达式组成,
tips:
感叹号小贴士
!运算符跟着之前输入的命令前缀,就可以执行之前的命令
例如:
执行过coolc 1.cl
那么我们执行
!c
和coolc 1.cl是一样的
修改:
{i.out_string(“hello world”);}1; 很繁琐,修改成如下问题,但是返回值类型会不同,不是int了,类型匹配出错
class Main{
i : IO <- new IO;
main():Int{
i.out_string("Hello World\n");
};
};
因此我们修改成IO
class Main{
i : IO <- new IO;
main():IO{
i.out_string("Hello World\n")
};
};
当然我们可以增加自己的灵活性
![image-20220115205916729](https://img-blog.csdnimg.cn/img_convert/7ad423cb5a0f5b1a91f9b20225db3db5.png)
main返回结果设置为object
class Main{
i : IO <- new IO;
main():Object{
i.out_string("Hello World\n");
};
};
![image-20220115205952590](https://img-blog.csdnimg.cn/img_convert/6fa3968bf12aef58730950261ba1cea3.png)
这里我们在外面进行定义,我们可以直接在里面调用
class Main{
main():Object{
(new IO).out_string("Hello World\n");
};
};
或者说,我们main类直接继承io,main就能够拥有io的所有功能,cool中self等于this
class Main inherits IO{
main():Object{
self.out_string("Hello World\n");
};
};
或者,cool的特性,不显式命名调用对象的情况下调用方法默认为self
class Main inherits IO{
main():Object{
out_string("Hello World\n");
};
};
![image-20220115210052980](https://img-blog.csdnimg.cn/img_convert/f5c79b8e163ebf9a03a5b916acda31fb.png)
02-02: Cool Example II (15m04s)【cool样例2】
这次我们写阶乘,不写hello world
class Main{
main():Object{
(new IO).out_string("1\n")
};
};
我们想让用户输入,然后进行输出
需要调用in_string,同时为了美观,我们组合一个换行
class Main{
main():Object{
(new IO).out_string((new IO).in_string().concat("\n"))
};
};
![image-20220116185309293](https://img-blog.csdnimg.cn/img_convert/cc5b4fcd8f159fc5c350ac40c0357223.png)
我们输入多少,就会返回多少
接下来,我们讨论如何将字符串转换为整数
阶乘计算需要对数字,我们这里接受的是字符串
cool中有一个专门编写的库用来做整数和字符串之间的转换
也就是A2I 意思是ascii码转换为整数
class Main inherits A2I{
main():Object{
(new IO).out_string(i2a(a2i((new IO).in_string())+1).concat("\n"))
};
};
代码的意思就是,输入的字符串ascii转整数 然后加一然后 整数转ascii(字符串)输出
但是编译器中没有提供a2i的相关函数,需要我们在编译的时候,指明我们需要的函数,
coolc fact.cl atoi.cl
![image-20220116191215298](https://img-blog.csdnimg.cn/img_convert/60394f3363819ee9f3dfa5d98faa251a.png)
我们找到相关atoi.cl库函数
复制到code中,即可编译完成
![image-20220116191308282](https://img-blog.csdnimg.cn/img_convert/06205bce9c2c63b949925a1bbe87becb.png)
![image-20220116191331658](https://img-blog.csdnimg.cn/img_convert/df8c84d0521f83acbeb9b4786db97c37.png)
我们来编写阶乘,需要调用fact(阶乘)函数
在cool中,if的结构是 if-then-else-fi 也就是一个完整定义
这里可能会感到奇怪,i=0不是赋值么,但是这里确实是一个判断
class Main inherits A2I{
main():Object{
(new IO).out_string(i2a(fact(a2i((new IO).in_string())).concat("\n"))
};
fact(i:Int):Int{
if(i = 0) then 1 else i * fact(i-1) fi
};
};
![image-20220116201526983](https://img-blog.csdnimg.cn/img_convert/21808453d68f93491c0f3a35929e39f2.png)
我们尝试把i == 0试试
![image-20220116201607033](https://img-blog.csdnimg.cn/img_convert/81d7d848b1227e5c168301f2c2e7981c.png)
发现编译失败
我们接下来使用循环来写阶乘
我们在cool中使用let声明局部变量
定义fact值为1
cool中赋值为<-
循环的开始和结束是loop和pool
最后一个语法块的值,就是这个方法的返回值
class Main inherits A2I{
main():Object{
(new IO).out_string(i2a(fact(a2i((new IO).in_string()))).concat("\n"))
};
fact(i:Int):Int{
let fact:Int <- 1 in{
while(not (i = 0)) loop
{
fact <- fact *i;
i <- i-1;
}
pool;
fact;
}
};
};
![image-20220116225035970](https://img-blog.csdnimg.cn/img_convert/d4084ac44cb0a8104f382716927faafd.png)
![image-20220116225045536](https://img-blog.csdnimg.cn/img_convert/5cfd89dbd88a2273d0a9da2f40cca27c.png)
02-03: Cool Example III (18m05s)【cool样例3】
本次课程,我们学习创建list
let表达式可以定义多个常量,使用逗号做分隔符
class Main inherits IO{
main() : Object{
let hello : String <- "Hello",
world : String <- "World!!",
newline : String <- "\n"
in
out_string(hello.concat(world.concat(newline)))
};
};
![image-20220117152937329](https://img-blog.csdnimg.cn/img_convert/675014c1291b4ba9df2861fc0907e5fe.png)
没有问题
然后,我们不使用这样的引入,而是使用一个抽象的list,构建字符串列表
list都会包含两部分,一个是值,一个是next指针指向其他list
nil:List 如果不赋值,默认是为空的也就是void
isvoid cool自带的检查是否为空
class List{
item:String;
next:List;
init(i:String, n:List):List{
{
item<-i;
next<-n;
self;
}
};
flatten():String{
if(isvoid next) then
item
else
item.concat(next.flatten())
fi
};
};
class Main inherits IO{
main() : Object{
let hello : String <- "Hello",
world : String <- "World!!",
newline : String <- "\n",
nil:List,
list:List <- (new List).init(hello,(new List).init(world,(new List).init(newline,nil)))
in
out_string(list.flatten())
};
};
![image-20220117165446742](https://img-blog.csdnimg.cn/img_convert/4744944fafcedf0a114027d23a243c09.png)
同样,成功输出
我们这里item可以进行修改,成为object
同时,我们需要修改flatten,通过case进行选择他的类型进行输出
如果传入int 那就i2a,其他同理
abort函数,终止并退出,返回一个object对象,但是这里的case需要返回stirng对象,我们放入语句块中
case分支必须分号结束
class List inherits A2I{
item:Object;
next:List;
init(i:Object, n:List):List{
{
item<-i;
next<-n;
self;
}
};
flatten():String{
let string:String <-
case item of
i:Int => i2a(i);
s:String =>s;
o:Object =>{abort();"";};
esac
in
if(isvoid next) then
string
else
string.concat(next.flatten())
fi
};
};
class Main inherits IO{
main() : Object{
let hello : String <- "Hello",
world : String <- "World!!",
i:Int <-42,
newline : String <- "\n",
nil:List,
list:List <- (new List).init(hello,
(new List).init(world,
(new List).init(i,(new List).init(newline,nil))))
in
out_string(list.flatten())
};
};
![image-20220117171820955](https://img-blog.csdnimg.cn/img_convert/96f2825ebcde439c4855ebe39bbe1f41.png)
![image-20220117171939514](https://img-blog.csdnimg.cn/img_convert/634767d27a75dbadc5badc9538a654ad.png)
CS-143 Week2 Lexical Analysis&Finite Automata[词法分析和有限自动机]
03-01: Lexical Analysis (12m06s)【词法分析】
![image-20220117230455219](https://img-blog.csdnimg.cn/img_convert/3b9c1b75622111298ab531fdaa873e58.png)
我们对该段进行分割
if(i == j)
z = 0;
else
z = 1;
将他们转换成为(token)词法单元,if,变量名 i,n,j 关系运算符,== 之类的
在词法分析器的眼中,是这样的
![image-20220117230652340](https://img-blog.csdnimg.cn/img_convert/5faffa5d7dbe86d8cf83b30d91b05dde.png)
\tif(i==j)\n\t\tz=0;\n\telse\n\t\tz=1;
整个代码就像字符串,也可以类比作为字节
词法分析器通过绘制分割线,将字符串转换为词法单元
![image-20220117230859758](https://img-blog.csdnimg.cn/img_convert/2473bb9e4fa0e18e72aeafe5adb2180d.png)
Token class(标记类)
光分词法单元是不行的,需要根据作用进行分类
![image-20220117231116936](https://img-blog.csdnimg.cn/img_convert/ad8e3882e0c0614f322dd39ad7de3abf.png)
这里类比在英语中,和在编程语言中的标记类
每个标记类,都会对应程序中的一组字符串,
比如:
名词:apple,banana,。。。
keywords:if,else,while
![image-20220117231829212](https://img-blog.csdnimg.cn/img_convert/563cee0e2cb9bd25e3f5c156b209f00a.png)
标记类对应一组字符串,也就是,这组字符串可以用来被标记类描述
identifier(标识符)
大多数编程语言中,标识符的标记类是字母或数字,以字母开头
例子:C语言中
integer(整数)
非空数字字符串
例:0,12,001,00,
keyword:
keywords:if,else,while
whitespace(空格)
空格也是一个标记类
例:if_ _ _()这里三个空格,就会被当作一个空格
![image-20220117232258929](https://img-blog.csdnimg.cn/img_convert/05611e224d3c63f388c5847aec9fbccf.png)
词法分析的目标是根据程序的子串的角色,然后对其进行分类
这里的role就是一个标记类
然后把标记类传递给解析器
这里是词法分析器和解析器之间的传递
![image-20220117233018987](https://img-blog.csdnimg.cn/img_convert/8d5a6e528b455a0dec152f7abb6d76f7.png)
1- 词法分析器获取到字符串,并存储为字节序列
2-发送给解析器的时候是一个序列对<class,string>
,也就是,标记类和你的子字符串,也就是<class,string>
这个pair叫做token
例如:
如果字符串是
“foo = 42”
会传递三个token(词法单元)
<identifier,“foo”>,<operator,"=">,<“integer”,“42”>
传递的单元是以字符串形式来存储的,这里的42
也是字符串
这些序列传递给解析器
词法分析器本质:
输入字符串并将其分块儿为成对的序列,其中每一个对都是一个标记类和原始输入的子字符串
样例分析
\tif(i==j)\n\t\tz=0;\n\telse\n\t\tz=1;
我们首先写一下标记类
whitespace 空格,回车,tab
keywords
identifiers
numbers(integer)
operator
特例: (
、)
、;
、=
这四个是单字符标记类,一组中只有这一个字符串
但是一个特殊的==
归类为关系运算符的标记类
这里使用开头首字母当作划分
\tif(i == j)\n\t\tz=0;\n\telse\n\t\tz=1;
w|k|(|i|w|o|w|i|)|w|w|w|i|=|n|;|w|w|k|w|w|w|i|=|n|;
![image-20220117234252414](https://img-blog.csdnimg.cn/img_convert/dc3369481d908f425f623f11b3ca530c.png)
Summarize
![image-20220117232922147](https://img-blog.csdnimg.cn/img_convert/15e18737ad71ce8e5204767a7c21dfff.png)
总结两点,
第一个:识别输入中与标记相对应的子字符串
tips 这是编译器的术语,这些子字符串称为词素lexemes(构成词的要素)
第二个,对于每个词素,我们需要确定标记类token class
<token class,lexemes>
等于token
Quiz
![image-20220118224348639](https://img-blog.csdnimg.cn/img_convert/2da35d78fbd7dff2db971e40d606fc9e.png)
x=0;\n\twhile (x < 10) { \n \tx++; \n }
W: Whitespace
K: Keyword
I: Identifier
N: Number
O: Other Tokens:
{ } ( ) < ++ ; =
ionowwkwoiwownwowwwwioowwwo
虽然对空格有异议,但是I K N 是固定的,3 1 2
Note that '\t\n' is a single whitespace token. Also remember that 'x' is an identifier but 'while' is a keyword. Finally, note that '++' and '10' are both single tokens.
请注意“\t\n”是单个空白标记。还要记住,“x”是一个标识符,“while”是一个关键字。最后,请注意,'+'和'10'都是单个标记。
![image-20220118234521133](https://img-blog.csdnimg.cn/img_convert/502a1dbbbbdcc1c623524255913fb017.png)
03-02: Lexical Analysis Examples (13m03s)【词法分析案例】
![image-20220118145448794](https://img-blog.csdnimg.cn/img_convert/4a9a4aeb741caf90665786ce64dd9c35.png)
在fortran中,空格是不重要的
例如:VAR1
和 VA R1
是一样的
fortran理念:你可以将程序中所有的空格删除,但是不会改变你程序想要表达的东西
tips:以后的例子部分来自龙书
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)