编译原理笔记

语法分析

元素

  1. LL(1)分析
  2. First 集合
  3. Follow 集合
  4. 文法 G = ( V N , V T , P , S ) G=(V_N, V_T, P, S) G=(VN,VT,P,S),其中 V N V_N VN是非终结符, V T V_T VT是终结符, P P P是产生式, S S S是起始符号
  5. 产生式的后缀 u u u(自取,表示产生式箭头后的部分)
  6. 预测集合 P S ( A → α ) PS(A\rightarrow \alpha) PS(Aα),其中 A → α A\rightarrow \alpha Aα是一个产生式
  7. 预测分析表 M M M
  8. 下推栈和余留字符串
  9. 递归下降LL(1)分析程序
  10. 左递归的文法(直接左递归,间接左递归)
    在这里插入图片描述
  11. 无回路的文法
  12. 左公因子
    在这里插入图片描述

符号表示

  1. S S S为一个字符集合,那么 S ∗ S^* S表示这个集合中的所能组合成的所有句子,包括 ε \varepsilon ε
    例子:{“ab”, “c”}* = {ε, “ab”, “c”, “abab”, “abc”, “cab”, “cc”, “ababab”, “ababc”, “abcab”, “abcc”, “cabab”, “cabc”, “ccab”, “ccc”, …}

