Context free grammer:上下文无关语法,是一种编码规范,也可以认为是一种替换规则。
相关概念如下:
- 非终结符(nonterminal):可被进一步替换的符号,也叫变量。通常在公式中用一个或多个大写英文字母表示的是非终结符,N表示非终结符的集合。
- 终结符(terminal):不可被替换的符号,在公式中用一个或多个小写英文字母表示非终结符,Σ表示终结符的集合。
- NUΣ:是N和Σ的并集,α∈NUΣ 表示α可以是终结符也可以非终结符,公式中的小写希腊字母是属于这种。α可以为空字符串。
- 产生式(production): 就是一条条的规则,如A->B C,大写字母P表示规则的集合
- 起始符S:特殊的非终结符,表示最高层的变量,相当于树结构的根节点。
一个简单的例子:
S----> A B
S----> A S B
A----> a
B----> b
箭头左侧代表LHS(Left Hand Side),右侧代表RHS(Right Hand Side)。
根据以上的文法,我们能够得到一个回文子串,aabb或aaabbb或…
一个稍复杂的例子:
文法 G 是一个结构 < N,T,P,S > ,其中 N 是一组非终结符,T 是一组终结符,P 是一组结果,而 S 是一个特殊的非终结符,称为文法的开始符号。语法是用来正式指定语言的语法。例如,考虑计算器表达式的语言,其中我们可以加、减、乘和除。我们还可以在单个内存位置中存储一个值,并在内存位置中取回该值。例如,(5S + 4) * R EOF 是这种语法中的一个句子。计算时,该表达式将产生值45。指定此语言语法的语法为:
G = < N,T,P,Prog >
N = { Prog,Expr,Term,Storable,Factor }
T = { number,+ ,-,* ,/,S,R,(,) ,EOF }
开始符号是 Prog,根据这些规则给出结果集。
答:
Prog -> Expr EOF
Expr -> Expr + Term | Expr - Term | Term
Term -> Term * Storable | Term / Storable | Storable
Storable -> Factor S | Factor
Factor -> number | R | ( Expr )
验证(5S + 4) * R EOF过程(每次替换一个终止符):
Prog => Expr EOF =>Term EOF =>Term * Storable EOF => Storable * Storable EOF =>Factor * Storable EOF => ( Expr ) * Storable =>EOF ( Expr + Term ) * Storable EOF => ( Term + Term ) * Storable EOF => ( Storable + Term ) * Storable EOF => ( Factor S + Term ) * Storable EOF => ( 5 S + Term ) * Storable EOF => ( 5 S + Storable ) * Storable EOF => ( 5 S + Factor ) * Storable EOF => ( 5 S + Factor ) * Storable EOF => ( 5 S + 4 ) * Storable EOF => ( 5 S + 4 ) * Factor EOF => ( 5 S + 4 ) * R EOF
以上结果存在缺陷,因为函数Expr首先会在递归下降解析器中去调用Expr函数,这样就进入了循环递归,称作左递归,为避免此现象,我们通常引入一个新的非终止符来替换RHS中的所有内容,所以我们得到新的结果集:
Prog -> Expr EOF
Expr -> Term RestExpr
RestExpr -> + Term RestExpr | - Term RestExpr | <null>
Term -> Storable RestTerm
RestTerm -> * Storable RestTerm | / Storable RestTerm | <null>
Storable -> Factor S | Factor
Factor -> number | R | ( Expr )
(CFG文法用来产生语言,而不是用来识别语言。因此对于语言创造者,文法用来描述所要创造的语言;对于阅读者,将文法转换为有限状态机,这个状态机可以识别这个文法产生的语言。)