自著——30天自制红孩儿解释器 第9天 解析简单的赋值语句

 自著——30天自制红孩儿解释器 第9天 解析简单的赋值语句

在第8天的基础上,到了对赋值语句的解析与执行的时候了。
下面举一个赋值语句的简单的例子。 做法是一贯的。
从最简单的出发,再逐渐地增加复杂度。

a=3; 是一个例子,最主要的特征是有一个等号,左边有一个变量名,
右边是一个数值 ,这个语句的含义很简单,把3这个数值赋给a 这个变量。
分号是语句的结束符。

上面是对赋值语句的直观的印象与含义解释。
下面给出一个 赋值语句的比较严格的BNF定义如下:
<assign statment>   :==   <variable name> = <expression> ; | <variable name> = <value> ;

第9天第一版本程序

需求 : aa=1; 这样的赋值语句的解析,生成 (= aa 1)这样的LISP风格的程序。
实现:
增加parse_variable
     parse_assign_statement


第9天第二版本程序
需求 :aa=1; 这样的赋值语句的执行,把变量a的值,记录到符号表中。
实现:增加一个执行按钮,在WEB页面上区别了解析与执行的过程。
       增加以下的函数:区别了解析与执行的过程。从程序上看,解析
       只进行语法的AST检查。执行过程涉及到符号表的操作。execute
       execute_assign_statement
       execute_variable

第9天第三版本程序
需求 :aa=1;bb=2;cc=3 这样的多个复合的赋值语句的执行,把变量a的值,记录到符号表中。
 实现:增加以下的一个函数,处理多个赋值语句。现在在分号结束符方面还有一个错误。
 在最后处目前最多只能有一个分号。如果有两个及两个的分号存在,则出错。
 execute_assign_compound_statement

主页面的代码如下:
<HTML>
<HEAD>
<TITLE> 30天自制解释器 9.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>
<script src='execute_lib.js' ></script>
</HEAD>
<BODY>
<p></p>
<p></p>
<p> aget_token_general=5;
b=a+1;
a
</p>
<p> </p>
<p>解析 赋值语句</p>
<p></p>
<textarea id='txt1' rows="20" cols="80"></textarea>
<input type='button' value='执行' οnclick='eval()'>第九天第一版</input>
<textarea id='txt2' rows="20" cols="80"></textarea>
<p>error show area:</p>
<textarea id='txt3' rows="20" cols="80"></textarea>
<script>
function eval()
{
var str=document.getElementById("txt1").innerText;
var result=0;
var token_array=[];
var result_str="";
  token_array=get_token_general({"lineno":1,"linelength":str.length,"str":str},token_array);

  // result=parse_sim_exp(token_array,0,0);
  //   result=parse_relation_exp(token_array,0,0);
     //   result=parse_logic_exp(token_array,0,0);
    result= parse_assign_statement(token_array,0,0);
    // result=test_symboltable_operation(token_array);
  // if (hasError(result.res)==0)
      // result=execute_exp(token_array);
    // result_str=sysmbol_table_arrtostring(result);
document.getElementById("txt2").innerText=result.res;//result_str;  //
}

function test_symboltable_operation(token_arr)
{
var symbol_table_arr=[];
   for (var i=0;i<token_arr.length;i++)
   {
       if (isVariable(token_arr[i])==1)
       {symbol_table_arr=symbol_table_do_variable(symbol_table_arr,token_arr[i].value,token_arr[i]);}
   }
   return symbol_table_arr;
}


function sysmbol_table_arrtostring(c)
{
  var tempstr="";
  var tempstr_sub="";
   for(var k=0;k<c.length;k++)
  {
     tempstr_sub="";
     for(var j=0;j<c[k].ref.length;j++)
        {tempstr_sub=tempstr_sub+' [l]: '+c[k].ref[j].lineno+' [p]:'+c[k].ref[j].position;}

  tempstr=tempstr+c[k].id+' '+c[k].type+' '+c[k].text+' '+c[k].value+' '+tempstr_sub+'----------';
  }
  return tempstr;
}