关系

  1. 给定一个文法 G G G和一个集合 X G X_G XG,其中 X G ⊂ { V N ∪ V T } ∗ X_G \subset \{V_N \cup V_T\}^* XG{VNVT},求这个集合 X G X_G XG的first集合

    1. 先求 { V N ∪ V T } \{V_N \cup V_T\} {VNVT}的first集合
      1. 对于 G G G中的任何一个终结符 a a a f i r s t ( a ) = { a } first(a)=\{a\} first(a)={a},包括 f i r s t ( ε ) = { ε } first(\varepsilon)=\{\varepsilon\} first(ε)={ε};对于 G G G中任何一个非终结符 A A A f i r s t ( A ) = ∅ first(A)=\varnothing first(A)=

      2. G G G的所有产生式的后缀 u u u的first集合
        举例,如产生式后缀 D a B DaB DaB,假设 f i r s t ( D ) = d , ε first(D)={d, \varepsilon} first(D)=d,ε f i r s t ( B ) = b first(B)={b} first(B)=b

        1. 对于任意一个 u u u f i r s t ( u ) = ∅ first(u)=\varnothing first(u)=
        2. 遍历 u u u的所有字符
        3. 如果遇到的是一个非终结符 A A A
          1. 那么遍历它的first集合,将其终结符加入 f i r s t ( u ) first(u) first(u)中(包括 v a r e p s i l o n varepsilon varepsilon)
          2. 如果 ε ∈ f i r s t ( A ) \varepsilon \in first(A) εfirst(A),那么继续查看下一个字符
          3. 否则将 f i r s t ( u ) first(u) first(u)中的 v a r e p s i l o n varepsilon varepsilon删掉,直接退出
        4. 如果遇到的是一个终结符 a a a
          1. a a a加入 f i r s t ( u ) first(u) first(u),将 f i r s t ( u ) first(u) first(u)中的 v a r e p s i l o n varepsilon varepsilon删掉,退出

        D a B DaB DaB为例, D D D的所有终结符 d d d加入 f i r s t ( u ) first(u) first(u) D D D ε \varepsilon ε元素,那么查看下一个,下一个是终结符 a a a,将 a a a加入 f i r s t ( u ) first(u) first(u),退出,所以 f i r s t ( u ) = { d , a } first(u)=\{d,a\} first(u)={d,a}

      3. G G G的所有产生式的后缀 u u u的first集合赋给其对应的非终结符

      4. 回到2,进行循环,直到集合中所有 u u u的first集合相对于上一轮都不再变动

    2. X G X_G XG中字符串的first集合可以以1.1.2中的方法计算出来,所有的字符串的集合累积到一起就是 X G X_G XG的first集合
  2. 给定一个文法 G G G,对所有属于 V N V_N VN的非终结符 A A A,求 F o l l o w ( A ) Follow(A) Follow(A)
    在这里插入图片描述

  3. 给定一个文法 G G G和其中的一个产生式 A → α A\rightarrow \alpha Aα求这个产生式的预测集合

    1. 如果 ε ∉ F i r s t ( α ) \varepsilon \notin First(\alpha) ε/First(α),那么 P S ( A → α ) = F i r s t ( α ) PS(A\rightarrow \alpha)=First(\alpha) PS(Aα)=First(α)
    2. 如果 ε ∈ F i r s t ( α ) \varepsilon \in First(\alpha) εFirst(α),那么 P S ( A → α ) = ( F i r s t ( α ) − { ε } ) ∪ F o l l o w ( A ) PS(A\rightarrow \alpha) = (First(\alpha)-\{\varepsilon \})\cup Follow(A) PS(Aα)=(First(α){ε})Follow(A)
  4. 给定一个文法 G G G,判断该文法是否是LL(1)的
    文法 G G G是LL(1)的,当且仅当对于 G G G中任何两个相同左部的不同产生式 A → α A\rightarrow \alpha Aα A → β A\rightarrow \beta Aβ,都满足 P S ( A → α ) ∩ P S ( A → β ) = ∅ PS(A\rightarrow \alpha)\cap PS(A\rightarrow \beta)=\varnothing PS(Aα)PS(Aβ)=

  5. 给定一个文法 G = ( V N , V T , P , S ) G=(V_N,V_T,P,S) G=(VN,VT,P,S),求它的预测分析表 M M M

    1. 搭建表的框架,表的每一行都对应 G G G的一个非终结符,表的每一列对应 G G G的所有终结符加上#符号
      在这里插入图片描述
    2. 往表内填写内容,检查文法的每一个产生式 A → α A\rightarrow \alpha Aα,若它的预测集合 P S ( A → α ) PS(A\rightarrow \alpha) PS(Aα)中包含 a ∈ V T ∪ { # } a\in V_T\cup \{\#\} aVT{#},则将 A → α A\rightarrow \alpha Aα加入 M [ A , a ] M[A, a] M[A,a](即表 M M M A A A, a a a对应的位置)
  6. 给定一个文法 G G G与它的预测分析表,求它的LL(1)分析过程

    1. 创建两个栈:下推栈和余留字符串,并将#号分别推入两个栈中
    2. 将初始符号 S S S推入下推栈,将输入的符号串推入余留字符串(注:右边的字符先入栈)
    3. 检查下推栈栈顶
      1. 如果栈顶是终结符,那么比对下推栈和余留字符串的栈顶是否匹配,若匹配就将两个栈顶都弹出,不匹配就进行错误处理。
      2. 如果栈顶是非终结符,则以该非终结符和余留字符串的栈顶作为坐标到预测分析表中查找,如果对应位置是一个产生式,那么将下推栈栈顶出栈,并将该产生式的后缀入栈(注:右边的字符先入栈);如果对应位置为空,那么报错
    4. 回到3进行循环,直到两栈栈顶同时为#,分析结束
  7. 给定一个文法 G G G,写出它的递归下降LL(1)分析程序

    1. 先求出 G G G中所有非终结符的预测集合
    2. 对于 G G G中的每一个非终结符 A A A
      1. 找到 A A A的产生式集合 A → u 1 ∣ u 2 ∣ . . . ∣ u n A\rightarrow u_1|u_2|...|u_n Au1u2∣...∣un
      2. 写出它的一个函数void ParseA(),其结构为
        	void ParseA(){
        		switch (lookahead){
        			case PS(A->u1):
        				...
        				break;
        			case PS(A->u2):
        				...
        				break;
        			...
        			case PS(A->un):
        				...
        				break;
        			default:
        				printf("syntax error\n");
        				exit(0);
        		}
        	}
        	// 这里lookahead是一个全局变量,存放扫描的终结符
        
      3. 对于每一个case,遍历其产生式后缀从左到右的符号
        1. 如果是一个终结符 a a a,那么写上一句MatchToken(a);
        2. 如果是一个非终结符 A A A,那么写上一句ParseA();
    3. 给出MatchToken的逻辑
      	void MatchToken(int expected){
      		if (lookahead != expected){
      			printf("syntax error\n");
      			exit(0);
      		}
      		else
      			lookahead = getToken();
      	}
      
  8. 给定一个含有直接左递归的产生式,将其消除左递归
    假设这个产生式为
    P → P α 1 ∣ P α 2 ∣ . . . ∣ P α m ∣ β 1 ∣ β 2 ∣ . . . ∣ β n P\rightarrow P\alpha_1|P\alpha2|...|P\alpha_m|\beta_1|\beta_2|...|\beta_n PPα1Pα2∣...∣Pαmβ1β2∣...∣βn
    其中 α i ≠ ε \alpha_i\neq \varepsilon αi=ε β j \beta_j βj不以 P P P开头

    1. 增加一个非终结符 Q Q Q
    2. 将产生式改为
      P → β 1 Q ∣ β 2 Q ∣ . . . ∣ β n Q Q → α 1 Q ∣ α 2 Q ∣ . . . ∣ α m Q ∣ ε \begin{align*} &P\rightarrow \beta_1Q|\beta_2Q|...|\beta_nQ\\ &Q\rightarrow \alpha_1Q|\alpha_2Q|...|\alpha_mQ|\varepsilon \end{align*} Pβ1Qβ2Q∣...∣βnQQα1Qα2Q∣...∣αmQε
  9. 给定一个无回路,无 ε \varepsilon ε产生式的文法,将其消除左递归(包括两种左递归)
    (一般题目给定的应该就是无回路也无 ε \varepsilon ε产生式的文法)

    1. 以某种顺序(随便的顺序)将文法非终结符排列成 A 1 , A 2 , . . . A n A_1, A_2,...A_n A1,A2,...An
    2. 进行消除 在这里插入图片描述
    3. 化简从2中得到的产生式集
  10. 给定一个产生式,提取其左公因子
    假设该产生式为
    P → α β 1 ∣ α β 2 ∣ . . . ∣ α β m ∣ γ 1 ∣ γ 2 ∣ . . . ∣ γ n P\rightarrow \alpha \beta_1|\alpha \beta_2|...|\alpha \beta_m|\gamma_1|\gamma_2|...|\gamma_n Pαβ1αβ2∣...∣αβmγ1γ2∣...∣γn

    1. 增加一个非终结符 Q Q Q
    2. 改写产生式为
      P → α Q ∣ γ 1 ∣ γ 2 ∣ . . . ∣ γ n Q → β 1 ∣ β 2 ∣ . . . ∣ β m \begin{align*} &P\rightarrow \alpha Q|\gamma_1|\gamma_2|...|\gamma_n\\ &Q\rightarrow \beta_1|\beta_2|...|\beta_m \end{align*} PαQγ1γ2∣...∣γnQβ1β2∣...∣βm
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值