ホームページ >バックエンド開発 >PHPチュートリアル >コンパイル原理に興味のある方

コンパイル原理に興味のある方

WBOY
WBOYオリジナル
2016-06-13 13:12:41825ブラウズ

コンパイル原理に興味のある方へ
最近文法解析をやってみたのですが、問題がたくさんあります。
提案してください。コードが入りきらなかったので2ページに分けました。ダウンロードアドレス http://download.csdn.net/detail/xuzuning/4529066

PHP コード
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->「ttrie.php」をインクルードします。

class Rule extends TTrie {
  パブリック $rule = array();
  パブリック $savematch = 0;

  関数 __construct($s='') {
    $this->set( array(
        ' ' => 「別居」、
        "rn" => 'セットルール',
        "n" => 'セットルール',
        "t" => 「別居」、
        「->」 => 「別居」、
        '→' => 「別居」、
        '|' => 'set_Parallel_rule',
        ));
    $this->match($s);
    if($this->rule[0][0] == $this->rule[0][1]) {
        if(count($this->rule[0]) == 2) $this->rule[0][0] .= "'";
        else array_unshift($this->rule, array($this->rule[0][0]."'", $this->rule[0][0]));
    }それ以外 {
        $c = $this->ルール[0][0];
        $n = 0;
        foreach($this->rule as $r) if($r[0] == $c) $n++;
        if($n > 1) array_unshift($this->rule, array($this->rule[0][0]."'", $this->rule[0][0])) ;
    }
  }
  関数 Separated() {
  }
  関数 set_rule() {
    $this->rule[] = $this->buffer;
    $this->buffer = array();
  }
  関数 set_Parallel_rule() {
    $t = $this->buffer[0];
    $this->set_rule();
    $this->buffer[] = $t;
  }
}


