C/C++教程

自著——30天自制计算机语言解释器 第2天 A+B-C+D运算的准备 :得到词语的数组

本文主要是介绍自著——30天自制计算机语言解释器 第2天 A+B-C+D运算的准备 :得到词语的数组,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

自著——30天自制计算机语言解释器 第2天 A+B-C+D运算的准备 :得到词语的数组

根据第一天的开发,发现,程序解析时处理的最基础的单元
是词语(TOKEN),所以需要在做其它事情之前,先把整个表达式
拆分成多个词语,以方便之后的处理。

例如 1+2+3+4 处理成如下的数组
1 5 1 1 0 ----------
2 8 + 1 1 ----------
3 5 2 1 2 ----------
4 8 + 1 3 ----------
5 5 3 1 4 ----------
6 8 + 1 5 ----------
7 5 4 1 6 ----------
数组中的每个元素都是一个对象。有序号 类型 值 行号 行内起始位置 这五个属性组成。
例如如下:
id   type      value    linenumber   startIndex
1    keyword   int      1             10

第2.1版本的程序
需求 针对 1+2+3+4 这样的表达式,检查语法错误。 例如操作数与操作数相连
或者是操作符与操作符 相连即为出错。

实现
循环遍历 词语的数组,判断相邻的词语 的类型是否一样,一样即为出错,并报出出错的位置。

词语 分成了九种类型
1 字符串型, 5数字型, 6分隔符型 7 块分隔符 8.操作符,9 空格符
BNF的定义如下:

 <operand>  :==  + | - | * | / | = | < | > | % | ^  | &  | |  | !
<block>     :==  { | } | [ | ] | ( | )
<delimeter> :==  , | ; | : | ' | "  
<digit>     :== 0 | 1|2|3|4|5|6|7|8|9
<number>    :== <digit> | <digit> <number>|<digit> . <number>

a~Z  letter  keyword  ,identifier ,variable

get_token函数实现的思路

采用类似于超级玛利的策略。
以 上跳,下跳 ,平跑 来分隔 词语。

off on    上跳   得到token 首字符
off off   平跑   过滤空格与分隔符
on  on    平跑   得到token 其它字符
on  off   下跳   token 结束

html页面代码如下
<HTML>
<HEAD>
<TITLE> 30天自制解释器 2.1 </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<script src='get_token_general.js' ></script>
</HEAD>
<BODY>
<p>本版本只能计算 a+b ,a-b,a*b ,a/b ,且本版有多个操作符,解析 操作数与操作数
操作符与操作符相连的错误 </p>
<p>a和b 都是正整数,而且 a 与 +,b 与+ 之间都可以有空格 </p>
<textarea id='txt1' rows="20" cols="80"></textarea>
<input type='button' value='执行' οnclick='eval()'>第二天第一版</input>
<textarea id='txt2' rows="20" cols="80"></textarea>
<script>

function eval()
{
var str=document.getElementById("txt1").innerText;
var result=0;
var token_array=[];

   token_array=get_token_general({"lineno":1,"linelength":str.length,"str":str},token_array);
   result=parse_exp(token_array);
   
   if (temp.length>1)
       {
          if(temp[0]=='+')
           {
              result=addcalc(temp[1],temp[2]);}
           else if (temp[0]=='-')
              {result=subcalc(temp[2],temp[1]);}
           else if(temp[0]=='*')
           {
              result=mulcalc(temp[1],temp[2]);}
           else if (temp[0]=='/')
              {result=divcalc(temp[2],temp[1]);}
       }
   else
    {result=temp[0]+"  can't eval"}
   if (result==0)
      result="parse success";
document.getElementById("txt2").innerText=result;
}
function parse_exp(arr)
{
  var result=0;
  var pretype=null;
   for(var i=0;i<arr.length;i++)
   {
        if(pretype==null)
          {pretype=arr[i].type;}
        else if(pretype==arr[i].type)
          { result="error parse:at "+arr[i].startindex+" value: "+arr[i].value;}
        else {pretype=arr[i].type}
   }
   return result;
}

function addcalc(operator1,operator2)
{
  return  parseInt(operator1)+parseInt(operator2);
}
function subcalc(operator1,operator2)
{
  return  parseInt(operator1)-parseInt(operator2);
}
function mulcalc(operator1,operator2)
{
  return  parseInt(operator1)*parseInt(operator2);
}
function divcalc(operator1,operator2)
{
  var result =0;
     if (operator2!=0)
        { result=parseInt(operator1)/parseInt(operator2);
        }
      else
        { result='runtime error : div is 0.'}
  return  result;
}

</script>
</BODY>
</HTML>

