使用html+css+javascript实现词法分析器
其中:
识别保留字:if、int、for、while、do、return、break、continue;
单词种别码为1。
其他的都识别为标识符;单词种别码为2。
常数为无符号整形数;单词种别码为3。
运算符包括:+、-、*、/、=、>、<、>=、<=、!= ;
单词种别码为4。
分隔符包括:,、;、{、}、(、); 单词种别码为5。
一些碎碎念:
为什么用html来实现呢?因为我认为html的可迁移性极强,而且窗口较易设计(虽然我没有在窗口设计上很花心思,但不可否认他确实有这个优点!),不管是在什么操作系统或者电脑上,甚至使用手机,平板等移动设备,都能直接运行并使用该“词法分析器”,不需要再额外配置环境。
好啦,话不多说,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>词法分析</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
function $(id){return document.getElementById(id);}
function decode(){
var ele = "else";
var inValue = $("inputValue").value.trim();
var arr = inValue.split("\n");
$("outputValue").value = "";
for(var i=0;i<arr.length;i++){
var j=0;
var a = Array();
var flag=0;
arr[i]=arr[i].trim();
while(arr[i][j]!=undefined){
while(arr[i][j]==" "){ //跳过为空格的情况
j++;
}
if(arr[i][j-1]==" "){
if(a.length==1){ //如果数组a只有1个字符,输出该字符
var str=a[0];
}else{ //a有>=2个字符,输出数组
var str=a.join("");
}
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}
if(a.length==0 && j!=arr[i].length-1){
a.push(arr[i][j]); //加入第一个字符
if(checkLetter(a[0])){ //如果是字母,falg=1
flag=1;
}else if(checkNumber(a[0])){ //如果是数字,falg=2
flag=2;
}else{ //其他,即特殊字符,flag=3;
flag=3;
var str=a[0];
if(setKey(str)==5){
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
a.splice(0,a.length);
}
}
j++;
}else if(a.length==0 && j==arr[i].length-1){ //如果只剩下最后一个字符的情况
var str=arr[i][j];
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
j++;
}else{
if(j!=arr[i].length-1){
switch(flag){
case 1: //判断为字母的情况,继续遍历数组查看后续是否能够成一个单词
if(checkLetter(arr[i][j])){ //如果是字母,则加入到a数组中,加入后继续遍历
a.push(arr[i][j]);
j++;
}else{ //如果不是字母,则表示上一个单词已经结束,则输出a数组存储的单词,并将该非字母字符重新遍历判断
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}
break;
case 2: //判断为数字的情况,继续遍历数组查看后续是否能够成一个数字集
if(checkNumber(arr[i][j])){ //如果是数字,则加入到a数组中,加入后继续遍历
a.push(arr[i][j]);
j++;
}else{ //如果不是数字,则表示上一个单词已经结束,则输出a数组存储的单词,并将该非字母字符重新遍历判断
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}
break;
case 3: //判断为数字的情况,继续遍历数组查看后续是否能够成一个数字集
if(checkNumber(arr[i][j]) || checkLetter(arr[i][j])){ //如果是数字或字母,即不是特殊字符,则表示上一个单词已经结束,则输出a数组存储的单词,并将该非字母字符重新遍历判断
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}else{ //如果是特殊字符,则加入到a数组中,加入后继续遍历
a.push(arr[i][j]);
j++;
}
break;
}
}else if(j==arr[i].length-1){ //如果遍历到最后一位字符
switch(flag){
case 1:
if(checkLetter(arr[i][j])){ //判断为是字母时,a加入最后一个字符并直接输出a数组所存储的完整单词
a.push(arr[i][j]);
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}else{ //若不是字母,则输出a存储的单词,并直接输出最后一个字符
if(a.length==1){ //如果数组a只有1个字符,输出该字符
var str=a[0];
}else{ //a有>=2个字符,输出数组
var str=a.join("");
}
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
var str1=arr[i][j];
$("outputValue").value += ("("+setKey(str1)+",\""+str1+"\")"+"\n");
break;
}
break;
case 2:
if(checkNumber(arr[i][j])){ //判断为是数字时,a加入最后一个字符并直接输出a数组所存储的完整单词
a.push(arr[i][j]);
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}else{ //若不是数字,则输出a存储的数字集,并直接输出最后一个字符
if(a.length==1){ //如果数组a只有1个字符,输出该字符
var str=a[0];
}else{ //a有>=2个字符,输出数组
var str=a.join("");
}
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
var str1=arr[i][j];
$("outputValue").value += ("("+setKey(str1)+",\""+str1+"\")"+"\n");
break;
}
break;
case 3:
if(checkNumber(arr[i][j]) || checkLetter(arr[i][j])){ //判断为是数字时,a加入最后一个字符并直接输出a数组所存储的完整单词
if(a.length==1){ //如果数组a只有1个字符,输出该字符
var str=a[0];
}else{ //a有>=2个字符,输出数组
var str=a.join("");
}
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
var str1=arr[i][j];
$("outputValue").value += ("("+setKey(str1)+",\""+str1+"\")"+"\n");
break;
}else{ //若不是数字,则输出a存储的数字集,并直接输出最后一个字符
a.push(arr[i][j]);
var str=a.join("");
a.splice(0,a.length); //清空a数组
$("outputValue").value += ("("+setKey(str)+",\""+str+"\")"+"\n");
}
break;
}
j++;
}
}
}
}
}
function setKey(ele){
if(parseFloat(ele)%1==0){ //如果是整数,种别码识别为3
return 3;
}else if(ele=="if"||ele=="int"||ele=="for"||ele=="while"||ele=="do"||ele=="return"||ele=="break"||ele=="continue"){
return 1;
}else if(ele=="+"||ele=="-"||ele=="*"||ele=="/"||ele=="="||ele==">"||ele=="<"||ele==">="||ele=="<="||ele=="!="){
return 4;
}else if(ele==','||ele==';'||ele=='{'||ele=='}'||ele=='('||ele==')'){
return 5;
}else{
return 2; //其他的都识别为标识符;单词种别码为2。
}
}
function checkNumber(value) { //判断是否为数字
var reg = /^[0-9]*$/;
if (reg.test(value)) {
return true;
}else{
return false;
}
}
function checkLetter(value) { //判断是否为字母
var Regx = /^[A-Za-z]*$/;
if (Regx.test(value)) {
return true;
}
else {
return false;
}
}
</script>
<style>
#header{width:100%;height:50px;}
#left{width:30%;height:500px;border:solid;float:left;}
#center{width:5%;height:500px;border:solid;float:left;}
#right{width:30%;height:500px;float:left;border:solid;}
#footer{clear:both;width:100%;height:50px;}
</style>
</head>
<body>
<div id="header">
<h1>词法分析程序</h1>
</div>
<div>
<form method="post" action="">
<div id="left" class="">
<textarea cols="46" rows="30" wrap="physical" id="inputValue"></textarea>
</div>
<div id="center"></div>
<div id="right" class="">
<textarea cols="46" rows="30" id="outputValue" readonly></textarea>
</div>
<div id="footer">
<input type="button" value="解析程序" onClick="decode()"/>
<input type="reset" value="重置"/>
</div>
</form>
</div>
</body>
</html>
运行结果: