作业 04 文法和语言总结与梳理

1. 梳理第二章的内容,写一篇理解与总结。

 语言是一个记号系统,完整的定义包括语法和语义两方面。语法是一组说明语言的规则,文法是用来阐明这些语法规则的一个重要形式工具。语义包括静态语义和动态语义,阐明语义要比语法困难的多。

符号和符号串
字母表: 字母表是符号的非空有穷集合。
任何程序语言都有自己的字母表

符号串:由字母表中的符号组成的任何有穷序列称之为该字母表上的符号串,也称作”字”。

符号串的几个常用术语 : 设s是符号串

前缀 : 移走s的尾部的零个或多于零个符号
后缀 : 删去s的头部的零个或多于零个符号
子串 : 从s中删去一个前缀和一个后缀
子序列 : 从s中删去零个或多于零个符号(不要求是连续的)
逆转 : 将s中的符号按相反次序写出而得到的符号串。
长度 : 是该符号串中的符号的数目。

符号串的运算 :连接:设x和y是符号串,它们的连接xy是把y的符号写在x的符号之后得到的符号串。 

文法和语言的形式定义
文法G定义为四元组 (VN,VT,P,S),
其中, VN :非终结符号集; VT :终结符号集; P:规则的集合; S:开始符(识别符)。
注: VN, VT和 P 是非空有穷集。S是一个非终结符,它至少要在一条产生式中作为左部出现。VN和VT不含公共的元素,即VN∩VT=φ,用V表示VN∪VT ,称为文法G的字母表。

文法G(VN,VT,P,S)中规则集合P的说明 :
规则(产生式或生成式)是形如α→β的(α,β)有序对,其中α∈(VN∪VT)+,且至少含有一个非终结符,β∈(VN∪VT)* ,α 称为规则的左部,β 称作规则的右部。

文法的写法 :一般不用将文法G的四元组显式的写出来,只写出产生式即可,并约定第一条产生式的左部为识别符。习惯上大写字母表示非终结符,小写字母表示终结符,有时也将G写为G[S]

推导的定义 :
直接推导“⇒”:
α→β是文法G的产生式, 若有v, w满足v=γαδ, w=γβδ,其中γ∈V* ,δ∈V* ,则称v直接推导出w (记作 v ⇒ w), 也称w直接归约到v。
间接推导:
若存在v=w0⇒w1⇒…⇒wn=w (n>0)则记为 v⇒+ w,称作 v推导出 w (或w归约到v)
若有 v ⇒+ w 或 v=w, 则记为v ⇒* w

句型、句子的定义

句型:有文法G,若S ⇒* x,则称x是文法G的句型。

句子:有文法G,若S ⇒* x,且x∈VT* ,则称x是文法G的句子。

文法生成的)语言的定义

由文法G生成的语言记为L(G),它是文法G的一切句子 的集合: L(G)={x|S ⇒* x,其中S为文法的开始符号,x ∈VT* }

文法的类型
通过对产生式施加不同的限制,文法可分为以下四类:

0型文法:对任一产生式α→β,都有α∈(VN∪VT)+,且至少含有一个非终结符,β∈(VN∪VT)* 。
0型文法的能力相当于图灵机,可以表征任何递归可枚举集。
0型文法描述的语言为0型语言,用L0表示。
例如 : aSb→cAd
1型文法:对任一产生式α→β,都有|β|≥|α|, 仅仅 S→ε除外。
1型文法又称作上下文有关文法(context-sensitive):其产生式的形式为α1Aα2→α1βα2,即只有A出现在α1和α2的上下文中时,才允许β取代A。
该文法描述的语言为1型语言或上下文有关语言,用L1表示。
例如:aUb→aABBaab
2型文法:对任一产生式α→β,都有α是一个非终结符,β∈(VN∪VT)*
2型文法又称作上下文无关文法(context-free):该文法相当于对1型文法中的规则形式加以限制而得到的。
2型文法描述的语言为2型语言或上下文无关语言,用L2表示。
G[S]: S→AB, A→BS|0, B→SA|1
3型文法:任一产生式的形式都为A→aB或A→a,其中A∈VN ,B∈VN ,a∈VT*
3型文法又叫正规文法,产生的语言为3型语言(正规语言),是有穷自动机所接受的集合。
高级程序设计语言的单词符号,如标识符、无符号整数等都是采用3型文法来描述的。
G[S]: S→0A|1B|0, A→0A|1B|0S, B→1B|1|0

上下文无关文法及其语法树
上下文无关文法有足够的能力描述程序设计语言的语法结构。

语法树:是描述上下文无关文法句型推导的直观工具。

语法树的定义:
设G=(VN,VT,P,S)为一上下文无关文法,若一棵树满足下列4个条件,则此树为G的语法树(推导树) :

每个结点都有一个标记,此标记是V的一个符号
根的标记是S
若一结点n至少有一个它自己除外的子孙,并且有标记A,则肯定A∈VN
如果结点n的直接子孙从左到右依次为n1,n2,…,nk,并且标记分别为A1,A2,…,Ak,那么A→A1A2…Ak 一定是P中的一个产生式
语法树的结果:
从左到右读出叶子的标记而构成的符号串即为语法树的结果