function symbol_table_do_variable(symbol_table_arr,variable_name,token_obj)
{
   var result=[];
   var lineno=token_obj.lineno;
   var position=token_obj.startindex;

    if (symbol_table_isexistvar(symbol_table_arr,variable_name)==1)
      {
          result=symbol_table_setvar_position(symbol_table_arr,variable_name,lineno,position);
      }
      else
        {
          if(token_obj.value.length>64)
           {  document.getElementById("txt3").innerText=" variable name:["+token_obj.value+"] is too long"+" at "+lineno+" ,position:"+position;
           }
           else {
              
              result=symbol_table_insertvar(symbol_table_arr,token_obj);
            }
        }
   return result;
}

function symbol_table_findvar(symbol_table_arr,variable_name)
{
    var result=-1;
 
    for (var i=0;i<symbol_table_arr.length ;i++ )
    {
        if (symbol_table_arr[i].text==variable_name)
        {
            result=i;
            break;
        }
    }
    return result;
}
function symbol_table_isexistvar(symbol_table_arr,variable_name)
{
    var result =symbol_table_findvar(symbol_table_arr,variable_name);
    if(result>=0)
      {result=1;}
      else
        {result=0;}
   return result;
}
function symbol_table_setvalue(symbol_table_arr,variable_name,value)
{
  var result=symbol_table_arr;
  var index =symbol_table_findvar(symbol_table_arr,variable_name);
  result[index].value=value;
  return result;
}
function symbol_table_setvar_position(symbol_table_arr,variable_name,lineno,position)
{
    var index =symbol_table_findvar(symbol_table_arr,variable_name);
    var result=symbol_table_arr;
    result[index].ref.push({"lineno":lineno,"position":position});

    return result;
}
function symbol_table_insertvar(symbol_table_arr,variable_obj)
{
  var result=symbol_table_arr;
    result.push({"id":symbol_table_arr.length,"type":"variable","value":"","text":variable_obj.value,"ref":[{"lineno":variable_obj.lineno,"position":variable_obj.startindex}],"level":0,"parentid":0});
  return result;
}
function sysbom_table_selectvar(symbol_table_arr,variable_name)
{
    var index =symbol_table_findvar(symbol_table_arr,variable_name);
    return symbol_table_arr[index].value;
}

function parse_assign_statement(arr,i,level)
{
      var operator1={};
   var operator2={};
   var result="";  

        operator1=  parse_variable(arr,i,level);
        if(hasError(operator1.res)>=0)
              {
                 return {"res":operator1.res,"i":i};
              }
              else {result =operator1.res;
              i=operator1.i;
              }

   if (  i<arr.length-2 &&(arr[i+1].value=='=') )
     {
        operator2= parse_sim_exp(arr,i+2,level);
         if( hasError(operator2.res)==-1)
           {
         result=make_lisp_program_action(arr[i+1].value,result,operator2.res);
       //result=execute_binary_relation_operator_action(arr[i+1].value,result,operator2.res);
           i=operator2.i;
           }
         else if(hasError(operator2.res)>=0)
              {result=operator2.res;
             //  break;
              }
            
     }
    return {"res":result,"i":i};
}

function parse_variable(arr,i,level)
{
  var result=0;
 // var resultObj={};

   if(isVariable(arr[i])==1)
     {result=arr[i].value;}   
     else
       {result='[error]: is not a vairable: at '+arr[i].startindex+" value: "+arr[i].value;}
    return {"res":result,"i":i};
}
function parse_logic_exp(arr,i,level)
{
   var operator1={};
   var operator2={};
   var result="";  

        operator1=  parse_relation_exp(arr,i,level);
        if(hasError(operator1.res)>=0)
              {
                 return {"res":operator1.res,"i":i};
              }
              else {result =operator1.res;
              i=operator1.i;
              }

   while(  i<arr.length-2 &&(arr[i+1].value=='&&'||arr[i+1].value=='||' || arr[i+1].value=='^^') )
     {
        operator2= parse_relation_exp(arr,i+2,level);
         if( hasError(operator2.res)==-1)
           {
         result=execute_binary_logic_operator_action(arr[i+1].value,result,operator2.res);
           i=operator2.i;
           }
         else if(hasError(operator2.res)>=0)
              {result=operator2.res;
               break;
              }
            
     }
    return {"res":result,"i":i};
}

