编译器-上下文无关语法

context-free grammars 上下文无关语法
这个用于parsing(句法分析)

能被finite automata 识别的语言叫做regular language
context-free language 包含 regualr language

例如以下language属于context-free 但是不属于 regular 

L = \left \{ a^nb^n | n\geq 0\right \}

S\rightarrow aSb | \epsilon

 G = (V, T, P ,S)

V : set of variables(non-terminals)
T : set of terminals
P : set of productions
S : start varible

注意 这里的V, T, P ,S只是代表语法中的四种类型 
比如下面的三行语法 
\\S \rightarrow S1S2 \\S1 \rightarrow aS1b | \epsilon \\S2 \rightarrow bS2 | b
S1这种在后续还需要被替代 所以属于V非终止变量
第三行的b这种不需要再被后续替换了 属于T终止变量
一共有三行 所以有三个P输出结果
S是起始位置 就是上图的S 
⚠️:语法中的字母不是固定的 可以使用任何字母 

Derivation Tree for aaabbb

 例2

L2 = \left \{a^nb^m | n\geq 0,m> n \right \}

 aabbbb
第一种思路可以把aabb看作一个整体 在其后面加上了些bb
\\S \rightarrow S1S2 \\S1 \rightarrow aS1b | \epsilon \\S2 \rightarrow bS2 | b

aabbbb

第二种思路是把 bb看作是整个string的中央 如果a和b数量相等 就是ab 但是当b的数量大于a的时候 这时中央部分必然只包含b

\\S \rightarrow aSb | B \\B \rightarrow bB | b

context-free : 上下文无关
context-sensitive : 上下文有关
那么context-free和context-sensitive的区别 :
context-free左边只有一个变量即S \rightarrow aSbbbb 而context-sensitive就是aSb \rightarrow aSbbbb左边即有变量varible 又有terminal

∑ = {ident,num,if,else,+,-,……}

总的来说 在词法分析的阶段 我们会把一个字符串作为输入给scanner 然后scanner会判断这是一个变量还是数字还是特殊字符还是赋值符号等等……
在计算机高级语言中 我们把变量名(identifier) 这一个类作为计算机语言表中的一个symbol 在scanner(词法分析)的过程中 无疑就是传入了一个字符串 返回一个类别 把各种类别组合在一起 形成了context-free language 然后用特定的grammar语法定义去判断这一堆类别组合是不是符合所规定的语法 如果不合规就会出现编译错误

x12 = abc + def ;
这里用类别看就是   ident = ident + ident ;即ident = Expr ;

Assign → ident = Expr ;
Expr → ident + ident 

这两行语法就可以support上面的一行代码 但是不通用 只限于上面的代码

//我们发现上面的代码只能做加法 同时这个Expr只支持两个的ident  所以我们修改一下 使得更通用
 Assign → ident = Expr ;
Expr → Expr Op ident|ident

Op → + |- | * | /

我们用一个实例来演示一下parsing tree (句法分析树)
⚠️:parsing tree之后会被我们转换成AST :abstract syntax tree(抽象语法树)然后AST才会被转换成IR :intermidiate representation
x = a + b * c ;

 但是我们发现还存在一个问题 目前按照这个语法 会先做加法运算 再做乘法运算 这显然是不合数学规则逻辑 还需要改进语法

x = a + b * c ;
在数学中 我们称a或者b*c 为一项(term) 把b*c中的b或者c称因子(factor)

Assign → ident = Expr ;
Expr → Expr + Term | Expr - Term | Term

Term → Term * Factor | Term / Factor | Factor

Factor → ident | num

 

 parsing tree是从底部开始向上运算 可以看到 这时候乘法*就处在了加号+的下面 

但是如果遇到 x = (a + b) * c - d; 呢?
这时在数学中(a + b)是一个factor       c也是一个factor       (a + b) * c是一个term
就形成了终极版本

Classic Expression Grammar :

Assign → ident = Expr ;
Expr → Expr + Term | Expr - Term | Term

Term → Term * Factor | Term / Factor | Factor

Factor → ident | num | ( Expr )

 

猜你喜欢

转载自blog.csdn.net/weixin_43754049/article/details/126245606