スクリプトの解釈
毎日、少しずつ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系のプログラム