function parse_relation_exp(arr,i,level)
{
       var operator1={};
   var operator2={};
   var result="";  

        operator1=  parse_sim_exp(arr,i,level);
        if(hasError(operator1.res)>=0)
              {
                 return {"res":operator1.res,"i":i};
              }
              else {result =operator1.res;
              i=operator1.i;
              }

   if (  i<arr.length-2 &&(arr[i+1].value=='>'||arr[i+1].value=='<'||arr[i+1].value=='>='||arr[i+1].value=='<='||arr[i+1].value=='=='||arr[i+1].value=='<>') )
     {
        operator2= parse_sim_exp(arr,i+2,level);
         if( hasError(operator2.res)==-1)
           {
         result=execute_binary_relation_operator_action(arr[i+1].value,result,operator2.res);
           i=operator2.i;
           }
         else if(hasError(operator2.res)>=0)
              {result=operator2.res;
             //  break;
              }
            
     }
    return {"res":result,"i":i};
}

function parse_sim_exp(arr,i,level)
{
   var operator1={};
   var operator2={};
   var result="";  

        operator1=  parse_term(arr,i,level);
        if(hasError(operator1.res)>=0)
              {
                 return {"res":operator1.res,"i":i};
              }
              else {result =operator1.res;
              i=operator1.i;
              }

   while(  i<arr.length-2 &&(arr[i+1].value=='+'||arr[i+1].value=='-') )
     {
        operator2= parse_term(arr,i+2,level);
         if( hasError(operator2.res)==-1)
           {
         result=execute_binary_calc_operator_action(arr[i+1].value,result,operator2.res);
           i=operator2.i;
           }
         else if(hasError(operator2.res)>=0)
              {result=operator2.res;
               break;
              }
            
     }
    return {"res":result,"i":i};
}

function parse_term(arr,i,level)
{
   var operator1=0;
   var operator2=0;
   var result="";
        operator1=  parse_factor(arr,i,level);
        if(hasError(operator1.res)>=0)
              {
               return {"res":operator1.res,"i":i};
              }
              else {result =operator1.res;
               i=operator1.i;}

   while( i<arr.length-2 &&(arr[i+1].value=='*'||arr[i+1].value=='/')  )
     {
        operator2= parse_factor(arr,i+2,level);

         if( hasError(operator2.res)==-1)
           {
           result=execute_binary_calc_operator_action(arr[i+1].value,result,operator2.res);
            i=operator2.i;
           }
         else if(hasError(operator2.res)>=0)
              {result=operator2.res;
               break;
              }

     }

    return {"res":result,"i":i};
}

function parse_factor(arr,i,level)
{
  var result=0;
  var resultObj={};

   if(arr[i].type==5)
     {result=arr[i].value;}
    else if (arr[i].type==7)
      {
         if (arr[i].value=='(')
         {
                 resultObj=parse_sim_exp(arr,i+1,level+1);
                 result=resultObj.res;
                 i=resultObj.i;
         }

          if (i<arr.length-1&& arr[i+1].value==')')
          {
                 i=i+1;
          }
          else if (i==arr.length-1 && arr[i]!=')')
              {
                   result='[error]: should be  ) : at '+arr[i].startindex+" but value: "+arr[i].value;
              }
          else
          {
              result='[error]: should be  ) : at '+arr[i].startindex+" but value: "+arr[i].value;
          }
      }
     else
       {result='[error]: is not number: at '+arr[i].startindex+" value: "+arr[i].value;}
    return {"res":result,"i":i};
}

function hasError(str)
{
 if(isNum(str)==1)
    return -1;
  else
  return str.indexOf("error");
}

function make_lisp_program_action(operand,operator1,operator2)
{
   return "("+ operand + " "+operator1+" "+operator2+")";
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王伟1982

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值