【编译原理/类C编译器】(三)语法分析

说在前面

运行界面

在这里插入图片描述

流程

  • 语法分析使用的是 LL(1) 方法

    • 消除左递归
      i. 消除直接左递归
      ii.消除间接左递归

    • 消除回溯
      (上述两部分手动完成)

    • LL(1)分析条件

    1. 文法不含左递归
    2. 对文法中每个非终结符A的各个产生式的候选首符集两两不相交,即A→α1│α2│… │αn , FIRST(αi)∩FIRST(αj) = Φ,(i ≠ j)
    3. 对文法中的每个非终结符A,若它存在某个候选首符集中包含ε,则FIRST(A)∩ FOLLOW(A) = Φ
    • 对于文法G的每个文法符号X∈VT∪VN,构造FIRST(X)
    1. 若X∈VT,则FIRST(X)={X};
    2. 若X ∈VN,且有产生式X→a…, a∈VT,则把a加入到 FIRST(X)中,若有X→ε,则把ε加入FIRST(X);
    3. 若X∈VN , 且X→Y … , Y∈VN, 则 FIRST (Y) - {ε}加到 FIRST (X)中,若X →Y1Y2 … Yk , Y1, Y2, … ,Yi -1 ∈ VN , ε∈FIRST (Yj) (1<=j <= i -1)则 FIRST (Yi) - {ε}加到FIRST (X)中。
      特别地,若ε∈FIRST (Yj) (1<=j <= k ),则ε加入FIRST (X)
/**
* @func 求first(x) 非终结符的first集合
*/
this.FIRSTX = function () {
	//从后向前
	//non_terminal即文法的非终结符集合,产生式左部
	for (s = this.non_terminal.length - 1; s > 0; s--) {
	
		//productions为产生式集合
		for (jj = Productions.length - 1; jj >= 0; jj--) {
        	var Split_r = Productions[jj].split(" ");//分割产生式

			//1.若X∈VT,则FIRST(X)={X};
            for (kk = 2; kk < Split_r.length; kk++)
            	if (Split_r[kk] == this.non_terminal[s] && 
            	this.Is_terminal(Split_r[kk - 1]) && 
            	this.non_terminal_first[s].indexOf(Split_r[kk - 1]) < 0)
                	this.non_terminal_first[s] += " " + Split_r[kk - 1];

			//2 3
            if (Split_r[0] == this.non_terminal[s]) {
                if (Split_r[1] == "@" && 
                this.non_terminal_first[s].indexOf("@") < 0) {
                    this.non_terminal_first[s] += " @";
                    continue;
                }

                for (h = 1; h < Split_r.length; h++) {
                    if (this.Is_terminal(Split_r[h]) &&
                     this.non_terminal_first[s].indexOf(Split_r[h]) == -1)
                        this.non_terminal_first[s] += " " + Split_r[h];
                    if (this.Is_terminal(Split_r[h]))
                        break;

                    var Split_t = 
                    (this.non_terminal_first[this.Get_non_i(Split_r[h])] 
                    || "").split(" ");
                    for (k = 0; k < Split_t.length; k++)
                        if ((this.non_terminal_first[s] || 
                        "").indexOf(Split_t[k]) == -1 && Split_t[k] != "@")
                            this.non_terminal_first[s] += " " + Split_t[k];

                    if (this.Is_to_null(Split_r[h])) {
                        if (h == Split_r.length - 1 &&
                         this.non_terminal_first[s].indexOf("@") < 0)
                           this.non_terminal_first[s] += " @";
                    }
                    else
                       break;
                }
            }
        }
    }
}
  • 对于符号串α= X1X2… Xn,构造 FIRST (α)
  1. 置 FIRST(α) = FIRST (X1)
  2. 若对 1<=j<= i -1, ε∈FIRST (Xj), 则把FIRST(Xi) -{ε}加到FIRST(α)中;
  3. 若对1<= j <=n, ε∈FIRST (Xj), 则把ε加到 FIRST(α)中。
/**
 * 参数First_alpha_t即上面的 α
 */