规范推导、规范句型:

最左(最右)推导: 在推导的任何一步α⇒β,其中α,β是句型,都是对α中的最左(右)非终结符进行替换。 
最右推导又称为规范推导,由规范推导所得的句型称为规范句型。

文法的二义性和语言的二义性:
若一个文法存在某个句子对应两棵不同的语法树,则称这个文法是二义的
或者,若一个文法存在某个句子有两个不同的最左(右)推导,则称这个文法是二义的
判定任给的一个上下文无关文法是否二义,或它是否产生一个先天二义的上下文无关语言,这两个问题是递归不可解的,但可以为无二义性寻找一组充分条件
文法的二义性和语言的二义性是不同的概念。因为可能有两个不同的文法G和G’满足L(G)=L(G’),其中G是二义的,G’是无二义的。
如果产生上下文无关语言的每一个文法都是二义的,则说此语言是先天二义的。

句型的分析
句型分析就是识别一个符号串是否为某文法的句型,是某个推导的构造过程。在语言的编译实现中,把完成句型分析的程序称为分析程序(识别程序)。从左到右的分析算法,即总是从左到右地识别输入符号串,首先识别符号串中的最左符号,进而依次识别右边的一个符号,直到分析结束。(以后介绍的算法均属此类)

从左到右的句型分析算法分类:

自上而下分析法: 从文法的开始符号出发,反复使用文法的产生式,寻找与输入符号串匹配的推导。
自下而上分析法: 从输入符号串开始,逐步进行归约,直至归约到文法的开始符号。
从语法树的构造过程来理解两种句型分析方法

自上而下方法:从文法符号开始,将它做为语法树的根,向下逐步建立语法树,使语法树的结果正好是输入符号串。
自下而上方法:从输入符号串开始,以它做为语法树的结果,自底向上的构造语法树。

2. 尝试写出PL/0 语言的文法。(或者你认为比较好的语言规则)

整数n<整数> ::= [-] <数字> {<数字>}

<数字> ::= 0 | 1 | 2 | … | 8 | 9

标识符<标识符i> ::= <字母> { <字母> | <数字> }

<字母> ::= a | b | … | X | Y | Z

<数字> ::= 0 | 1 | 2 | … | 8 | 9

表达式e<表达式e> ::= [+|-] <项> { <加减运算符> <项> }

      <加法运算符> ::= + | -

      <项> ::= <因子> { <乘法运算符> <因子> }

<因子> ::= <标识符> | <无符号整数> | ‘(’ <表达式> ‘)’

<乘法运算符> ::= * | /

<无符号整数> ::= <数字> { <数字> }

<标识符i> ::= <字母> { <字母> | <数字> }

<字母> ::= a | b | … | X | Y | Z

<数字> ::= 0 | 1 | 2 | … | 8 | 9

条件语句:<条件语句> ::= if<条件>then<语句>

<条件> ::= <表达式> <关系运算符> <表达式> | ODD <表达式>

<语句> ::= <赋值语句> | <条件语句> | <当型循环语句> | <过程调用语句> | <读语句> | <写语句> | <复合语句> | <空语句>

<关系运算符> ::= = | # | < | <= | > | >=

<赋值语句> ::= <标识符id> := <表达式>

<条件语句> ::= if<条件>then<语句>

<当型循环语句> ::= WHILE <条件> DO <语句>

<过程调用语句> ::= CALL <标识符>

<读语句>  ::= READ ‘(’ <标识符> {,<标识符>} ‘)’

<写语句>  ::= WRITE ‘(’ <表达式> {, <表达式>} ‘)’

<复合语句> ::= begin <语句> {;<语句>} end

赋值语句:<赋值语句> ::= <标识符id> := <表达式>

<标识符id> ::= <字母> { <字母> | <数字> }

      <表达式> ::= [+|-] <项> { <加减运算符> <项> }

复合语句:<复合语句> ::= begin <语句> {;<语句>} end

      <语句> ::= <赋值语句> | <条件语句> | <当型循环语句> | <过程调用语句> | <读语句> | <写语句> | <复合语句> | <空语句>

函数:<函数> ::= <类型说明><函数名><复合语句>

      <复合语句> ::= begin <语句> {;<语句>} end

<语句> ::= <赋值语句> | <条件语句> | <当型循环语句> | <过程调用语句> | <读语句> | <写语句> | <复合语句> | <空语句>

程序:<程序> ::= <分程序>

<分程序> ::= [<常量说明部分>] [<变量说明部分>][<过程说明部分>] <语句>

<常量说明部分> ::= CONST <常量定义> { ,<常量定义> } ;

<常量定义> ::= <标识符> = <无符号整数>

<无符号整数> ::= <数字> {<数字>}

<变量说明部分> ::= VAR <标识符 > { , <标识符 > } ;

<标识符> ::= <字母> {<字母>|<数字>}

<过程说明部分> ::= <过程首部><分程序>{; <过程说明部分> };

<过程首部> ::= PROCEDURE <标识符> ;

posted @ 2019-09-26 21:13  椰梨  阅读(494)  评论(0编辑  收藏  举报