编译原理:词法分析PHP代码实现

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=drive-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="login.css">
    <style>
        body {
            background: url('backiee-210221.jpg');
            background-repeat: no-repeat;
            background-size: 100% auto;
        }
        
        #code {
            width: 30%;
            height: auto;
            margin: 0 auto;
            margin-top: 15%;
            text-align: center;
            background: #00000060;
            padding: 20px 50px;
        }
        
        #code h1 {
            color: #fff;
        }
        
        #code .form .item input {
            margin-top: 25px;
        }
        
        #code .form i {
            font-size: 18px;
            color: rgb(180, 155, 155);
        }
        
        #code .form .item input {
            width: 180px;
            font-size: 20px;
            border: 0;
            border-bottom: 2px solid#fff;
            padding: 5px 10px;
            background: #ffffff00;
            color: #fff;
        }
        
        .b {
            width: 300px;
            height: 200px;
            font-size: 20px;
            font-weight: 200;
            background: hsla(0, 0%, 100%, 0);
            color: aliceblue;
        }
    </style>
    <title>卷起来</title>
</head>

<body>
    <div id="code">
        <form method="post" action="WordAnalysis.php">
            <h1>词法分析测试界面</h1>
            <div class="form">
                <div class="item">
                    <i class="fa fa-user-circle-o" aria-hidden="true"></i>
                    <textarea class=b name="code" value=""></textarea>
                </div>
            </div>
            <input type="reset" value="重置">
            <input type="submit" value="提交" name=submit>

        </form>
    </div>
</body>

</html>

后端

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=drive-width,initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="login.css">
    <style>
        body {
            background: url('backiee-210221.jpg');
            background-repeat: no-repeat;
            background-size: 100% auto;
        }
        
        #code {
            width: 30%;
            height: 80%;
            margin: 0 auto;
            margin-top: auto;
            text-align: center;
            background: #00000060;
            padding: 20px 50px;
        }
        
        #code h2 {
            color:antiquewhite;
        }
        #code h3{
            color:aliceblue;
        }
        #code{
            color:aqua;
        }
        
        #code .form .item input {
            margin-top: 25px;
        }
        
        #code .form i {
            font-size: 18px;
            color: rgb(180, 155, 155);
        }
        
        #code .form .item input {
            width: 180px;
            font-size: 20px;
            border: 0;
            border-bottom: 2px solid#fff;
            padding: 5px 10px;
            background: #ffffff00;
            color: #fff;
        }
        
        .b {
            width: 300px;
            height: 200px;
            font-size: 20px;
            font-weight: 200;
            background: hsla(0, 0%, 100%, 0);
            color: aliceblue;
        }
        #codes{
            text-align: left;
            color: yellow;
        }
    </style>
    <title>卷起来</title>
</head>

<body>
    <div id="code">
<?php
echo "<meta charset='utf-8'>";
//////////////////////////////////////////////////
///////////////////////////
// 读取网页上输入的代码,将文件保存在code.txt当中
$code = $_POST['code'];
$file = fopen('code.txt', 'w') or die('Unable to open file: ' . $file);
fwrite($file, $code);
fclose($file);
// 将code.txt 当中的字符全部逐个存入数组,并过滤空格
$path = 'code.txt';
$handle = fopen($path, 'r');
$char_array = array();
$char_array_display = array();
$i = 0;
while (FALSE !== ($chars = fgetc($handle))) {
    // 将字符存入数组
    $char_array[$i] = $chars;
    $i++;
}
$i = 0;
while (FALSE !== ($chars = fgets($handle))) {
    // 将字符存入数组
    $char_array_display[$i] = $chars;
    $i++;
}

fclose($handle);
//过滤空格
echo "<br>";
//使用正则表达式过滤
$char_array = preg_grep('/\S+/', $char_array);