クラス文法 {
  var $closure = array();
  var $first = array();
  var $follow = array();
  var $rule = array();
  var $identifier = array();
  var $leay = array();
  var $forecast = array();
  var $stack = array();
  var $ll = 'LL(0)';
  var $lr = 'LR(0)';

  関数 __construct($s='') {
    $p = 新しいルール($s);
    $this->rule = $p->rule;
    $this->set_grammar();
  }

  関数 set_grammar() {
    foreach($this->rule as $rule) {
        if(! in_array($rule[0], $this->identifier)) $this->identifier[] = $rule[0];
    }
    foreach($this->rule as $rule) {
        foreach($rule as $v)
            if(! in_array($v, $this->identifier) && ! in_array($v, $this->leay))
                $this->leay[] = $v;
    }
    $this->set_first();
    $this->set_follow();
    $this->set_closure();
    $this->set_select();
    $this->set_forecast();
  }
  関数 set_first() {
    foreach($this->rule as $rule) $this->first[$rule[0]] = array();
    // 形のような U->a… の生成式 (その中 a は终结符) を直接取得し、a を First(U) に挿入します
    foreach($this->rule as $v) {
        if(in_array($v[1], $this->leay)) $this->first[$v[0]][] = $v[1];
    }
    // 逆転送形式入力 U->P1P2P3…Pn の生成式 (P は终结符),应先制 First(P1) 内のすべての内容が First(U) 中へ転送され、結果 P1 中にεがある場合、 First(P2) 内の内容は First(U) に送信され、Pi に到達するまでは転送されません
    する {
        $t = シリアル化($this->first);
        foreach($this->rule as $rule) {
            for($i=1; $i<count if>identifier)) {
                    $this->first[$rule[0]] = array_unique(array_merge($this->first[$rule[0]], $this->first[$v]));
                    if(! in_array('#', $this->first[$v])) ブレーク;
                }それ以外の場合は中断します。
            }
        }
    }while($t != Serialize($this->first));
  }
  関数 set_follow() {
    foreach($this->rule as $rule) $this->follow[$rule[0]] = array();
    // 形如 …Ua… 的、掴a 直接Follow(U)中に直接收入
    foreach($this->rule as $rule) {
        for($i=1; $i<count if>identifier) && in_array($rule[$i+1], $this->leay))
                $this->follow[$rule[$i]][] = $rule[$i+1];
        }
        if(in_array($rule[$i], $this->identifier)) $this->follow[$rule[$i]][] = '#';
    }
    foreach($this->follow as &$v) if(! $v) $v[] = '#';
    // 直接收取形例 …UP…(P是终结符)的,最初(P)中非ε收入toFollow(U)中
    foreach($this->rule as $rule) {
        for($i=1; $i<count if>identifier) && in_array($rule[$i+1], $this->identifier)) {
                $this->follow[$rule[$i]] = array_unique(array_merge($this->follow[$rule[$i]], array_diff($this->first[$rule[$i+1] ]]、 配列('#'))));
            }
        }
    }//逆転送形式の場合、U->aPの(Pは终结符)またはU->aPQ(P,Qは非终结符でQ中に含まれます)、应ハンドルFollow(U)中の全コンテンツ転送フォロー(P)中
    する {
        $t = シリアル化($this->follow);
        foreach($this->rule as $rule) {
            $s = $rule[0];
            $d = 終了($rule);
            if(in_array($d, $this->leay)) 続行;
            $p = 前($rule);
            if(in_array($p, $this->leay)) $this->follow[$d] = array_unique(array_merge($this->follow[$d], $this->follow[$s] ]));
            elseif(in_array('#', $this->follow[$d])) $this->follow[$p] = array_unique(array_merge($this->follow[$p], $this-> ;フォロー[$s]));
        }
    }while($t != Serialize($this->follow));
  }
  関数 set_closure() {
    $shift = 配列();
    $this->closure[0][] = array('offs' => 1, 'rule' => 0);
    for($i=0 ; $i <count>closure); $i++) {
        $cnt = count($this->closure);
        //建設闭包クロージャー
        $ex = 配列();
        $j = 0;
        $tmp = 配列();
        する {
            $size = count($this->closure[$i]);
            for($j=0; $j<count>closure[$i]); $j++) {
                $dfa = $this->クロージャ[$i][$j];
                $rule = $this->rule[$dfa['rule']];
                if(isset($rule[$dfa['offs']])) {
                    $ch = $ex[] = $rule[$dfa['offs']];
                }
                foreach($this->rule as $r=>$rule) {
                    if(in_array($rule[0], $ex)) {
                        $t = array('offs' => 1, 'rule' => $r);
                        if(!isset($tmp[$r][1])) $this->closure[$i][] = $t;
                        $tmp[$r][1] = 1;
                    }
                }
            }
        }while(count($this->closure[$i]) != $size); //まで不再增大

        // 判断状態态转向に行く
        $out = 配列();
        foreach($this->closure[$i] as $k=>$dfa) {
            $rule = $this->rule[$dfa['rule']];
            if(isset($rule[$dfa['offs']])) {
                $t = "$dfa[ルール],$dfa[オフ]";
                $ch = $rule[$dfa['offs']];
                $this->closure[$i][$k]['char'] = $ch;
                if(isset($out[$ch])) $shift[$t] = $out[$ch];
                if(isset($shift[$t])) {
                    $this->closure[$i][$k]['target'] = $shift[$t];
                    $dfa['offs']++;
                    if(!$this->in_closure($dfa, $this->closure[$shift[$t]])) $this->closure[$shift[$t]][] = $dfa;

                } それ以外 {
                    $cnt = count($this->closure);
                    $this->closure[$i][$k]['ターゲット'] = $cnt;
                    $shift[$t] = $cnt;
                    $dfa['offs']++;
                    $this->closure[count($this->closure)][] = $dfa;
                    $out[$ch] = $cnt;
                }
            }
        }

        //造造状態态转换表
        foreach($this->closure[$i] as $k=>$dfa) {
            if(isset($dfa['target'])) {
                $v = $dfa['char'];
                if(in_array($v, $this->identifier)) $this->goto[$i][$v] = $dfa['target'];
                それ以外 {
                    $this->action[$i][$v][] = "S$dfa[ターゲット]";
                    $this->request[$i][$v] = $dfa['rule'];
                }
            } それ以外 {
                $ch = $this->rule[$dfa['rule']][0];
                foreach($this->follow[$ch] as $v) {
                    $this->action[$i][$v][] = "r$dfa[ルール]";
                    $this->request[$i][$v] = $dfa['rule'];
                }
            }
        }
        foreach($this->action[$i] as $c=>$v) {
            $v = 配列固有($v);
            if(count($v) > 1) $this->lr = 'SLR(1)';
            $this->アクション[$i][$c] = $v;
        }
    }
  }

  関数 in_closure($t, $s) {
    foreach($s as $r) if($t['offs'] == $r['offs'] && $t['rule'] == $r['rule']) return true;
    false を返します。
    return in_array(serialize($t), array_map('serialize', $s));
  }
  関数 set_select() {
    foreach($this->rule as $i=>$rule) {
        $y = 配列($rule[1]);
        if(in_array($y[0], $this->leay)) {
            if($y[0] != '#') {
                $this->select[$i] = $y;
                続く;
            }
        }else $y = $this->first[$rule[1]];
        $x = $this->follow[$rule[0]];
        //SELECT(X->Y)=(FIRST(Y)-{ε})并FOLLOW(X)
        $this->select[$i] = array_unique( array_merge(array_diff($y, array('#')), $x) );
    }
  }/**※予測分析テーブルの構築
   **/
  関数 set_forecast() {
    foreach($this->select as $i=>$r) {
        $c = $this->ルール[$i][0];
        $v = array_reverse(array_slice($this->rule[$i], 1));
        foreach($r として $k) {
            $this->forecast[$c][$k][] = $v;
        }
    }
    //检查冲突
    foreach($this->forecast as $c=>$r) {
        foreach($r として $k) {
            if(count($k) > 1) {
                $this->ll = 'LL(1)';
            }
        }
    }
  }

 <div class="clear"></div></count></count></count></count></count>
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。