编程语言复习笔记
在期末复习的时候将上课课件以及课本内容进行了整理。
一、课程内容简介&&绪论
- 语法与语义
- 名字、绑定和作用域
- 数据类型
- 表达式与赋值语句
- 控制语句
- 子程序
- 高级语言属性
1.1 语言评价准则
- 可读性
- 整体简单性
- 正交性
- 语法设计:语言的形式能否反映语句的意义
- 可写性
- 简单性和正交性:较少量的基本结构和一套组合基本结构的一致规则 (即正交性),比简单地提供大量基本结构好得多
- 对抽象的支持
-
- 过程抽象:子程序实现排序,多处使用
- 数据抽象:用结构node表现二叉树的节点
- 表达性:较简捷程序实现大量计算
- 可靠性:任何情况下都能按设计的那样执行
- 类型检查
- 静态类型检查:编译时检查,例如JAVA
- 动态类型检查:运行时检查,例如JavaScript
- 异常处理:拦截运行时错误的措施,例如除零操作
- ==别名==:两个或者多个不同的名称访问同一个内存单元
- 成本(培训成本啊,编写成本啊啥的),重点成本:
-
- 用语言编程程序的成本
- 可靠性差的成本
- 维护程序的成本
- 其他特性(常用语言都有):
- 可移植性:JAVA是可移植的,C语言需要重新编译
- 普遍性:C语言是一种通用的语言,可用于系统开发和应用程序
- 定义良好性:JAVA有良好的官方文档
1.2 语言的分类
对于计算过程可以有多种不同看法,由此产生了不同的计算模型(范型),基于不同计算范型产生了不同的语言类(语言范型)
主要范型有:
- 过程式语言(命令式语言)
- 函数式语言
- 面向对象语言
- 声明式语言(Declarative)
- 脚本语言
1.2.1 过程式语言
计算看成一系列操作的执行 ,基本计算元素是一组基本操作。计算在一个环境里进行,操作的效果就是改变环境的状态。
语言提供一组描述组合操作的手段,提供的抽象手段是定义新操作(定义过程)
写程序是描述操作执行的顺序过程,描述状态和状态的变化
1.2.2 面向对象语言
计算看成是一批独立对象相互作用的效果 。
面向对象语言提供:
-
- 描述(定义)对象及其行为的机制
- 描述对象之间相互作用的机制
比较纯的面向对象语言:
- 基于类 的语言:Java
- 基于 对象 的语言:JavaScript,通过原型概念定义新的类似对象
1.2.3 函数式语言
计算看成对数据的函数变换。
基本计算元素是一组基本函数,提供各种函数组合机制(复合,函数选择),抽象手段是定义新函数(允许递归定义)
1.2.4 声明式语言
基本思想是:只描述需要做什么,不描述怎么做
包含:
-
- 逻辑式语言
- 关系式语言
- 基于约束的语言
1.2.5 脚本语言
- 提供一批高级数据结构,提供灵活的变量、函数、对象等机制
- 采用解释方式实现,使用灵活方便
- 许多脚本语言提供了高级的文本处理功能
- 例:shell、PHP、Perl、Python
1.3 语言的实现:抽象机器
机器语言可以看做是计算机硬件的“抽象”
高级语言可看作是一种“抽象计算机” 的机器语言
常用的实现方式:编译和解释
- 编译:将程序翻译成机器语言,翻译慢,执行快
- 解释:对程序进行解释执行,无翻译,执行慢
- 混合实现:将程序翻译成中间语言,并解释执行,较小翻译代价,较快执行速度
- 编译:将程序翻译成机器语言,翻译慢,执行快
二、语法与语义
2.1 概述
- 描述语言的难处之一:所有人都必须能理解这种概述
- 类似自然语言,程序语言描述也分为语法和语义(考点):
-
- 语法:语言的表达式、语句和程序单元的形式
- 语义:这些表达式、语句和程序单元的意义
- 语言是句子的集合
- 句子是由字符表中的字符组成的串
2.2 语法的形式化定义
2.2.1 上下文无关文法(形式语言内容)
定义:上下文无关文法G是一个四元组(V,T,P,S)
- V——非终结符的非空有穷集合,为了定义语言而引入的辅助符号
- T——终极符的非空有穷集合,可以出现在语言的句子中,且 V∩T=ϕ V ∩ T = ϕ
- S—— S∈V S ∈ V , 为文法G的开始符号
- P——形如 α−>β α − > β 的产生式的非空有穷集合,其中 α∈V,β∈(V∪T)∗ α ∈ V , β ∈ ( V ∪ T ) ∗
2.2.2 巴恩斯范式 BNF
BNF提供了两类符号:终结符和非终结符
终结符:被定义的语言的符号,最终可以出现在程序中
非终结符:是为了定义语言的语法而引入的辅助符号
一个非终结符表示语言中的一个语法类:
< stmt >表示语句
- < expr >表示表达式
一个语言的BNF语法定义由一组产生式(或规则)组成,其本质是一个上下文无关文法
产生式的形式是:
左部 → → 右部
- 左部:总是一个非终结符
- 右部:用 | 分隔的一个或多个终结符和非终结符的序列。<…>用于表示非终结符
一个简单的文法:
< program > ->< stmts >
< stmts >->< stmt >|< stmt >;< stmts >
< stmt >->< var >=< expr >
< var >->a|b|c|d
< expr>->< term>+< term>|< term>-< term>
< term>->< var>|const
==BNF的推导==
推导是一个或一系列产生式的应用
句型:由开始符号经过推导得到的字符串 例如:a=b+< var >
句子:只有终结符的句型 例如:a=b+const
最左推导:每次总是替换句型最左边的非终结符
最右推导:每次总是替换句型最右边的非终结符
推导树:推导的树形结构表示,例如
a=b+const
的语法树:
- 最左推导就是树的最左遍历
最右推导就是树的最右遍历
关于推导的练习 PPT
考虑下列BNF: < expr >-> < expr >+< expr >| < var >; < var >->a|b|c ;
写出其最左推导:
< expr >
=>< expr>+< expr>
=>< expr>+< expr>+< expr>
=>< var>+< expr>+< expr>
=>a+< expr>+< expr>
=>a+< var>+< expr>
=>a+b+< expr>
=>a+b+< var>
=>a+b+c写出其最右推导:
< expr>
=>< expr>+< expr>
=>< expr>+< expr>+< expr>
=>< expr>+< expr>+< var>
=>< expr>+< expr>+c
=>< expr>+< var>+c
=>< expr>+b+c
=>< var>+b+c
=>a+b+c画出推导树:
存在两颗推导树,说明存在二义性。
二义性:文法生成的句型有两个或多个语法树,例子为上图,在这里是结合性造成的。
可能造成二义性的原因
优先级
结合性
二义性:< expr> -> < expr> + < expr> | const
非二义性:< expr> -> < expr> + const | const
++与+:a+++b
if-then-else:
if < cond> then if < cond> then < stmt> else < stmt>
最后的else与谁匹配
解决二义性:
- 用==不同的非终结符==表示==不同的优先级==
- 低优先级的符号先出现
//例子
//二义性:
< expr>->< expr>< op>< expr>|const
< op>->+|-|*|/
//非二义性:
< expr>->< expr>< op_L>< term>|< term>
< term>->< term>< op_H>const|const
< op_L>->+|-
< op_H>->*|/
//非二义性(允许括号):
< expr>->< expr>< op_L>< term>|< term>
< term>->< term>< op_H>< factor>|< factor>
< factor>->const|’(‘< expr>’)’
< op_L>->+|-
< op_H>->*|/
==设计无二义性的BNF的练习(PPT)==
- 请设计一个描述布尔逻辑表达式的无二义性的BNF(考虑优先级和结合性)
- n请设计一个描述if语句的无二义性的BNF
1)左结合+(or,and,not)优先级依次变高
< expr>->< expr> or < term> | < term>
< term>->< term> and < factor> | < factor>
< factor>-> not < factor> | true | false
2)?
< stmt>->< matched>|< unmatched>
< matched>->if< logic_expr> then < matched> else < matched>|any non-if statement
< unmatched>->if then | if then < matched> else < unmatched>
扩展BNF——EBNF
! EBNF只是增加了可读性和可写性,并没有增加表达能力
- 用圆括号()表示多个选项:< expr>->< expr>( + | - ) < term>
- 用方括号[ ]表示可选部分:< if_stmt>->if< cond> then< stmt> [ else < stmt> ]
- 用花括号{ }表示0次或者多次重复:< ident>->letter{ letter|digit }
1)BNF 和 对应的EBNF
//BNF
< expr> -> < expr> + < term>
| < expr> - < term>
| < term>
< term> -> < term> * < factor>
| < term> / < factor>
| < factor>
//EBNF (左结合)
< expr> -> < term> {(+ | -) < term>}
< term> -> < factor> {(* | /) < factor>}
2)将 EBNF 转为 BNF
//EBNF
S->A{bA}
A->a[b]B
B->(c|d)e
//BNF
S->SbA|A
A->aB|abB
B->ce|de
==设计描述布尔逻辑表达表达式的EBNF==
//二义性
< bExpr>->< bExpr>(and|or)< bExpr>
< bFactor>-> not< bFactor>| true | false
//非二义性
< bExpr>->[< bExpr> or]< bTerm>
< bTerm>->[< bTerm> and]< bFactor>
< bFactor>->(not< Factor>|true|false)
2.3 属性文法
背景概述
- 有些语言的结构特点很难用BNF描述
- 类型兼容性规则:例如java中浮点数不能给整型变量赋值,反之则可以,BNF很难实现
- 变量声明规则:变量必须在使用前声明
- 这类语言规则成为==静态语义规则==
- 与程序执行过程中的意义只有间接关系
- 在编译时进行分析
- Knuth在1968年提出了==属性文法==
- 添加静态语义属性的上下文无关文法
- 既可以描述语法,也可以描述静态语义
一个例子引入属性概念
例子:形如id = id+id的赋值语句
- id的类型是整数或者浮点数
- +号两边的id的类型必须一样
- =左边id的类型必须匹配右边表达式的类型
- 右边的表达式的==类型==必须匹配它的==期望类型==
BNF:
< ass_stmt>->< var>=< expr>
< expr> ->< var> +< var>
< var> -> id
为了满足上述要求,需要:
- 表达式或变量的==实际类型==
- 表达式的==期望类型==
这些需求解的信息成为语义属性,简称属性
属性文法的具体定义
属性文法是具有以下附加特性的文法
每个文法符号X都有一个属性集A(X):
- ==综合属性==:沿语法树自底向上传递的语义信息==(-> 是综合属性)==
- ==继承属性==:沿语法树自顶向下、从左到右传递语义信息==(赋值= 是继承属性)==
- ==本质属性==:叶子结点(即终结符)的综合属性
每条产生式有一个==计算属性==的语义函数集
- 每条产生式有一个==分析静态语义==可能为空的谓词函数集
例子的详细解析
例子:形如id = id+id的赋值语句
- i