//数据展示函数
$char_array = array_merge($char_array);
//var_dump($char_array);
function display_array($array)
{
    for ($i = 0; $i < count($array); $i++) {
        echo $array[$i];
    }
}
//display_array($char_array);
//foriinrange(n):inta;forjinrange(m):
//var_dump($char_array);
////////////////////////////////////////////////////////////////////
//////////////////////////////////////
// 判断一目运算符函数,传入字符即可判断
// 运算符: 如:+、-、*、/、:=、=、>、<、>=、<=
// 界符:   如:‘,’、‘.’ 、‘;’ 、‘(’ 、‘)’、‘{’、‘}’,‘:’
function YunSuanFu_Single($char)
{
    if ($char == '+' || $char == '-' || $char == '*' || $char == '/'  ||
     $char == '%' || $char == '=' || $char == '>' || $char == '<' ||
      $char == '!' || $char == '&' || $char == '|') {
        echo "<运算符,$char><br>";
        return 1;
    }
    if ($char == ',' || $char == '.' || $char == ';' || $char == ':') {
        echo "<界符,$char><br>";
        return 1;
    }
    return 0;
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////
// 判断二元定界符函数,需要传入当前数组以及数组指针的位置
// 函数的返回值就是最后输出主函数需要跳跃的值
function YunSuanFu_Double($char_array, $i)
{
    // 判断()
    if ($char_array[$i] == '(') {
        for ($j = $i; $j < count($char_array); $j++) {
            //循环后面的数组
            if ($char_array[$j] == ')') {
                echo "<界符,()><br> ";
                return 1;
            }
        }
    }
    // 判断{}
    if ($char_array[$i] == '{') {
        for ($j = $i; $j < count($char_array); $j++) {
            //循环后面的数组
            if ($char_array[$j] == '}') {
                echo "<界符,{}><br> ";
                return 1;
            }
        }
    }
    // 判断[]
    if ($char_array[$i] == '[') {
        for ($j = $i; $j < count($char_array); $j++) {
            //循环后面的数组
            if ($char_array[$j] == ']') {
                echo "<界符,[]><br> ";
                return 1;
            }
        }
    }
    // 判断赋值符号
    if ($char_array[$i] == ':' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '=') {
            echo "<运算符,:=><br>";
            return 2;
        }
    }
    // 判断双等号
    if ($char_array[$i] == '=' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '=') {
            echo "<运算符,==><br>";
            return 2;
        }
    }
    // 判断不等号
    if ($char_array[$i] == '!' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '=') {
            echo "<运算符,!=><br>";
            return 2;
        }
    }
    //判断 >=
    if ($char_array[$i] == '<' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '=') {
            echo "<运算符,<=><br>";
            return 2;
        }
    }
    // 判断<=
    if ($char_array[$i] == '>' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '=') {
            echo "<运算符,>=><br>";
            return 2;
        }
    }
    // 判断符号&&
    if ($char_array[$i] == '&' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '&') {
            echo "<运算符,&&><br>";
            return 2;
        }
    }
    //判断符号||
    if ($char_array[$i] == '|' && $i + 1 < count($char_array)) {
        if ($char_array[$i + 1] == '|') {
            echo "<运算符,||><br>";
            return 2;
        }
    }
    return 0;
}
//////////////////////////////////////////////////////////////
////////////////////////////////////////////
// 判断关键字
// 判断关键字需要使用到有穷自动机
// 从最长的关键字开始匹配,直到匹配成功到最短的关键字
// 关键字存档文件:keyword.txt
// 可以知道最长的关键字也就只有八个
function Guanjianzi($char_array, $i)
{
    //将关键字存储到数组当中去
    $code_path = 'keyword.txt';
    $GuanJianZi_Array  = file($code_path, FILE_IGNORE_NEW_LINES);
    // 截取需要的字符串
    $len = count($char_array) - $i+1; //这里有可能出错。。
    if ($len >= 8) {
        $len = 8;
        //最长的关键字也就只有八个长度
    }
    $num = $len; // 赋值给计数变量
    while ($num > 0) {
        $sliced_array = array_slice($char_array, $i, $num);
        //包括i在内的num个数组
        $key_str = implode($sliced_array);
        for ($j = 0; $j < count($GuanJianZi_Array); $j++) {
            if ($key_str == $GuanJianZi_Array[$j]) {
                echo "<关键字," . $key_str . "><br>";

                return $num; //需要返回长度值,然后再主函数里面进行跳跃
            }
        }
        $num--;
    }
    return 0;
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////
// 判断数字
function isNumber($char_array, $i)
{
    if (is_numeric($char_array[$i])) {
        $len = count($char_array) - $i;
        $num = $len;
        while ($num > 0) {
            //直接把后面的数组来切割进行判断
            $sliced_array = array_slice($char_array, $i, $num);
            $num_str = implode($sliced_array);
            if (is_numeric($num_str)) {
                echo "<数字," . $num_str . "><br>";
                return $num;
            }
            $num--;
        }
    } else
        return 0;
}
//////////////////////////////////////////////////////////////////
////////////////////////////////////////
function GuanJianZi_All()
{
    //从文件种读取关键字到数组中去
    $code_path = 'keyword.txt';
    $GuanJianZi_Array  = file($code_path, FILE_IGNORE_NEW_LINES);
    //var_dump($GuanJianZi_Array);

    // 以空格分界的关键字读入数组
    $char_path = 'code.txt';
    $code_string = file_get_contents($char_path);
    //$char_key=fopen($char_path,'r');
    $char_key_array = preg_split('/[\s,]+/', $code_string);
    //var_dump($char_key_array);
    //开始比较
    $key_array = array();
    for ($i = 0; $i < count($char_key_array); $i++) {
        for ($j = 0; $j < count($GuanJianZi_Array); $j++) {
            if ($char_key_array[$i] == $GuanJianZi_Array[$j]) {
                array_push($key_array, $char_key_array[$i]);
            }
        }
    }
    return $key_array;
}
$key_array = GuanJianZi_All();
//var_dump($key_array);

function JieFu(){
    $char_path = 'boder.txt';
    $code_string = file_get_contents($char_path);
    //$char_key=fopen($char_path,'r');
    $boder_array = preg_split('/[\s,]+/', $code_string);
    return $boder_array;
}
$boder_array=JieFu();
//var_dump($boder_array);
// 判断标识符
function isName($char_array, $i, $key_array,$boder_array)
{
    // 首先判断不以数字或者下划线打头
    if ($char_array[$i] == "_" || preg_match('/[a-zA-Z]/',$char_array[$i])) {
        for ($j = $i; $j < count($char_array); $j++) {
            // 从i号开始,往上递增
            if(in_array($char_array[$j],$boder_array) 
            && strlen($char_array[$j]) > 0) {
                $sliced_array_one = array_slice($char_array, $i, $j-$i);
                $key_str = implode($sliced_array_one);
                echo "<标识符,".$key_str."><br>";
                return $j-$i;
                    
            }
            $num = 2;
            //从第2个字符开始寻找是否是关键字
            while ($num < count($char_array) - $j) {
                $sliced_array = array_slice($char_array, $j, $num);
                $key_str = implode($sliced_array);

                // 如果是关键字的话
                if (in_array($key_str, $key_array) && strlen($key_str) > 0) {
                    $sliced_array = array_slice($char_array, $i, $num-1);
                    $key_str = implode($sliced_array);
                    echo "<标识符," . $key_str . "><br>";
                    return $num-1;
                }
                
                $num++;
            }
            
        }
    }
    return 0;
}

////////////////////////////////////////////////////////
//////////////////////////////////////////////////



// 主函数
echo "<h2>词法分析程序</h2>";
echo "<h3>源代码</h3>";
$code_path = 'code.txt';
echo "<div id=codes>";
$Code_Array  = file($code_path);
for($i=0; $i<count($Code_Array); $i++){
    echo $Code_Array[$i]."<br>";
}
echo "</div><br>";
echo "<h3>词法分析</h3>";
$m = 0;
while ($m <= count($char_array)) {
   
    $count == 0;
    $diff = count($char_array) - $m;
    $sum = 0;
    //echo count($char_array);
    // 先判断是不是双目运算符,再判断是不是单目运算符
    $sum = YunSuanFu_Double($char_array, $m);
    //echo "<br>$sum"."  "."$m<br>";
    $m += $sum;


    $sum = YunSuanFu_Single($char_array[$m]);
    $m += $sum;
    
    //判断是不是关键字
    $sum = GuanJianZi($char_array, $m);
    $m += $sum;
    // 判断是不是标识符
    $sum = isName($char_array, $m,$key_array,$boder_array);
    $m += $sum;
    
    $sum = isNumber($char_array, $m);
    $m += $sum;
    //echo "<br>$sum"."  "."$m<br>";
    //判断数组长度和m的差值,即到某个字符时,所有的函数都不匹配的时候
    if ($diff == count($char_array) - $m) {
        $m += 1; //指针就向后移动一位
    }
}
?>

    </div>
    </body>

    </html>

posted @ 2021-10-08 16:42  Zeker62  阅读(82)  评论(0编辑  收藏  举报