プログラミング言語 作成の実際 しらいゆたか.

Slides:



Advertisements
Similar presentations
2.5 プログラムの構成要素 (1)文字セット ① ASCII ( American Standard Code for Interchange ) JIS コードと同じ ② EBCDIC ( Extended Binary Coded Decimal for Information Code ) 1.
Advertisements

【事例演習5】  字句解析     解 説  “ハッシュを用いた字句解析の方法”.
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
JavaScript プログラミング入門 2006/11/10 神津.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
12.3,E,-15, 12.3,E5,+,=, >,<,…,
配列(2) 第10回[平成15年6月26日(木)]:PN03-10.ppt 今日の内容 1 素数を求める(教科書の例):復習
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング基礎I(再) 山元進.
コンパイラ 第9回 コード生成 ― スタックマシン ―
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
プログラミング言語論 第4回 式の構文、式の評価
アルゴリズムとデータ構造 2011年6月13日
構造体.
Boost.勉強会 #8 大阪 ( ) C++ Tips 3 カンマ演算子編.
プログラミング論 II 電卓,逆ポーランド記法電卓
  【事例演習6】  数式インタプリタ      解 説     “インタプリタの基本的な仕組み”.
の まとめ 2007/04/02 (Mon) / d;id:hzkr
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
構造体 構造体, 構造体とポインタの組み合わせ,.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラムの制御構造 選択・繰り返し.
プログラミング2 関数
第10回関数 Ⅱ (ローカル変数とスコープ).
アルゴリズムとプログラミング (Algorithms and Programming)
ソフトウェア制作論 平成30年10月3日.
第7回 プログラミングⅡ 第7回
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造1 2005年6月24日
アルゴリズムとデータ構造 2010年6月21日
プログラミング言語論 第四回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造 2011年7月8日課題の復習
コンパイラ 2011年10月20日
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
アルゴリズムとプログラミング (Algorithms and Programming)
C++ 構文解析 構文解析器の状態保存と復元
参照されないリテラル 長谷川啓
IF文 START もしも宝くじが当たったら 就職活動する 就職活動しない YES END NO.
第6回レポート解説 条件1 条件2 条件3 月の入力 月、日、曜日の表示 日の入力 曜日の入力
C#プログラミング実習 第3回.
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
アルゴリズムとデータ構造 2012年6月11日
アルゴリズムとデータ構造1 2009年6月15日
第5回 プログラミングⅡ 第5回
C言語講座 制御(選択) 2006年 計算技術研究会.
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 第7回 2004年11月16日(火).
情報処理Ⅱ 2005年10月28日(金).
JAVA入門⑥ クラスとインスタンス.
コンパイラ 2012年10月11日
プログラミング 4 文字列.
アルゴリズムとデータ構造 2010年6月17日
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
:: の扱い 長谷川啓.
情報処理Ⅱ 2005年11月25日(金).
8.文字列処理 8.1 C#の文字列 C#では, “ABCD”のように文字列を2重引用符で挟んで指定します。ASCIIコード体系のとき,以下のような内部形式となります。 1 1 文字 ‘A’ ナル文字 1 1 文字 ‘B’ A B C D \ 文字 ‘C’ 1 1 文字 ‘D’ ナル文字‘\0’
プログラミング基礎a 第5回 C言語によるプログラミング入門 配列と文字列
プログラミング入門2 第5回 配列 変数宣言、初期化について
場合分け(If Then Else,Select Case) 繰返し(Do While) 繰返しその2(For Next)
情報処理Ⅱ 小テスト 2005年2月1日(火).
情報処理Ⅱ 第3回 2004年10月19日(火).
情報処理Ⅱ 2006年10月20日(金).
7.集合 7.1 集合とは [集合と要素] 関東の都道府県 群馬県 栃木県 要素 埼玉県 茨城県 東京都 千葉県 神奈川県
6.3 インタプリタ (1)インタプリタ(interpreter)とは
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
6.5 最終コード生成 (1)コードの形式 ①絶対2進コード(AB : absolute binary) 命令後のオペランドが絶対番地指定。
Presentation transcript:

プログラミング言語 作成の実際 しらいゆたか

言語プロセッサの処理 次の手順で処理する。 (1)文識別 (2)語彙解析(Lexical Analysis) (3)構文解析(Syntax Analysis) (4)意味解析(Semantic Analysis)    およびコード生成(Code Generation) さらに,インタプリタの場合,実行(Execution)

1.文識別 最初に行うのは,1文を取り出す処理。 ■ 1行の中に複数の文 ■ 2行以上で1文 語彙解析の途中で,文の終わりを判別するのは ■ 1行の中に複数の文 ■ 2行以上で1文 語彙解析の途中で,文の終わりを判別するのは 処理を複雑にしてしまう。 文識別は最初に行う。 ただし,文字列の処理が必要。 最小限の文字列処理を行いながら文を取り出す。

プログラム例(1) public int ptrText; public string AllText; private string 文取り出し() // 全ソースの中から1文を取り出す { string S=""; while(ptrText<AllText.Length) {  if(AllText[ptrText]=='\n'||AllText[ptrText]=='\r'){ptrText++;return S;}  else if(AllText[ptrText]==':') {ptrText++;return S;}  else if(AllText[ptrText]=='_') { ptrText++; while(ptrText<AllText.Length){      if(AllText[ptrText]=='\n'||AllText[ptrText]=='\r')break;   ptrText++; }  }    (続きあり)

プログラム例(2) else if(AllText[ptrText]==‘“’){ // 文字列内処理 S += AllText[ptrText].ToString(); ptrText++; while(ptrText<AllText.Length) {   if(AllText[ptrText]=='\n'||AllText[ptrText]=='\r') { MessageBox.Show("ダブルクォーテーション(\")が足りません"); return S;   }   else if(AllText[ptrText]=='"') { if((ptrText>=AllText.Length) || (AllText[ptrText]!='"')) break;   S+=AllText[ptrText].ToString(); ptrText++; }    }  S=S+AllText[ptrText].ToString();  ptrText++; private void 全文取出し() // テキストボックスの内容をソースプログラムとする。 { AllText=textBox1.Text; ptrText=0;

2.語彙解析(Lexical Analysis) 文字列を単語に分ける処理。 準備として,次のような構造体を定義しておこう。   public struct WordData { public string type; public string str; public WordData(string tp,string st) {  type = tp; str = st;} }

語彙解析の2段階 複数の文字種別による単語がありうるので, 文字種別の判定だけでは単語を区別するのが困難。 もし可能だとしても処理が複雑になる。 (C#の例)12.5E-12 したがって,2段階に分離するのが常套手段。 単語の識別 呼出し 文字種別による識別

最も低レベルの文字列の判別(1) public string 数字="0123456789"; private int 該当文字(string str, char CH) { for(int i=0;i<str.Length;i++) if(str[i]==CH) return i; return -1; } private WordData LA0() // 文字種別による識別 while(ptr<str.Length) if(str[ptr]==' ' || str[ptr]==' ' || str[ptr]=='\t') ptr++; else if(str[ptr]=='\n') ptr++; else if(str[ptr]=='\r') ptr++; else if(str[ptr]=='\"') return 文字列設定(); else if(str[ptr]=='.' ) return 数字列設定(); else if(該当文字(数字,str[ptr])>=0) return 数字列設定(); else if(該当文字(区切記号,str[ptr])>=0) return 区切記号設定(); else return 名前設定(); return new WordData("End","");

最も低レベルの文字列の判別(2) private WordData 文字列設定() { string S="";ptr++; while(ptr<str.Length)   if(str[ptr]=='\n'||str[ptr]=='\r')   { MessageBox.Show("\"がありません"); return new WordData("String",S); } else if(str[ptr]=='"') ptr++; if((ptr==str.Length) || (str[ptr]!='"')) return new WordData("String",S); S=S+str[ptr].ToString();

最も低レベルの文字列の判別(3) private WordData 数字列設定() { string S=""; while(ptr<str.Length && 該当文字(数字,str[ptr])>=0) S += str[ptr].ToString();     ptr++; } if(ptr<str.Length && str[ptr]=='.')   S +="."; ptr++;   while(ptr<str.Length && 該当文字(数字,str[ptr])>=0)   {  S += str[ptr].ToString();  ptr++;   } if(S==".") return new WordData("Delimiter",S); else return new WordData("Number",S);

最も低レベルの文字列の判別(4) private WordData 名前設定() { string S=""; while(ptr<str.Length)     if ( str[ptr]=='"' || str[ptr]==' ' || str[ptr]==' ' ||      str[ptr]=='\n'|| str[ptr]=='\r') break;   int N = 該当文字(区切記号,str[ptr]); if (N>=0) break;   S += str[ptr].ToString();   ptr++; } return new WordData("Name",S); private WordData 区切記号設定() WordData P= new WordData("Delimiter",str[ptr].ToString()); ptr++; return P;

単語の識別(1) public int numTokenX=0 ; // 語彙解析結果の格納位置 public WordData[] tokenX=new WordData[500]; // 語彙解析結果 private bool E_exp(string str) // Eに続いて数字列になっているか(指数形式の判別) { if(str.Length<2) return false; if(str[0]!='E' && str[0]!='e') return false; for(int i=1;i<str.Length;i++) if(該当文字(数字,str[i])<0) return false; return true; } // 途中経過表示用(途中経過表示なければ必要ない) private void debugLA(WordData token1,WordData token2,WordData token3,WordData token4) string S=" 1:"+ token1.type+ " \t ["+token1.str+"]\n"+ " 2:"+ token2.type+" \t ["+token2.str+"]\n"+ " 3:"+ token3.type+" \t ["+token3.str+"]\n"+ " 4:"+ token4.type+" \t ["+token4.str+"]"; DialogResult result = MessageBox.Show(S,"語彙解析途中",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false; private void set_TokenX(string type, string str) // 語彙解析結果のセット tokenX[numTokenX].type=type; tokenX[numTokenX].str=str; numTokenX++;

単語の識別(2) private void combineDelimiter(string str1, string str2) // 複数区切り記号による演算子 { set_TokenX("Delimiter",str1+str2);} private void LA1() { numTokenX=0; WordData token1,token2,token3,token4; token1=LA0();token2=LA0();token3=LA0();token4=LA0(); while(token1.type!="End") if(checkBox1.Checked)debugLA(token1,token2,token3,token4); if( token1.type=="Number" &&  token2.type=="Name" && token2.str=="E" && token3.type=="Delimiter" && (token3.str=="+" || token3.str=="-")&& token4.type=="Number") set_TokenX("Number",token1.str+token2.str+token3.str+token4.str); } else if( token1.type=="Number" && token2.type=="Name" && E_exp(token2.str)){ set_TokenX("Number",token1.str+token2.str); token1=token3;token2=token4;token3=LA0();token4=LA0(); else if(token1.type=="Delimiter" && token1.str==">" && token2.type=="Delimiter" && token2.str=="=" ) { combineDelimiter(token1.str,token2.str);

単語の識別(3) else if(token1.type=="Delimiter" && token1.str==">" && combineDelimiter(token1.str,token2.str); token1=token3;token2=token4;token3=LA0();token4=LA0(); } else if(token1.type=="Delimiter" && token1.str=="=" && token2.type=="Delimiter" && token2.str=="<" ){ else if(token1.type=="Delimiter" && token1.str=="<" && else if(token1.type=="Delimiter" && token1.str=="|" && token2.type=="Delimiter" && token2.str=="|" ){ else if(token1.type=="Delimiter" && token1.str=="&" && token2.type=="Delimiter" && token2.str=="&" ){ else if(token1.type=="Delimiter" && token1.str=="%" &&   token2.type=="Delimiter" && token2.str=="%" ){

単語の識別(4) else if(token1.type=="Delimiter" && token1.str=="!" && combineDelimiter(token1.str,token2.str); token1=token3;token2=token4;token3=LA0();token4=LA0(); } else if(token1.type=="Delimiter" && token1.str=="=" && else if(token1.type=="Delimiter" && token1.str=="+" && token2.type=="Delimiter" && token2.str=="+"){ else if(token1.type=="Delimiter" && token1.str=="-" && token2.type=="Delimiter" && token2.str=="-"){

単語の識別(5) else if(token1.type=="Delimiter" && token1.str=="-" && combineDelimiter(token1.str,token2.str); token1=token3;token2=token4;token3=LA0();token4=LA0(); } else if(token1.type=="Delimiter" && token1.str=="*" && token2.type=="Delimiter" && token2.str=="="){ else if(token1.type=="Delimiter" && token1.str=="/" && else if(token1.type=="Name" && token1.str=="end" && token2.type=="Name" && token2.str=="if"){ set_TokenX(token1.type,token1.str+token2.str); else{ set_TokenX(token1.type,token1.str); token1=token2;token2=token3;token3=token4;token4=LA0();

3.構文解析 語彙解析の結果から文を判別して, 一文の解析結果を作成する。 ただし,式の場合は,優先順位を判別する必要がある。 基本的には,逆ポーランド記法に展開する。 文全体の処理と逆ポーランド記法への変換を分ける。

逆ポーランド記法変換 ①変数や定数はそのまま出力トークンへ移動する。 ②演算子はスタック上の演算子と比較し,スタック上の演算子の優先度が取り出した演算子と等しいか大きい場合,スタック上の演算子をポップして出力トークンに移動する。 ④取り出した演算子をプッシュする。 ⑤前括弧の場合,プッシュする。 ⑥後括弧の場合,前括弧までをポップする。このとき,スタックトップが関数表現ならば,関数呼出しを出力トークンに移動する。 ⑦関数表現の場合,関数表現と前括弧をプッシュする。 ⑧コンマの場合,前括弧の直前までポップする。 ⑨1文終わりのときは後括弧と同じ処理を行う。

演算子等の解釈 ①演算子モードと値モードを用意し,初期値は値モードとする。 ②値モードのとき,演算子がきたら前置単項演算子とみなす。 ③演算子モードのとき,前括弧がきたら,先行する名前は関数表現とみなし,値モードに移行する。 ④演算子モードのとき,後置演算子か通常の演算子かを判定する。  後置演算子でない場合,値モードに移行する。 ⑤コンマのとき,値モードに移行する。 ⑥前括弧の場合,値モードに移行する。 ⑦後括弧の場合,演算子モードに移行する。

逆ポーランド記法への変換 (1)トレース用ルーチン // このルーチンを残しておくことでモードがどのように移行しているかをチェックできる。 private void debugSA0(int i,bool Mode) { string S="*Lexical\n";int k; for(k=i; k<numToken; k++) S +=" " + token[k].str; S+="\n*Mode = "+(Mode ? "Value" :"Operation")+"\n*Polish\n"; for(k=0; k<numPolish; k++) if(Polish[k].operation=="-$" || Polish[k].operation=="+$") S +=" " + Polish[k].operation; else S +=" " + Polish[k].str; } S += "\n*Stack\n"; for(k=ptrStack-1; k>=0; k--) if(Stack[k].operation=="-$" || Stack[k].operation=="+$") S +=" " + Stack[k].operation; else S +=" " + Stack[k].str; S+="\n"; DialogResult result = MessageBox.Show(S,"構文解析途中経過1",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false;

逆ポーランド記法への変換 (2)データ領域宣言 public struct TokenData { public string operation; public int priority; public string str; public TokenData(string ope,int pr, string st) operation = ope; priority = pr ; str = st ; } public int numPolish=0 ;// 出力トークンの数 public int numToken=0 ; // 入力トークンの数 public int ptrStack=0 ; // スタックの高さ public TokenData[] Polish=new TokenData[200];// 出力トークン public TokenData[] Stack=new TokenData[200]; // スタック public WordData[] token=new WordData[500]; // 入力トークン

逆ポーランド記法への変換 (3)変換処理① // 以下の処理を行う前に, // 文中の式表現に対応する部分を取り出して // token[numToken]に移しておく private void SA0() { numPolish=0; ptrStack=0 ; int i=0;bool Mode=true; while(i<numToken) if(checkBox1.Checked) debugSA0(i,Mode); if(Mode) {  // 値モード if(token[i].type=="Delimiter" && (token[i].str=="+" || token[i].str=="-")) pushProc(new TokenData(token[i].str+“$”,300,token[i].str)); // 前置 else if(token[i].type=="Delimiter" && (token[i].str=="++" || token[i].str=="--")) else if(token[i].type=="Delimiter" && token[i].str=="!" ) pushProc(new TokenData(token[i].str,40,token[i].str)); // 前置 else if(token[i].type=="Delimiter" && token[i].str=="(") pushProc(new TokenData(token[i].str,0,token[i].str)); // 前置 else if(token[i].type=="Name" && token[i].str=="if") {                                // if関数 postFix(new TokenData("if",0,token[i].str)); push(new TokenData("Block",0,token[i].str)); }

逆ポーランド記法への変換 (3)変換処理② else if(token[i].type==“Name” && // 関数表現 i<(numToken-1) && (token[i+1].type=="Delimiter" && token[i+1].str=="(")) { postFix(new TokenData("ArgEnd",0,token[i].str)); push(new TokenData("Func",0,token[i].str)); i++; } else if(token[i].type!=“Delimiter”) // 値または変数など postFix(new TokenData(token[i].type,0,token[i].str)); Mode=false;    // 演算子モードに移行 else MessageBox.Show("001 区切記号の位置の誤り"); break;

逆ポーランド記法への変換 (3)変換処理③ else { // 演算子モード Mode=true; // 標準的には値モードに移行 { // 演算子モード Mode=true; // 標準的には値モードに移行 if (token[i].type=="Delimiter" && (token[i].str=="+" || token[i].str=="-")) pushProc(new TokenData(token[i].str,100,token[i].str)); else if(token[i].type=="Delimiter" && (token[i].str=="++" || token[i].str=="--")) pushProc(new TokenData(token[i].str,10,token[i].str)); else if(token[i].type=="Delimiter" && (token[i].str=="+=" || token[i].str=="-=")) else if(token[i].type=="Delimiter" && (token[i].str=="*=" || token[i].str=="/=")) else if(token[i].type=="Delimiter" && token[i].str=="=") else if(token[i].type=="Delimiter" && (token[i].str=="||" || token[i].str=="&&" || token[i].str== "%%")) pushProc(new TokenData(token[i].str,30,token[i].str)); (token[i].str=="==" || token[i].str=="!=" || token[i].str== ">" || token[i].str==">=" || token[i].str=="=>" || token[i].str== "<" || token[i].str=="<=" || token[i].str=="=<")) { if (token[i].str=="=>") token[i].str=">="; else if(token[i].str=="=<") token[i].str="<="; pushProc(new TokenData(token[i].str,50,token[i].str)); } (token[i].str=="*" || token[i].str=="/"|| token[i].str=="%")) pushProc(new TokenData(token[i].str,200,token[i].str));

逆ポーランド記法への変換 (3)変換処理④ else if(token[i].type=="Name" && token[i].str=="mod") pushProc(new TokenData(token[i].str,200,token[i].str)); else if(token[i].type=="Delimiter" && token[i].str=="^") pushProc(new TokenData(token[i].str,400,token[i].str)); else if(token[i].type=="Delimiter" && token[i].str==")") { popProcS();Mode=false;} else if(token[i].type=="Delimiter" && token[i].str==",") popProcF(); else if(token[i].type=="Name" && (token[i].str=="then" || token[i].str=="else")){ popProcBlock(); postFix(new TokenData(token[i].str,0,token[i].str)); push(new TokenData("Block",0,token[i].str)); Mode=true; } else if(token[i].type=="Name" && token[i].str=="endif"){ else { MessageBox.Show("002 名前の位置または演算子の誤り"); break; i++;  }  if(checkBox1.Checked) debugSA0(i,Mode);  popProcE();

逆ポーランド記法への変換 (4)データ領域アクセス① public void push(TokenData TK) { Stack[ptrStack++]=TK; } public TokenData pop() { if(ptrStack==0) return new TokenData("Empty",0,""); ptrStack--; return Stack[ptrStack]; } public void postFix(TokenData TK) { Polish[numPolish]=TK;numPolish++;} public void pushProc(TokenData TK) { if(ptrStack>0) while(ptrStack>0 &&TK.priority<=Stack[ptrStack-1].priority && TK.operation!="(") postFix(pop()); push(TK); public void popProcS() { TokenData XX=pop(); while(ptrStack>=0) if(XX.operation=="(") break; if(XX.operation=="Func"){postFix(XX);break; } postFix(XX); XX=pop();

逆ポーランド記法への変換 (4)データ領域アクセス② public void popProcF() { TokenData XX = pop(); while(ptrStack>=0) if(XX.operation=="Func"){push(XX); break;} postFix(XX); XX=pop(); } public void popProcBlock() if(XX.operation=="Block")break; public void popProcE() TokenData XX; XX=pop(); while(ptrStack>0) { postFix(XX);XX=pop();} if(XX.operation!="Empty")postFix(XX);

逆ポーランド記法への変換 (5)変換用トークンの複写 private void token複写(ref int i) // 語彙解析結果すべてを複写 { numToken=0; while(i<numTokenX) token[numToken]=tokenX[i];numToken++; i++; } private void token複写Comma(ref int i) // コンマまでを複写(括弧のレベルを考慮する) numToken=0;int lebel=0; if (tokenX[i].type=="Delimiter" && tokenX[i].str=="(")lebel++; else if(tokenX[i].type=="Delimiter" && tokenX[i].str==")")lebel--; else if(lebel==0 && tokenX[i].type=="Delimiter" && tokenX[i].str==",") return;

1文ごとの構文解析 文種別ごとに, 式部分を分離し,逆ポーランド変換を行い, 文ごとの解釈を行う。 IfブロックやWhileブロックの処理を行うために スタックを用意する。

If ブロックやWhileブロック用のスタック public struct BlockData // ブロックコントロールデータ { public string Type; public int BP; public int IfP; public int ThenP; } public BlockData [] IfStack=new BlockData[200]; public int IfStackP=0; public BlockData [] DoStack=new BlockData[200]; public int DoStackP=0; public int[] numBreak=new int[200]; // Break処理用テーブル public int[,] BreakP=new int[200,200];

構文解析 (1)トレース用ルーチン private void debugSA(int i) { listBox2.Items.Clear();string S=""; for(int k=0;k<numPolish;k++) string X=Polish[k].operation+ "\t" + Polish[k].str;    S="\n"+X; listBox2.Items.Add(X); } DialogResult result = MessageBox.Show(S,"構文解析途中経過2",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false;

構文解析 (2)構文解析・コード生成メイン処理① private void SA() { int i=0; while(i<numTokenX) if(tokenX[i].type==“Name” && tokenX[i].str==“if”) // if文 if論理式(ref i); // if文から論理式を取り出し numPolish=0; SA0(); numStatementNo++; int oldP=numStatement; SA設定("StNo",0,numStatementNo.ToString()); if(checkBox1.Checked) debugSA(0); 現Polishのオブジェクト設定(); IfPush(oldP,numStatement,0); SA設定("Number",0,""); SA設定("then",0,"then"); if(i+1 < numTokenX) MessageBox.Show("thenの後に文は書けません"); }

構文解析 (2)構文解析・コード生成メイン処理② else if(tokenX[i].type==“Name” && tokenX[i].str==“else”) // else処理 { IfStack[IfStackP].ThenP=numStatement; SA設定("Number",0,""); SA設定("goto",0,"goto"); numStatementNo++; AllStatement[IfStack[IfStackP].IfP].str=numStatement.ToString(); SA設定("StNo",0,numStatementNo.ToString()); if(i+1 < numTokenX) MessageBox.Show("elseの後に文は書けません"); } else if(tokenX[i].type=="Name" && tokenX[i].str=="endif") // end if int IP=IfStack[IfStackP].IfP; if(AllStatement[IP].str=="") AllStatement[IP].str=numStatement.ToString(); else AllStatement[IfStack[IfStackP].ThenP].str=numStatement.ToString(); if(i+1 < numTokenX) MessageBox.Show("endifの後に文は書けません"); IfStackP--;

構文解析 (2)構文解析・コード生成メイン処理③ else if(tokenX[i].type==“Name” && tokenX[i].str==“while”) // while文 { i++; token複写(ref i); numPolish=0; SA0(); numStatementNo++; int oldP=numStatement; SA設定("StNo",0,numStatementNo.ToString()); if(checkBox1.Checked) debugSA(0); 現Polishのオブジェクト設定(); DoPush(oldP,numStatement,0,"while"); SA設定("Number",0,""); SA設定("then",0,"then"); } else if(tokenX[i].type=="Name" && tokenX[i].str=="wend") numStatementNo++; SA設定("Number",0,DoStack[DoStackP].BP.ToString()); SA設定("goto",0,"goto"); string S=numStatement.ToString(); if (DoStack[DoStackP].Type=="while") AllStatement[DoStack[DoStackP].IfP].str=S; else MessageBox.Show("while_wendの対応がとれません.文="+numStatementNo.ToString()); for(int k=0;k<numBreak[DoStackP];k++) AllStatement[BreakP[DoStackP,k]].str=S; if(i+1 < numTokenX) MessageBox.Show ("wendの後に文は書けません.文="+numStatementNo.ToString()); DoStackP--;

構文解析 (2)構文解析・コード生成メイン処理④ else if(tokenX[i].type=="Name" && tokenX[i].str=="repeat") { numStatementNo++; int oldP=numStatement; SA設定("StNo",0,numStatementNo.ToString()); DoPush(oldP,numStatement,0,"repeat"); } else if(tokenX[i].type=="Name" && tokenX[i].str=="until") i++; token複写(ref i); numPolish=0; SA0(); if(checkBox1.Checked) debugSA(0); 現Polishのオブジェクト設定(); string BS=DoStack[DoStackP].BP.ToString(); SA設定("Number",0,BS); SA設定("then",0,"then"); string S=numStatement.ToString(); if (DoStack[DoStackP].Type !="repeat") MessageBox.Show("repeat_untilの対応がとれません.文="+numStatementNo.ToString()); for(int k=0;k<numBreak[DoStackP];k++) AllStatement[BreakP[DoStackP,k]].str=S; if (DoStackP>0) DoStackP--;

構文解析 (2)構文解析・コード生成メイン処理⑤ else if(tokenX[i].type=="Name" && tokenX[i].str=="for") { i++; for初期化(ref i); numPolish=0;SA0(); numStatementNo++; // 初期化式 SA設定("StNo",0,numStatementNo.ToString()); if(checkBox1.Checked) debugSA(0); 現Polishのオブジェクト設定(); numPolish=0; for判定(ref i); SA0();  // 判定式 for(int k=0;k<numPolish;k++)TempStatement[k]=Polish[k]; int numTemp=numPolish; int IGoto=numStatement; SA設定("Number",0,""); SA設定("goto",0,"goto"); int oldP=numStatement; for増分(ref i); numPolish=0; SA0(); // 増分式 AllStatement[IGoto].str=numStatement.ToString(); for(int k=0;k<numTemp;k++) AllStatement[numStatement++]=TempStatement[k]; DoPush(oldP,numStatement,0,"for"); SA設定("Number",0,""); SA設定("then",0,"then"); }

構文解析 (2)構文解析・コード生成メイン処理⑥ else if(tokenX[i].type=="Name" && tokenX[i].str=="next") { numStatementNo++; SA設定("StNo",0,numStatementNo.ToString()); SA設定("Number",0,DoStack[DoStackP].BP.ToString()); SA設定("goto",0,"goto"); string S=numStatement.ToString(); if (DoStack[DoStackP].Type=="for") AllStatement[DoStack[DoStackP].IfP].str=S; else MessageBox.Show("for_nextの対応がとれません.文="+numStatementNo.ToString()); S=numStatement.ToString(); for(int k=0;k<numBreak[DoStackP];k++) AllStatement[BreakP[DoStackP,k]].str=S; if(i+1 < numTokenX) MessageBox.Show     ("nextの後に文は書けません.文="+numStatementNo.ToString()); DoStackP--; break; } else if(tokenX[i].type=="Name" && tokenX[i].str=="break") BreakP[DoStackP,numBreak[DoStackP]++]=numStatement; SA設定("Number",0,""); if(i+1 < numTokenX) MessageBox.Show("breakの後に文は書けません");

構文解析 (2)構文解析・コード生成メイン処理⑦ else if(tokenX[i].type=="Name" && tokenX[i].str=="function") { i++; if (tokenX[i].type != "Name") MessageBox.Show("関数名がありません。"+tokenX[i].str); } else FunctionNameTable[numberOfFunction].name=tokenX[i].str; int ID=0; while(FunctionNameTable[ID].name != tokenX[i].str) ID++; if(ID>=numberOfFunction) numberOfFunction++; FunctionNameTable[ID].ptr=numStatement; numStatementNo++; SA設定("StNo",0,numStatementNo.ToString()); if(checkBox1.Checked)   string S=“関数名 : ” +FunctionNameTable[ID].name +    " address : " +FunctionNameTable[ID].ptr;   DialogResult result = MessageBox.Show (S, "構文解析途中経過2",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false;        i++;

構文解析 (2)構文解析・コード生成メイン処理⑧ if(tokenX[i].type !="Delimiter" || tokenX[i].str!="(")      MessageBox.Show("左括弧がありません。"+tokenX[i].str); i++; SA設定("*PStart*",0,"*PStart*"); if(i<numTokenX){ while(i<numTokenX){ if(tokenX[i].type=="Name"){ AllStatement[numStatement].operation="*Parm*"; AllStatement[numStatement].priority=0; AllStatement[numStatement].str=tokenX[i].str; numStatement++; if(checkBox1.Checked){ DialogResult result = MessageBox.Show ("仮引数 : "+tokenX[i].str,"構文解析途中経過2",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false; }        else MessageBox.Show("引数名がありません。"+tokenX[i].str);        i++;  if(!(tokenX[i].type =="Delimiter" &&( tokenX[i].str!=","|| tokenX[i].str!=")"))) MessageBox.Show("コンマ,または右括弧がありません。"+tokenX[i].str);  }  SA設定("*PEnd*",0,"*PEnd*");   }

構文解析 (2)構文解析・コード生成メイン処理⑨ else if(tokenX[i].type=="Name" && tokenX[i].str=="dim") { i++; string ArrayName; numStatementNo++; SA設定("StNo",0,numStatementNo.ToString()); while(i<numTokenX) ArrayName=tokenX[i].str; token複写Comma(ref i); numPolish=0; SA0(); SA設定("*dimStart",0,ArrayName); if(checkBox1.Checked) listBox2.Items.Clear(); for(int k=0;k<numPolish;k++) listBox2.Items.Add(Polish[k].operation+ "\t" + Polish[k].priority.ToString()+ "\t" + Polish[k].str); } Polish[numPolish-1].operation ="dim"; 現Polishのオブジェクト設定(); if(checkBox1.Checked) debugSA(i);

構文解析 (2)構文解析・コード生成メイン処理⑩ else if(tokenX[i].type=="Name" && tokenX[i].str=="end") { numStatementNo++; SA設定("StNo",0,numStatementNo.ToString()); SA設定("end",0,"end"); if(i+1 < numTokenX) MessageBox.Show ("endの後に文は書けません.文="+numStatementNo.ToString()); break; } else if(tokenX[i].type=="Name" && tokenX[i].str=="return") i++; token複写(ref i); numPolish=0; SA0(); int oldP=numStatement; if(checkBox1.Checked) debugSA(0); 現Polishのオブジェクト設定(); SA設定("return",0,"return"); string S=numStatement.ToString();

構文解析 (2)構文解析・コード生成メイン処理⑪ else { // 代入文    token複写(ref i); numPolish=0; SA0(); numStatementNo++; SA設定("StNo",0,numStatementNo.ToString()); if(checkBox1.Checked) { listBox2.Items.Clear(); for(int k=0;k<numPolish;k++) listBox2.Items.Add(Polish[k].operation+ "\t" + Polish[k].priority.ToString()+ "\t" + Polish[k].str); } 現Polishのオブジェクト設定(); if(checkBox1.Checked) debugSA(i); i++;

構文解析 (3)設定用関数① private void if論理式(ref int i) // ifの論理式 { numToken=0;i++; if(i<numTokenX) { while(i<numTokenX){ if(tokenX[i].type=="Name" && tokenX[i].str=="then"){i++;break;} token[numToken++]=tokenX[i++]; } } } private void for初期化(ref int i) // forの初期化式 { numToken=0; if(tokenX[i].type=="Delimiter" && tokenX[i].str==";"){i++;break;} private void for判定(ref int i)  // forの判定式 private void for増分(ref int i) // forの増分式

構文解析 (3)設定用関数② private void SA設定(string op, int pr, string str) { AllStatement[numStatement].operation=op; AllStatement[numStatement].priority=pr; AllStatement[numStatement].str=str; numStatement++; } private void IfPush(int BP, int IfP,int ThenP) { IfStackP++; IfStack[IfStackP].BP=BP; IfStack[IfStackP].IfP=IfP; IfStack[IfStackP].ThenP=ThenP; IfStack[IfStackP].Type="if"; private void DoPush(int BP, int IfP,int ThenP, string Type) { DoStackP++; DoStack[DoStackP].BP=BP; DoStack[DoStackP].IfP=IfP; DoStack[DoStackP].ThenP=ThenP; DoStack[DoStackP].Type=Type; numBreak[DoStackP]=0; private void 現Polishのオブジェクト設定() { for(int k=0;k<numPolish;k++) AllStatement[numStatement++]=Polish[k]; }

逆ポーランド記法のまま実行するには, スタックマシンとして実行する これによってインタプリタを実現できる。 評価用のスタックが必要。 ただし,代入等の処理が必要なので, 演算等により値が必要になった時点で評価する。 配列は,本来,該当サイズの領域を確保する必要があるが, ここでは,配列添え字と組み合わせた文字列の変数 たとえば「A(1,2,3)」として処理する。

バインディングの方法 (呼出時) ①リターンアドレスをプログラムスタックにpush ②仮引数名と値をプログラムスタックにpush ③演算スタックをPopし,仮引数名に実引数の値を割り当てる。 (リターン時) ①仮引数の値をプログラムスタックからPopして元に戻す。 ②リターンアドレスをプログラムスタックからPopして元に戻す。 ③リターン値を演算スタックにPushする。

バインディングの方法 手続き ①仮引数Push ②値割り当て ③関数実行 ④リターン 演算スタック A2 A1 返却値 プログラム カウンタ 関数アドレス 変数名テーブル 変数名テーブル 変数名テーブル P1:V1 P1:A1 P1:V1 関数実行 プログラム カウンタ P2:V2 P2:A2 P2:V2 Return プログラムスタック P2:V2 P2:V2 P2:V2 P1:V1 P1:V1 P1:V1 リターンアドレス リターンアドレス リターンアドレス リターンアドレス

インタプリタのデータ宣言① public struct NameData // 変数名の構造体 { public string Name; public string Text; public double Val; public string Type; public NameData(string name, double val) Name=name; Val=val; Text=val.ToString(); Type="Number"; } public NameData(string name, string val) Name=name; Val=0.0; Text=val; Type="String"; public NameData(string name) Name=name; Val=0.0; Text=""; Type="Name";

インタプリタのデータ宣言② public struct BlockData // 実行用ブロックコントロールデータ { public string Type; public int BP; public int IfP; public int ThenP; } public struct FunctionName // 関数名データ public string name; public int ptr; public FunctionName [] FunctionNameTable =new FunctionName[200]; public int numberOfFunction=0; public NameData[] argData =new NameData[200]; public int numArg=0; public int ptrArg=0; public int nextIP; public NameData [] NameTable = new NameData[200]; public int ptrNameTable=0; public NameData [] EvalStack = new NameData[200]; public int ptrEvalStack=0; public NameData[] ProgStack=new NameData[2000]; public int ptrProgStack=0 ;

private void button3_Click(object sender, System.EventArgs e) { ptrProgStack=0;Eval();Eval_Display_Result(numStatement+1);} private void Eval() { NameData P1,P2; int i=0; pushEvalStack(new NameData("*Function*")); while(i<numStatement) { if(checkBox1.Checked)debugEval(i); nextIP =i+1; if (AllStatement[i].operation=="end") { MessageBox.Show("プログラムの終了です。カウンタ=" + i.ToString()); break;} switch (AllStatement[i].operation) { case "+" :Eval_add();break; case "-" :Eval_sub();break; case "%" :Eval_mod();break; case "*" :Eval_mult();break; case "mod" :Eval_mod();break; case "/" :Eval_dev();break; case "^" :Eval_exp();break; case "=" :Eval_set();break; case "++" :Eval_PPset();break; case "--" :Eval_MMset();break; case "++$" :Eval_BeforPPset();break; case "--$" :Eval_BeforMMset();break; case "-$" :Eval_minus();break; case "+$" :Eval_plus();break; case "+=" :Eval_AsignPset();break; case "-=" :Eval_AsignMset();break; case "*=" :Eval_AsignMultset();break; case "/=" :Eval_AsignDivset();break; case "==" :Eval_equal();break; case "!=" :Eval_not_equal();break; case ">" :Eval_greater_than();break; インタプリタメイン①

インタプリタメイン② case ">=" :Eval_greater_than_equal();break; case "<" :Eval_less_than();break; case "<=" :Eval_less_than_equal();break; case "||" :Eval_or();break; case "&&" :Eval_and();break; case "%%" :Eval_exclusive_or();break; case "!" :Eval_not();break; case "ArgEnd" :Eval_Arg();break; case "Func" :Eval_func(AllStatement[i].str);break; case "*dimStart" :Eval_dimStart(AllStatement[i].str);break; case "dim" :Eval_dim();break; case "*PStart*" :Eval_PStart();break; case "*Parm*" :Eval_Param(AllStatement[i].str);break; case "return" :Eval_return();break; case "StNo" : StatementNo=int.Parse(AllStatement[i].str); if(checkBox1.Checked) MessageBox.Show("Statement No = "+AllStatement[i].str); ptrEvalStack=0;break; case "goto" : P1=Eval(popEvalStack()); nextIP=(int)P1.Val; break; case "then" : P2=Eval(popEvalStack()); P1=Eval(popEvalStack()); if(P1.Type=="Number" && P2.Type=="Number" ) { if(P1.Val ==0) nextIP=(int)P2.Val; } else MessageBox.Show("評価エラーです"); break; default :pushEvalStack(AllStatement[i]);break; } i=nextIP; Eval_Display_Result(i); } } インタプリタメイン②

トレース用ルーチン private void debugEval(int i) { string S1=AllStatement[i].operation; string S2=AllStatement[i].str; if(S1!=S2) { if(S1=="String") S1 += ("\"" + S2+"\""); else S1 += ("(" + S2+")"); } string S="*Operation " +S1 + "\n\n*PC=" + i + " StNo=" + StatementNo.ToString(); int k; S += "\n\n*Name Table\n"; for(k=0; k<ptrNameTable; k++) { S +=NameTable[k].Name+"\t"; if(NameTable[k].Type=="Number") S +="Number[" + NameTable[k].Val+"]\n"; else S +=NameTable[k].Type+"[" + NameTable[k].Text+"]\n"; S += "\n*Eval Stack\n"; for(k=ptrEvalStack-1; k>=0; k--) { S +=EvalStack[k].Name+"\t"; if (EvalStack[k].Type=="Name") S += "Name\n"; else if(EvalStack[k].Type=="Number") S +="Number[" + EvalStack[k].Val+"]\n"; else S +=EvalStack[k].Type+"\"" + EvalStack[k].Text+"\"\n"; DialogResult result = MessageBox.Show(S,"評価",MessageBoxButtons.OKCancel); if(result==DialogResult.Cancel) checkBox1.Checked=false;

実行用メソッド① private void pushEvalStack(TokenData TK) // TokenのPush { switch (TK.operation) { case "String" : EvalStack[ptrEvalStack]=new NameData("",TK.str);break; case "Number" : EvalStack[ptrEvalStack]=new NameData("",double.Parse(TK.str));break; case "Name" : EvalStack[ptrEvalStack]=new NameData(TK.str);break; default : EvalStack[ptrEvalStack]=new NameData("",0.0); //MessageBox.Show("未だサポートしていません"+TK.operation); break; } ptrEvalStack++; private void pushEvalStack(NameData NM) // 変数名のPush { EvalStack[ptrEvalStack]=NM; private void Eval_dimStart(String S) // dim 文の開始 { EvalStack[ptrEvalStack]=new NameData(S); EvalStack[ptrEvalStack].Type="*dimStart"; private void Eval_Array_gen(string nameDT,NameData[] P,int N,string S) // 配列生成 { if(N<0) NameTable[ptrNameTable++]=new NameData(nameDT+"("+S+")"); else for(int i=1;i<=P[N].Val;i++)Eval_Array_gen(nameDT,P,N-1,S +","+i.ToString());

実行用メソッド② private void Eval_dim() // dim文の実行 { NameData[] P =new NameData[200]; NameData P1=popEvalStack(); if(P1.Type=="=*dimStart") NameTable[ptrNameTable++]=new NameData(P1.Name); else { int numArg=0; while(ptrEvalStack>=0 && P1.Type!="ARGEND"){ P[numArg++]=P1; P1 =popEvalStack();} P1=popEvalStack(); if(P1.Type!="*dimStart") MessageBox.Show("**System Error(Dim文)"); { int N=numArg-1; if( N>=0) for(int i=0;i<=P[N].Val-1;i++)Eval_Array_gen(P1.Name,P,N-1,i.ToString()); } } } private void Eval_Arg() // 引数終了 { EvalStack[ptrEvalStack]=new NameData("ARGEND"); EvalStack[ptrEvalStack].Type="ARGEND"; ptrEvalStack++; } private NameData popEvalStack() // ポップ:ただし,初期値はUndefinedとする。 { NameData P=new NameData("$$Undefined$$"); if(ptrEvalStack>0) { ptrEvalStack--; P=EvalStack[ptrEvalStack]; return P;

実行用メソッド③ private NameData Eval(NameData NM) // 変数値を求める { switch (NM.Type) { case "String": return NM; case "Number": return NM; case "Refer" : return Eval(NameTable[(int)NM.Val]); default : if(NM.Name=="$$Undefined$$") return new NameData("",0.0); NameTable[ptrNameTable]=NM; // 変数名テーブルの探索 int ID=-1; for(int i=ptrNameTable-1;i>=0;i--) if(NameTable[i].Name==NM.Name){ ID=i;break;} if(ID<0) // 変数名テーブルになければ変数を登録する { NameTable[ptrNameTable]=NM; ptrNameTable++; return new NameData(NM.Name,0.0); } else   // 変数名スコープでReferなら上位を参照 { while (NameTable[ID].Type=="Refer") ID=(int)NameTable[ID].Val; return NameTable[ID];

実行用メソッド④ private void Eval_add() { NameData P2=Eval(popEvalStack()); NameData P1=Eval(popEvalStack()); if(P1.Type=="Number" && P2.Type=="Number") pushEvalStack(new NameData("",P1.Val + P2.Val)); else if(P1.Type=="String" && P2.Type=="String") pushEvalStack(new NameData("",P1.Text + P2.Text)); else if(P1.Type=="String" && P2.Type=="Number") pushEvalStack(new NameData("",P1.Text + P2.Val.ToString())); else if(P1.Type=="Number" && P2.Type=="String") pushEvalStack(new NameData("",P1.Val.ToString() + P2.Text)); else pushEvalStack(new NameData("",0)); } private void Eval_sub() pushEvalStack(new NameData("",P1.Val - P2.Val)); else pushEvalStack(new NameData("","計算できません")); private void Eval_mult() pushEvalStack(new NameData("",P1.Val * P2.Val)); private void Eval_dev() pushEvalStack(new NameData("",P1.Val / P2.Val));

実行用メソッド⑤ private void Eval_exp() { NameData P2=Eval(popEvalStack()); NameData P1=Eval(popEvalStack()); if(P1.Type=="Number" && P2.Type=="Number") pushEvalStack(new NameData("",Math.Pow(P1.Val,P2.Val))); else pushEvalStack(new NameData("","計算できません")); } private void Eval_mod() pushEvalStack(new NameData("",(long)(P1.Val) % (long)(P2.Val))); private void Eval_minus() { NameData P1=Eval(popEvalStack()); if(P1.Type=="Number") pushEvalStack(new NameData("",-P1.Val)); private void Eval_plus() if(P1.Type=="Number") pushEvalStack(new NameData("",P1.Val)); private void Eval_Boolean(bool R) // 論理値のプッシュ { if(R) pushEvalStack(new NameData("",-1)); else pushEvalStack(new NameData("",0));

実行用メソッド⑥ private void Eval_equal() { NameData P2=Eval(popEvalStack()); NameData P1=Eval(popEvalStack()); if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val == P2.Val); else if(P1.Type=="String" && P2.Type=="String" ) Eval_Boolean(string.Compare(P1.Text, P2.Text)==0); else Eval_Boolean(false); } private void Eval_not_equal() if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val != P2.Val); Eval_Boolean(string.Compare(P1.Text, P2.Text)!=0); else Eval_Boolean(true); private void Eval_greater_than() if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val > P2.Val); Eval_Boolean(string.Compare(P1.Text, P2.Text)>0); else pushEvalStack(new NameData("","計算できません")); private void Eval_greater_than_equal() if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val >= P2.Val); Eval_Boolean(string.Compare(P1.Text, P2.Text)>=0);

実行用メソッド⑦ private void Eval_less_than() { NameData P2=Eval(popEvalStack()); NameData P1=Eval(popEvalStack()); if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val < P2.Val); else if(P1.Type=="String" && P2.Type=="String" ) Eval_Boolean(string.Compare(P1.Text, P2.Text)<0); else pushEvalStack(new NameData("","計算できません")); } private void Eval_less_than_equal() if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean(P1.Val <= P2.Val); Eval_Boolean(string.Compare(P1.Text, P2.Text)<=0); private void Eval_or() if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean((P1.Val !=0) || (P2.Val !=0)); private void Eval_and() Eval_Boolean((P1.Val !=0) && (P2.Val !=0));

実行用メソッド⑧ private void Eval_exclusive_or() { NameData P2=Eval(popEvalStack()); NameData P1=Eval(popEvalStack()); if (P1.Type=="Number" && P2.Type=="Number" ) Eval_Boolean((P1.Val !=0) ^ (P2.Val !=0)); else pushEvalStack(new NameData("","計算できません")); } private void Eval_not() { NameData P1=Eval(popEvalStack()); if (P1.Type=="Number" ) Eval_Boolean(!(P1.Val !=0)); private int Eval_set_search(NameData P) // 代入用変数名テーブルの探索 { for(int i=ptrNameTable-1;i>=0;i--) if(NameTable[i].Name==P.Name) return i; return -1; private int Eval_set_pointer(NameData P) // 代入すべき変数名の探索(Referを考慮) { int ID=Eval_set_search(P); if(ID>=0) { while(NameTable[ID].Type=="Refer") { if(checkBox1.Checked) MessageBox.Show(NameTable[ID].Name +" Type=" + NameTable[ID].Type +" Val=" +NameTable[ID].Val); ID=(int)(NameTable[ID].Val); if(checkBox1.Checked) else{ NameTable[ptrNameTable]=P;ID=ptrNameTable++;}   return ID;

実行用メソッド⑧ private void Eval_set() // 代入処理 { NameData P2=Eval(popEvalStack()); NameData P1=popEvalStack(); int i=Eval_set_pointer(P1); if(checkBox1.Checked) MessageBox.Show("Set ("+i+") Name=" + NameTable[i].Name + " Type=" + NameTable[i].Type + " Val=" + NameTable[i].Val+ "\n Assign Type” + P2.Type+ " Val=” + P2.Val+ " Text=\"” +P2.Text + "\""); NameTable[i].Text=P2.Text; NameTable[i].Type=P2.Type; NameTable[i].Val =P2.Val; pushEvalStack(P2); } private void Eval_PPset() // 後置++ { NameData P1=popEvalStack(); pushEvalStack(Eval(P1)); NameTable[i].Val++; private void Eval_MMset() // 後置-- NameTable[i].Val--;

実行用メソッド⑨ private void Eval_AsignPset() // += { NameData P2=Eval(popEvalStack()); NameData P1=popEvalStack(); int i=Eval_set_pointer(P1); if(NameTable[i].Type=="Number" && P2.Type=="Number") NameTable[i].Val += P2.Val; else if(NameTable[i].Type=="Number" && P2.Type=="String") { NameTable[i].Type= "String"; NameTable[i].Text= NameTable[i].Val.ToString() + P2.Text; } else if(NameTable[i].Type=="String" && P2.Type=="Number") NameTable[i].Text= NameTable[i].Text + P2.Val; else NameTable[i].Text= NameTable[i].Text + P2.Text; pushEvalStack(Eval(P1));

実行用メソッド⑩ private void Eval_AsignMset() // -= { NameData P2=Eval(popEvalStack()); NameData P1=popEvalStack(); int i=Eval_set_pointer(P1); if(NameTable[i].Type=="Number" && P2.Type=="Number") NameTable[i].Val -= P2.Val; else MessageBox.Show("演算の型が異なります"); pushEvalStack(Eval(P1)); } private void Eval_AsignMultset() // *= if(NameTable[i].Type=="Number" && P2.Type=="Number") NameTable[i].Val *= P2.Val; private void Eval_AsignDivset() // /= if(NameTable[i].Type=="Number" && P2.Type=="Number") NameTable[i].Val /= P2.Val; private void Eval_BeforPPset() // 前置++ { NameData P1=popEvalStack(); NameTable[ptrNameTable]=P1; int i=Eval_set_pointer(P1); NameTable[i].Val++;

実行用メソッド⑪ private void Eval_BeforMMset() // 前置-- { NameData P1=popEvalStack(); NameTable[ptrNameTable]=P1; int i=Eval_set_pointer(P1); NameTable[i].Val--; pushEvalStack(Eval(P1)); } private NameData Eval_func(string S, double V, string T) // 関数定義 { NameData P1=new NameData(""); P1.Type=T; P1.Val=V; P1.Text=S; return P1; private void Eval_funCall(FunctionName FName) // 関数呼出し:シャドウバインディング { int prt=FName.ptr; string S=FName.name; int i; ProgStack[ptrProgStack++]=new NameData("*progStart",(double)nextIP); while(ptrEvalStack>0) // 実引数をPop,プログラムスタックにPush { NameData P1=popEvalStack(); if (P1.Type !="Number" && P1.Type !="String") i = Eval_set_pointer(P1); ProgStack[ptrProgStack++]=P1; nextIP=prt; // Return Addressの設定 if(checkBox1.Checked) MessageBox.Show( "Call Address="+nextIP.ToString()); int P=ptrNameTable; NameTable[ptrNameTable++]=new NameData("*function*",S); NameTable[P].Val=StatementNo;

実行用メソッド⑫ private void Eval_return() // 復帰処理 { NameData P1=Eval(popEvalStack()); ptrEvalStack=0; while(ptrProgStack>0) { NameData P2=ProgStack[--ptrProgStack]; if(P2.Name=="*progStart") { nextIP=(int)P2.Val; if(checkBox1.Checked) MessageBox.Show("Return Address="+nextIP); break; } pushEvalStack(P2); if(checkBox1.Checked) MessageBox.Show("ProgStack Value="+P2.Name); pushEvalStack(P1); if(checkBox1.Checked) MessageBox.Show("return Value="+P1.Val); while(ptrNameTable>0) // 変数名テーブルの復帰 { NameData P2=NameTable[--ptrNameTable]; if(P2.Name=="*function*") { StatementNo=(int)P2.Val; if(checkBox1.Checked) MessageBox.Show("Return Statement="+StatementNo.ToString());

実行用メソッド⑬ private void Eval_PStart() { ptrArg=numArg; if(checkBox1.Checked) MessageBox.Show(" Arg番号 " + ptrArg.ToString()); } private void Eval_Param(string Pname) // パラメータの設定 { int i,j; if( ptrArg<=0){ MessageBox.Show("引数の数が合いません.");return;} NameData P2=argData[--ptrArg]; i=ptrNameTable; NameTable[ptrNameTable++]=new NameData(Pname); switch (P2.Type) { case "Number": case "String":NameTable[i].Type=P2.Type; NameTable[i].Text=P2.Text; NameTable[i].Val=P2.Val; break; default: j=ptrNameTable-1; while (j>=0 && NameTable[j].Name !="*function*") j--; while (j>=0 && NameTable[j].Name !=P2.Name)j--; if (NameTable[j].Name !=P2.Name) { MessageBox.Show("変数"+P2.Name + "が見つかりません."); NameTable[i].Type="Number"; NameTable[i].Val=0; else { NameTable[i].Type="Refer"; NameTable[i].Val=j;} break; if(checkBox1.Checked) { string S="*Parameter ptrArg=" + ptrArg.ToString()+" 変数番号 " + i.ToString() + " 仮引数名 " +NameTable[i].Name + "\n型 " +NameTable[i].Type+ " Val=" +NameTable[i].Val +" Text=\"" +NameTable[i].Text+"\""; MessageBox.Show(S);

実行用メソッド⑭ private void Eval_func(string Fname) { NameData P1 =popEvalStack(); numArg=0; while(ptrEvalStack>0 && P1.Type!="ARGEND") {argData[numArg]=P1; numArg++; P1 =popEvalStack();} string S=""; double V=0.0; string T="Number"; FunctionNameTable[numberOfFunction].name=Fname; int i=0; while(FunctionNameTable[i].name!=Fname)i++; if(i!=numberOfFunction) Eval_funCall(FunctionNameTable[i]); else { switch (Fname) { case "sin" : P1=Eval_func(S,Math.Sin(Eval(argData[0]).Val),T);break; case "cos" : P1=Eval_func(S,Math.Cos(Eval(argData[0]).Val),T);break; case "tan" : P1=Eval_func(S,Math.Tan(Eval(argData[0]).Val),T);break; case "abs" : P1=Eval_func(S,Math.Abs(Eval(argData[0]).Val),T);break; case "ToString" : P1=Eval_func(Eval(argData[0]).Val.ToString(),V,"String");break; case "MsgBox" : P1=Eval(argData[0]); if(P1.Type=="Number") S=P1.Val.ToString(); else S=P1.Text; MessageBox.Show(S); P1=Eval_func(S,0,"String");break; default    : NameData PX=Eval(argData[numArg-1]); S=Fname +"("+PX.Val.ToString(); for(i=numArg-2;i>=0;i--) {PX=Eval(argData[i]); S += ","+PX.Val.ToString();} S += ")"; i=Eval_set_pointer(new NameData(S)); P1=Eval(NameTable[i]); break; } pushEvalStack(P1); } }

実行用メソッド⑮ private void Eval_Display_Result(int ProgramCounter) { listBox3.Items.Clear(); string S="**PC = " + ProgramCounter.ToString()+ " StNo = " + StatementNo.ToString(); listBox3.Items.Add(S); listBox3.Items.Add(""); for(int i=0;i<ptrNameTable;i++) { S=NameTable[i].Name+ "\t" + NameTable[i].Type + " :\t" ; if(NameTable[i].Type=="String") S += "\"" + NameTable[i].Text +"\""; else S += NameTable[i].Val.ToString(); listBox3.Items.Add(S); } listBox3.Items.Add(""); listBox3.Items.Add("関数名"); for(int i=0;i<numberOfFunction;i++) { S=FunctionNameTable[i].name+ "\t" + FunctionNameTable[i].ptr; listBox3.Items.Add(""); listBox3.Items.Add("プログラムスタック ("+ptrProgStack+")"); for(int i=ptrProgStack-1;i>=0;i--) { S="Name ="+ProgStack[i].Name+ " Type=" +ProgStack[i].Type+  " Text=" +ProgStack[i].Text+ " Val=" + ProgStack[i].Val;