コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

スクリプトの解釈

毎日、少しずつOsoScriptを作っています。今日はバグを1つ見つけまして取っていました。後、ColdFireの回路も少しずつ作製中です。

電源回りを実装しました。今日はスクリプトの解釈のところを簡単に書きます。

スクリプトの解釈

OsoScriptは関数型の言語なので、構文はすべて計算式または関数のみで表されます。そこで、スクリプトの解釈は、ほぼ計算式を解釈しているだけです。例えば、下記のようなスクリプトがあった場合、

b = ( b * b + s )/( b + b );
if( y-b<0.0001 ){
break;
}

プログラム内部の構文解釈部では、下記が呼ばれるだけです。p_expression()からp_factor()まで呼び出しが続き、一行分の「b = ( b * b + s )/( b + b );」の処理が終わるまで、事あるごとに、延々とp_expression()の再起呼び出しが続きます。1スクリプト処理が終わると、すべての再起呼び出しから抜けて戻ってきているはずです。下記に簡単すぎますが、イメージがわけばということで、ソースを書きました。

//構文解析開始
value = p_expression();

p_expression()は、compare_Term()を呼びます。

//**********************************************
//式解析ルーチンのスタート
//**********************************************
float	p_expression( void )
{
float	value;
  value = compare_Term();
  //ここ以降で、エラー処理や構文末';'の初期化などを行う。
  //まだ、手付かずです。
  if( ErrorFlag!=0 )	return( value );
  return( value );
}

compare_Term()は、sumdiff_Term()を呼びます。

//**********************************************
//比較評価する項を解く関数
//**********************************************
float	compare_Term( void )
{
float	value;
  value = sumdiff_Term();
  while( 1 ){
    if( Amatch( ">", 0 ) ){
      if( value>p_expression() )	value = 1;	else	value = 0;
    }
    else if( Amatch(">=", 0 ) ){
      if( value>=p_expression() )	value = 1;	else	value = 0;
    }
    else if( Amatch("==", 0 ) ){
      if( value==p_expression() )	value = 1;	else	value = 0;
    }
    else if( Amatch("<=", 0 ) ){
      if( value<=p_expression() )	value = 1;	else	value = 0;
    }
    else if( Amatch("<", 0 ) ){
      if( value<p_expression() )	value = 1;	else	value = 0;
    }
    else if( Amatch("!=", 0 ) || Amatch("<>", 0 ) ){
      if( value!=p_expression() )	value = 1;	else	value = 0;
    }
    else{
      break;
    }
  }
  return( value );
}

sumdiff_Term()は、productdiv_Term()を呼びます。

//**********************************************
//和差を計算する項を解く関数
//**********************************************
float	sumdiff_Term( void )
{
float	value;
  value = productdiv_Term();
  while( 1 ){
    if( Amatch("+", 0 ) ){
      PNFlag = 1;
      value = value + productdiv_Term();
    }
    else if( Amatch("-", 0 ) ){
      PNFlag = 2;
      value = value - productdiv_Term();
    }
    else{
      break;
    }
  }
  return( value );
}

productdiv_Term()は、p_factor()を呼びます。

//**********************************************
//積商を計算する項を解く関数
//**********************************************
float	productdiv_Term( void )
{
float	value;
  value = p_factor();
  while( 1 ){
    if( Amatch("*", 0 ) ){
      PNFlag = 3;
      value = value * p_factor();
    }
    else if( Amatch("/", 0 ) ){
      PNFlag = 4;
      value = value / p_factor();
    }
    else if( Amatch("%", 0 ) ){
      PNFlag = 5;
      value = (float)((int)value % (int)p_factor());
    }
    else{
      break;
    }
  }
  return( value );
}

p_factor()に数値や変数、命令の処理や、分岐やループの処理を書きます。命令の区別なんかは、ハッシュテーブルを使ってもいいかも知れませんね。まだ未実装です。

//**********************************************
//要素を解く関数
//**********************************************
float	p_factor( void )
{
float	value=0;
  if( Amatch("(", 0 ) ){
    PNFlag = 0;
    value = p_expression();
    tojikakkoCheck();
  }
  else if( (Amatch("+",1)||Amatch("-",1)) && PNFlag==0 ){
    //式の先頭がプラス(+)かマイナス(-)だったときの処理
    value = 0;
    if( Amatch( "+", 0 ) ){
      value = value + p_expression();
    }
    else if( Amatch( "-", 0 ) ){
      value = value - p_expression();
    }
  }
  else if( Amatch("if", 0 ) ||  Amatch("elseif", 0 ) ){
    while( issptab( charget(TokenPos) ) )	TokenPos++;
    value = if_bunki();  //ifとelseifの処理
  }	
  else if( Amatch("else", 0 ) ){
    value = exeBlock( 0 );  //elseの処理
  }
  else if( Amatch("break", 0 ) ){		//break命令
    Henatai[ LocalHenStac[LocalHenStacPtr-1] ][0] = '2';
  }

〜〜〜〜〜〜〜途中省略〜〜〜〜〜〜〜

  else if( AmatchNumber() ){
    value = p_numericsE();
  }
  else if( AmatchAlphabet() ){
    value = p_hensuuORFunc();
  }
  else if( Amatch("#[", 0 ) ){
    //#]がくるまですべて無視する
    while( !Amatch("#]",0 )  )	TokenPos++;
  }
  else if( Amatch("#", 0 ) ){
    while( charget(TokenPos)!=0xd  )	TokenPos++;
    while( issptab( charget(TokenPos) ) )	TokenPos++;
  }
  else{
    value = 1.0;
    ErrorFlag = 2;
  }
  PNFlag = 0;
  return( value );
}

代入がある場合は、変数の判断をした後に'='があるかどうか判断し、'='があれば、'='以降にトークンを進めた後、p_expression()を呼び出す感じです。
if()文やwhile()、for()文も、関数と考えることで同じ処理で済ますことができます。構文に関しては、呼び先で、さらにp_expression()を呼び出すことにより、スクリプトの解釈を進めていくことになります。
解析のイメージくらいしか伝えられなくてすいません。現在、エラーに関するところはほとんど作っていない状態です。

本当にやりたいことリスト

(ブログの終わりにやりたいことを書いておきたいと思います)

  • 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
  • Androidプログラム
  • Web系のプログラム