编译原理:词法分析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>
本文来自博客园,作者:{Zeker62},转载请注明原文链接:https://www.cnblogs.com/Zeker62/p/15380566.html