get_token_general.js 的代码如下:
//var b=[];
// a="int a,b;char c;c=a&&b;";
function get_token_general(a,b)
{
    var str='';
    var preState=0;
    var curState=0;
    var pretype=0;
    var curtype=0;
    var temp='';
    var tempString='';
    
    var id=b.length;
    var startindex=0;

  for(var i=0;i<a.linelength;i++)
  {
   
      str=a.str.substr(i,1);
      curtype=getType(str);
      curState=getState(preState,pretype,curtype);
      temp=str;

      if (curState==0)             //(preState==0&&curState==0)   //  stop
      {
        
           id=id+1;

           b.push({"id":id,"type":curtype,"value":temp,"lineno":a.lineno,"startindex":i});
        
      }
      else if (curState==1)           //(preState==0&&curState==1)  //jump up
      {
         startindex=i;
         tempString=temp;
      }
      else if (curState==3)         //(preState==1&&curState==0)  //jump down
      {
        id=id+1;
       b.push({"id":id,"type":pretype,"value":tempString,"lineno":a.lineno,"startindex":startindex});
      
        
        
           id=id+1;

           b.push({"id":id,"type":curtype,"value":temp,"lineno":a.lineno,"startindex":i});
        
        tempString='';
      }
      else if (curState==8)
      {
               id=id+1;
       b.push({"id":id,"type":pretype,"value":tempString,"lineno":a.lineno,"startindex":startindex});
      

       tempString='';
      }
      else if (curState==2)              //(preState==1&&curState==1)  //run
      {
         tempString=tempString+temp;
      }
      else if (curState==4)
      {
       id=id+1;
       b.push({"id":id,"type":pretype,"value":tempString,"lineno":a.lineno,"startindex":startindex});
      

          startindex=i;
           tempString=temp;
      }

      pretype=curtype;
      preState=curState;

   }
   if(tempString!='')
   {
              id=id+1;
       b.push({"id":id,"type":pretype,"value":tempString,"lineno":a.lineno,"startindex":startindex});
       
   }
  return b;
}

function getType(str)
{
   var type=0;    
      if(isAlphabet(str)==1)
      {
      type=1;    
      }
      else if(isDigit(str)==1)
      {
      type=5;    
      }
      else if (isDelimiter(str)==1)
      {
       type=6;      
      }
      else if (isBlock(str)==1)
      {
        type=7;
      }
      else if (isOperand(str)==1)
      {
        type=8;
      }
      else if ( isSpace(str)==1)
      {
         type=9;    
      }
      return type;
}
function getState(preState,pretype,curtype)
{
    var curState=0;
      if(preState==0||preState==9||preState==3||preState==8)
      {
        if(curtype==5||curtype==1)
          {curState=1;}
        else if(curtype==6||curtype==7)
          { curState=0;}
         else if(curtype==9)
         {curState=9;}
      }
      else if(preState==1||preState==2)
      {
             if(curtype==5)
              {
                if(pretype!=8)
                    {curState=2;}
                 else
                    {curState=4;}
              }    
             else if (curtype==1)
              {
                if(pretype==1)
                {curState=2;}
                else if (pretype==8)
                {curState=4;}
                else
                {curState=2;}
              }
             else if(curtype==6||curtype==7)
               { curState=3;}
              else if(curtype==8)
              {curState=4;}
             else if(curtype==9)
              {curState=8;}
      }
      else if (preState==4)
      {      if(curtype<=5&&pretype<=5)
             {
                 curState=2;
             }
             else if(curtype==6||curtype==7)
               { curState=3;}
              else if(curtype==8&&pretype==8)
              {curState=2;}
             else if(curtype==9)
              {curState=8;}
             else
               {curState=4;}
      }
      else
      {
         curState=0;
      }
      return curState;
}

function isAlphabet(str)
{
   var result=0;
   if(str>='a' &&str<='z'||(str>='A'&&str<='Z'))
     {
       result=1;
     }
  return result;
}

function isDigit(str)
{
   var result=0;
   if(str>='0' &&str<='9'||(str=='.'))
     {
       result=1;
     }
  return result;
}

function isOperand(str)
{
 var result=0;
   if(str=='+')
   { result=1;}
      else if (str=='-')
   { result=1;}
    else if (str=='*')
   { result=1;}
    else if (str=='/')
   { result=1;}
   else if (str=='=')
   { result=1;}
    else if (str=='>')
   { result=1;}
   else if (str=='<')
   { result=1;}
   else if (str=='%')
    { result=1;}
    else if (str=='^')
   { result=1;}
    else if (str=='&')
   { result=1;}
   else if (str=='|')
   { result=1;}
   return result;     
}

function isDelimiter(str)
{
   var result=0;
   if(str==',')
   { result=1;}
   else if (str==';')
   { result=1;}
    else if (str==':')
   { result=1;}
 
   return result;
}

function isBlock(str)
{
 var result=0;
   if(str=='(')
   { result=1;}
      else if (str==')')
   { result=1;}
    else if (str=='{')
   { result=1;}
    else if (str=='}')
   { result=1;}
   else if (str=='[')
   { result=1;}
    else if (str==']')
   { result=1;}
   return result;
}


function isSpace(str)
{
 var result=0;
   if(str==' ')
   { result=1;}
   else if (str=='    ')
   { result=1;}

   return result;
}

这篇关于自著——30天自制计算机语言解释器 第2天 A+B-C+D运算的准备 :得到词语的数组的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!