fork download
  1. import java.util.*; /* 文法7のパーサクラス */
  2.  
  3. class Main {
  4. public static void main(String[] args) {
  5. Context ct = new Context("[0-9]+|\\+|\\-|\\*|\\/|\\(|\\)", args[0]);
  6. Exp s = new Exp();
  7. s.parse(ct);
  8. double i = s.exe();
  9. System.out.println(i);
  10. }
  11. }
  12.  
  13. class Context {
  14. String token;
  15. String test;
  16. String exp;
  17. int index = 0;
  18.  
  19. Context(String test, String exp) {
  20. this.test = test;
  21. this.exp = exp;
  22. this.nextToken();
  23. }
  24.  
  25. boolean match(String s) {
  26. if (token == null) {
  27. return token == s;
  28. } else {
  29. return token.equals(s);
  30. }
  31. }
  32.  
  33. void nextToken() {
  34. char c = 0;
  35. while (index < exp.length()) {
  36. c = exp.charAt(index);
  37. if (c != ' ') {
  38. break;
  39. }
  40. index++;
  41. }
  42.  
  43. if (exp.length() <= index) {
  44. token = null;
  45. return;
  46. }
  47.  
  48. if (isNum(c)) {
  49. StringBuilder b = new StringBuilder();
  50. b.append(c);
  51. index++;
  52. while (index < exp.length()) {
  53. c = exp.charAt(index);
  54. if (c == ' ') {
  55. index++;
  56. } else if (!isNum(c)) {
  57. break;
  58. } else {
  59. b.append(c);
  60. index++;
  61. }
  62. }
  63. token = b.toString();
  64. } else {
  65. token = String.valueOf(c);
  66. index++;
  67. }
  68. if (!token.matches(test)) {
  69. throw new RuntimeException("Invalid Expression");
  70. }
  71. }
  72.  
  73. boolean isNum(char c) {
  74. return -1 < "0123456789".indexOf(c);
  75. }
  76.  
  77. String currentToken() {
  78. return token;
  79. }
  80. }
  81.  
  82. abstract class Node { //parse, exeメソッドは全クラスに必須なのでabstractクラスで宣言
  83. public abstract void parse(Context ct);
  84. public abstract double exe();
  85. }
  86.  
  87. // Exp -> term Tail1*
  88. class Exp extends Node {
  89. private Term term; //Termオブジェクトを指す変数
  90. private Tail1 tail1; //Tail1オブジェクトを指す変数
  91. private ArrayList <Tail1> al = new ArrayList<Tail1>(); //Tail1オブジェクトの格納用
  92. public void parse(Context ct) {
  93. (term = new Term()).parse(ct); //Termオブジェクト作成&解析指示
  94. while (ct.match("+") || ct.match("-")) { //加算or引き算の続く限りTail1を作る
  95. (tail1 = new Tail1()).parse(ct); //Tail1オブジェクト生成&解析指示
  96. al.add(tail1); //Tail1オブジェクトをalに格納
  97. }
  98. }
  99. public double exe() {
  100. double value = term.exe();
  101. for (Tail1 tail : al) {
  102. value += tail.exe();
  103. }
  104. return value;
  105. }
  106. }
  107.  
  108. // Tail1 -> + Term | - Term
  109. class Tail1 extends Node {
  110. private String op; //加算か減算かを記録する変数
  111. private Term term; //Termオブジェクトを指す変数
  112. public void parse(Context ct) {
  113. if (ct.match("+") || ct.match("-")) { //加算or減算の確認
  114. op = ct.currentToken(); //加算か減算かを記録
  115. ct.nextToken(); //次のトークンを読む
  116. (term = new Term()).parse(ct); //Termオブジェクト作成&解析指示
  117. } else { //'+'か'-'以外の記号で始まっていた場合
  118. System.out.println("Tail1:先頭に '+'か'-'がありません");
  119. System.exit(0); //終了
  120. }
  121. }
  122. public double exe() {
  123. if ("+".equals(op)) {
  124. return term.exe();
  125. } else {
  126. return -term.exe();
  127. }
  128. }
  129. }
  130. // Term -> Fac Tail2*
  131. class Term extends Node {
  132. private Fac fac; //Facオブジェクトを指す変数
  133. private Tail2 tail2; //Tail2オブジェクトを指す変数
  134. private ArrayList <Tail2> al = new ArrayList<Tail2>(); //Tail2オブジェクトを任意個格納する
  135. //ためのオブジェクト
  136. public void parse(Context ct) {
  137. (fac = new Fac()).parse(ct); //Facオブジェクト作成&解析指示
  138. while (ct.match("*") || ct.match("/")) { //乗算or割り算の続く限りTail2を作る
  139. (tail2 = new Tail2()).parse(ct); //Tail2オブジェクト生成&解析指示
  140. al.add(tail2); //Tail2オブジェクトをalに格納
  141. }
  142. }
  143. public double exe() {
  144. double value = fac.exe();
  145. for (Tail2 tail : al) {
  146. value *= tail.exe();
  147. }
  148. return value;
  149. }
  150. }
  151. // Tail2 -> * fac | / fac
  152. class Tail2 extends Node {
  153. private String op; //乗算か割り算かを記録する変数
  154. private Fac fac; //Facオブジェクトを指す変数
  155. public void parse(Context ct) {
  156. if (ct.match("*") || ct.match("/")) {//乗算or割り算の確認
  157. op = ct.currentToken(); //乗算か割り算かを記録
  158. ct.nextToken(); //トークンを1つ読む
  159. (fac = new Fac()).parse(ct); //Facオブジェクトを作成
  160. } else { //'*'か'/'以外の記号で始まっていた場合
  161. System.out.println("Tail2:先頭に '*'か'/'がありません");
  162. System.exit(0); //終了
  163. }
  164. }
  165. public double exe() {
  166. if ("*".equals(op)) {
  167. return fac.exe();
  168. } else {
  169. return 1.0 / fac.exe();
  170. }
  171. }
  172. }
  173. // Fac -> num | ( Exp )
  174. class Fac extends Node {
  175. private int num; //numの値を格納する変数
  176. private Exp exp; //( Exp )の場合,Expオブジェクトを指す変数
  177.  
  178. public void parse(Context ct) {
  179. if (ct.currentToken() != null && ct.currentToken().matches("[0-9]+")) {//自然数?
  180. num = Integer.parseInt(ct.currentToken()); //数値に変換しnumに格納
  181. ct.nextToken(); //次のトークンに進む
  182. } else if (ct.match("(")) { //トークンが'('だったら( Exp )
  183. ct.nextToken(); //次のトークンを読む
  184. (exp = new Exp()).parse(ct); //Expオブジェクトを生成
  185. if (ct.match(")")) //閉じカッコがあれば次のトークンを読む
  186. ct.nextToken();
  187. else {//閉じカッコでなければエラー
  188. System.out.println("Fac:閉じカッコがありません");
  189. System.exit(0);
  190. }
  191. } else { //numでも(Exp)でもない場合
  192. System.out.println("Fac:numでも(Exp)でもありません");
  193. System.out.println(ct.currentToken());
  194. System.exit(0);
  195. }
  196. }
  197. public double exe() {
  198. if (exp == null) {
  199. return num;
  200. } else {
  201. return exp.exe();
  202. }
  203. }
  204. }
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty