前提・実現したいこと
Unityを使ってコンパイラのようなものを作成しており、
利用者がプログラムを入力できるようにしている。
その際に、文字をひとつずつ読み取り、四則演算を行って
計算をすることができています。
BNF法を利用して計算をしています。
発生している問題・エラーメッセージ
このままだと、すべてがint型でしか計算ができなくなってしまうので、キャストや
floatなど別の型での計算結果がおかしくなってしまうという点です。
これを解決するためにfloatやdoubleなどの計算を別途用意していたのですが、
もっと別の計算方法があるのでは?と思っておりますが、思いつきません。
BNF法を利用して、普通のコンパイラのような計算はできないでしょうか。
##該当するプログラム
C#
1 2public class INT_Arithmetic 3{ 4 static int nowIndex = 0; 5 6 static List<string> substList; 7 8 static public string Check(List<string> list) 9 { 10 substList = list; 11 nowIndex = 0; 12 return eval1().ToString(); 13 } 14 15 static int eval1() 16 { 17 var value = eval2(); 18 while (true) 19 { 20 if (nowIndex == substList.Count) 21 { 22 return value; 23 } 24 if (substList[nowIndex] == "+") 25 { 26 nowIndex++; 27 value += eval2(); 28 } 29 else if (substList[nowIndex] == "-") 30 { 31 nowIndex++; 32 value -= eval2(); 33 } 34 else 35 break; 36 } 37 return value; 38 } 39 40 static int eval2() 41 { 42 var value = eval3(); 43 if (nowIndex == substList.Count) 44 { 45 return value; 46 } 47 if (substList[nowIndex] == "*") 48 { 49 nowIndex++; 50 value *= eval3(); 51 } 52 else if (substList[nowIndex] == "/") 53 { 54 nowIndex++; 55 value /= eval3(); 56 } 57 else if (substList[nowIndex] == "%") 58 { 59 nowIndex++; 60 value %= eval3(); 61 } 62 return value; 63 } 64 65 static int eval3() 66 { 67 if (substList[nowIndex] == "(") 68 { 69 nowIndex++; 70 var value = eval1(); 71 if (substList[nowIndex] != ")") 72 { 73 // 閉じがない 74 } 75 nowIndex++; 76 return value; 77 } 78 else 79 return number(); 80 } 81 82 static int number() 83 { 84 int value = 0; 85 double deciValue = 0.0f; 86 bool plasFlag = true; // falseはマイナス 87 bool decimalFlag = false; 88 int decCount = 10; 89 // 無限ループさせる 90 while (true) 91 { 92 if (substList.Count > nowIndex) 93 { 94 // 数値だった場合 95 if (int.TryParse(substList[nowIndex], out int result)) 96 { 97 // 小数点対応 98 if (decimalFlag) 99 { 100 deciValue = deciValue + (result / (double)decCount); 101 decCount *= 10; 102 nowIndex++; 103 continue; 104 } 105 else 106 { 107 value = result; 108 } 109 if (nowIndex < substList.Count - 1) 110 // 次の値が、小数点だったら 111 if (substList[nowIndex + 1] == ".") 112 { 113 decimalFlag = true; 114 nowIndex += 2; 115 continue; 116 } 117 break; 118 } 119 else 120 { 121 if (decimalFlag) 122 { 123 return (int)value; 124 } 125 // 数字ではないので、変数 126 // すでに定義されている変数なのか 127 object sv = DataTable.GetVariableValueData(substList[nowIndex]); 128 if (sv != null) 129 { 130 value = (int)sv; 131 break; 132 } 133 else 134 { 135 // マイナス・プラスの符号の可能性があり 136 switch (substList[nowIndex]) 137 { 138 case "+": 139 plasFlag = true; 140 break; 141 case "-": 142 plasFlag = false; 143 break; 144 default: 145 //エラー 146 break; 147 } 148 nowIndex++; 149 } 150 } 151 } 152 else 153 { 154 return value; 155 } 156 } 157 nowIndex++; 158 if (!plasFlag) 159 { 160 value *= -1; 161 } 162 return value; 163 } 164}
補足情報(FW/ツールのバージョンなど)
visualStudio 2019
unity 2020.2.2f
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/26 02:20
2021/05/26 04:25