this.FIRST_ALPHA = function (First_alpha_t) {
        var Split_r = First_alpha_t.split(" ");//分割α
        //这里的 α 为产生式的右部 “ X1 X2 ...... Xn”,用空格来分割
        //α最前面有个空格
        var bool_null = 0;
        var First_alpha_First_t = "";//α的first集合
        for (j = 1; j < Split_r.length; j++) {
            if (Split_r[j] == "@")
                continue;
                
			//1.置 FIRST(α) = FIRST (X1)
            if (this.Is_terminal(Split_r[j])) {
                First_alpha_First_t += " " + Split_r[j];
                break;
            }

            var Split_t = 
            this.non_terminal_first[this.Get_non_i(Split_r[j])].split(" ");
            //获取Alpha首字符的FIRST集合并分割

            if (Split_t.indexOf("@") >= 0)
                bool_null = 1;
            else
                bool_null = 0;
                
			//2.
            for (k = 0; k < Split_t.length; k++)
                if (Split_t[k] != "@" && 
                First_alpha_First_t.indexOf(Split_t[k]) == -1)
                    First_alpha_First_t += " " + Split_t[k];
                    //置 FIRST(α) = FIRST (X1) - {ε};

            if (bool_null == 0)
                break;

			//3.
            if (bool_null == 1 && j == Split_r.length - 1)
                First_alpha_First_t += " @";
        }

        return First_alpha_First_t;
    }
  • 对于文法G的每个非终结符,构造FOLLOW(A)
  1. 若A为文法开始符号,置#于FOLLOW(A)中;
  2. 若有产生式B→αAβ,则将FIRST( β) - {ε}加到FOLLOW (A)中;
  3. 若有B→αA 或 B → αAβ, 且β=> * ε;则将FOLLOW(B)加到FOLLOW(A)中;
  4. 反复使用以上规则, 直至 FOLLOW(A)不再增大为止
    /**
     * @func 求FOLLOWX
     */
    this.FOLLOWX = function () {
        if (this.non_terminal_follow[1].indexOf("#") < 0)
            this.non_terminal_follow[1] += " #";

        for (u = this.non_terminal.length - 1; u >= 0; u--) {
            for (w = Productions.length - 1; w >= 0; w--) {
                var Split_r = Productions[w].split(" ");
                for (z = 1; z < Split_r.length; z++)
                    if (Split_r[z] == this.non_terminal[u]) {
                        break;
                    }

                if (this.Is_terminal(Split_r[z + 1]) && (this.non_terminal_follow[u].indexOf(Split_r[z + 1]) < 0)) {
                    this.non_terminal_follow[u] += " " + Split_r[z + 1];
                    continue;
                }

                var temp_s = false;
                if (z >= 1 && z < Split_r.length - 1) {
                    var temp = "";

                    for (q = z + 1; q < Split_r.length; q++)
                        temp += " " + Split_r[q];

                    for (q = z + 1; q < Split_r.length; q++)
                        if (this.Is_to_null(Split_r[q]))
                            temp_s = true;
                        else {
                            temp_s = false;
                            break;
                        }
                    var follow_t = (this.FIRST_ALPHA(temp) || "").split(" ");
                    for (e = 0; e < follow_t.length; e++)
                        if (this.non_terminal_follow[u].indexOf(follow_t[e]) < 0)
                            this.non_terminal_follow[u] += " " + follow_t[e];
                }
                if (z == Split_r.length - 1 || temp_s) {
                    var Split_t = (this.non_terminal_follow[this.Get_non_i(Split_r[0])] || "").split(" ");
                    for (p = 0; p < Split_t.length; p++)
                        if (this.non_terminal_follow[u].indexOf(Split_t[p]) < 0 && Split_t[p] != "@")
                            this.non_terminal_follow[u] += " " + Split_t[p];
                }
            }
        }
    }
  • 构造预测分析表
  1. 对文法的每个产生式A ,执行(2)和(3)
  2. 对FIRST(α)的每个终结符a,把A 加入M[A, a]
  3. 如果在FIRST(α)中,对FOLLOW(A)的每个终结符b(包括#), 把A 加入M[A, b]
  4. M中其它没有定义的条目都是error
    /**
     * @func 初始化分析预测表
     */
    this.InitTable = function () {
        this.Init();

        var MAX = 0;
        while (1) {
            this.FIRSTX();
            var count = 0;
            for (y = 0; y < this.non_terminal.length; y++)
                count += (this.non_terminal_first[y] || "").length;

            if (count > MAX)
                MAX = count;
            else
                break;
        }

        this.FIRST_ALPHA_ALL();

        MAX = 0;
        while (1) {
            this.FOLLOWX();
            var count = 0;
            for (x = 0; x < this.non_terminal.length; x++)
                count += (this.non_terminal_follow[x] || "").length;

            if (count > MAX)
                MAX = count;
            else
                break;
        }


        for (r = 0; r < this.non_terminal.length; r++) {
            this.analyse_table[r] = new Array();

            for (v = 0; v < TERMINAL.length; v++)
                this.analyse_table[r][v] = "";

            for (f = 0; f < Productions.length; f++) {
                var Split_r = Productions[f].split(" ");
                if (Split_r[0] != this.non_terminal[r])
                    continue;
                if (Split_r[1] == "@") {
                    var Split_t = this.non_terminal_follow[r].split(" ");
                    for (b = 1; b < Split_t.length; b++)
                        this.analyse_table[r][this.Get_ter_i(Split_t[b])] += f + 1;
                }
                else {
                    var Split_t = this.right_first[f].split(" ");
                    for (b = 1; b < Split_t.length; b++)
                        this.analyse_table[r][this.Get_ter_i(Split_t[b])] += f + 1;
                }

            }
        }
    }
  • 总控程序
    分析栈STACK: 放文法符号, 初始放一个#号, 再放入开始符号S。
    设栈顶为X,当前输入符号为a,则对于任何(X,a)执行以下三种动作之一:
  1. 若X = a =“ #” 则分析成功
  2. 若X = a ≠“ # ” 则把X从STACK栈中弹出,a指向下一输入符号
  3. 若X是非终结符, 则按M[X, a]中的产生式进行推导(弹出X, 将右部符号串反序入栈), 或进行出错处理。
   /**
    * 语法分析
    */
   this.Check = function () {
       var cnt = 0;

       //倒置
       this.terminal_array.reverse();

       while (this.terminal_array.length > 0) {
           if (this.ArrayX.top().str == this.terminal_array.top().str && this.ArrayX.top().str == "#") {
               return true;
           }
           else if ((this.ArrayX.top().str == this.terminal_array.top().str && this.ArrayX.top().str != "#")
               || (this.ArrayX.top().str == "relop" && this.Is_relop(this.terminal_array.top().str))) {
               cnt++;
               this.Analyse_Stack += "<tr><td>" + cnt + "</td><td>" + "..." + this.ArrayX.top().str
                   + "</td><td>" + this.terminal_array.top().str + "..." + "</td><td>REDUCED<td></tr>";

               //将TE_Array的lexical复制
               this.ArrayX.top().lexical = this.terminal_array.top().data;

               if (this.ArrayX.top().str == "relop") {
                   this.ArrayX.top().op = this.terminal_array.top().data;
               }

               this.ArrayX.pop();
               this.terminal_array.pop();
           }
           else if (!this.Is_terminal(this.ArrayX.top().str)) {
               if (this.analyse_table[this.Get_non_i(this.ArrayX.top().str)][this.Get_ter_i(this.terminal_array.top().str)] == "")
                   return false;
               else {
                   //从预测分析表中获取产生式ID
                   var Production_G_ID = this.analyse_table[this.Get_non_i(this.ArrayX.top().str)][this.Get_ter_i(this.terminal_array.top().str)] - 1;
                   var Split_r = (Productions[Production_G_ID] || "").split(" ");

                   if (Split_r[1] == "@") {
                       cnt++;
                       this.Analyse_Stack += "<tr><td>" + cnt + "</td><td>" + "..."
                           + this.ArrayX.top().str + "</td><td>" + this.terminal_array.top().str
                           + "..." + "</td><td>@</td></tr>";

                       this.ArrayX.pop();
                       continue;

                   }

                   //语法数生长
                   for (jj = 1; jj < Split_r.length; jj++) {
                       this.ArrayX.top().children.push(new Node(Split_r[jj], Split_r[jj], this.ArrayX.top()));
                   }

                   //弹出栈顶
                   var _top = this.ArrayX.pop();

                   //界面相关
                   cnt++;
                   this.Analyse_Stack += "<tr><td>" + cnt + "</td><td>" + "..."
                       + Split_r[0] + "</td><td>" + this.terminal_array.top().str + "..."
                       + "</td><td>" + Split_r[0] + "→";

                   //_top的孩子节点反序入栈
                   for (ii = 1; ii < Split_r.length; ii++) {
                       _top.children[Split_r.length - ii - 1].production_id = Production_G_ID;
                       _top.children[Split_r.length - ii - 1].child_id = Split_r.length - ii - 1;
                       this.ArrayX.push(_top.children[Split_r.length - ii - 1]);

                       this.Analyse_Stack += Split_r[ii] + "&nbsp;&nbsp;";
                   }

                   this.Analyse_Stack += "</td></tr>";
               }
           }
           else
               return false;
       }
       return false;
   }
}

END (代码等这系列完结后放github)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值