fork download
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. class Command
  5. {
  6. private static boolean lastReadNumber = false;
  7. private static boolean byteLeftOver = false;
  8. private static int leftOverByte = 0;
  9. public boolean available = true;
  10. private static final String PRINT = "print";
  11. private String deferString = null; // the defer clause, without enclosing parentheses
  12. private String againString = null; // the again clause, without enclosing parentheses
  13. private String actionString = null; // the command to be executed, without terminating semi-colon
  14. public int numToDo = 1;
  15.  
  16. public void setDeferString(String s)
  17. {
  18. deferString = s;
  19. }
  20.  
  21. public void setAgainString(String s)
  22. {
  23. againString = s;
  24. }
  25.  
  26. public void setActionString(String s)
  27. {
  28. actionString = s;
  29. }
  30.  
  31. public boolean execute(Integer lineNumber)
  32. {
  33. try
  34. {
  35. if (this.evaluateBoolean(deferString))
  36. return false;
  37. this.action();
  38. if (!this.evaluateBoolean(againString))
  39. WheneverCode.code.changeNumToDo(lineNumber, -1);
  40. }
  41. catch (SyntaxException e)
  42. {
  43. System.out.println("Syntax error detected at runtime in line numbered " + lineNumber.toString());
  44. System.out.println(e.getMessage() + "\n");
  45. System.exit(0);
  46. }
  47. return true;
  48. }
  49.  
  50. /*
  51.   * Evaluates the argument string as a boolean expression.
  52.   */
  53. private boolean evaluateBoolean(String s) throws SyntaxException
  54. // ******** HAVE TO IMPLEMENT UNARY NOT **********
  55. {
  56. if (s == null || s.equals("false"))
  57. return false;
  58. if (s.equals("true"))
  59. return true;
  60. if (WheneverCode.traceLevel > 3)
  61. System.out.println("[Boolean eval: " + s + " ]");
  62. // check for numerical comparisons
  63. int less = s.indexOf("<");
  64. int greater = s.indexOf(">");
  65. int equals = s.indexOf("==");
  66. int notequals = s.indexOf("!=");
  67. int i = -1;
  68. if (less >= 0 && (i < 0 || less < i))
  69. i = less;
  70. if (greater >= 0 && (i < 0 || greater < i))
  71. i = greater;
  72. if (equals >= 0 && (i < 0 || equals < i))
  73. i = equals;
  74. if (notequals >= 0 && (i < 0 || notequals < i))
  75. i = notequals;
  76. if (i >= 0) // we have a numerical comparison - evaluate it and substitute it into the string
  77. {
  78. int lside = Math.max(s.substring(0,i).lastIndexOf("&&"), s.substring(0,i).lastIndexOf("||"));
  79. int rside1 = s.indexOf("&&", i);
  80. int rside2 = s.indexOf("||", i);
  81. int rside = -1;
  82. if (rside1 >= 0 && rside2 >= 0)
  83. rside = Math.min(rside1, rside2);
  84. if (rside1 >= 0 && rside2 < 0)
  85. rside = rside1;
  86. if (rside1 < 0 && rside2 >= 0)
  87. rside = rside2;
  88. String lstring = "";
  89. String rstring = "";
  90. String lcomp;
  91. String rcomp;
  92. String op = s.substring(i,i+2);
  93. // extract left comparison operand and left boolean leftover string if necessary
  94. if (lside >= 0)
  95. {
  96. lside += 2;
  97. lstring = s.substring(0,lside);
  98. lcomp = s.substring(lside,i).trim();
  99. }
  100. else
  101. lcomp = s.substring(0,i).trim();
  102. // add different amount to index to extract right operand for different length operators
  103. if (op.equals("<=") || op.equals(">=") || op.equals("==") || op.equals("!="))
  104. i += 2;
  105. else // simple < or >
  106. i++;
  107. // extract right comparison operand and right boolean leftover string if necessary
  108. if (rside >= 0)
  109. {
  110. rstring = s.substring(rside);
  111. rcomp = s.substring(i,rside).trim();
  112. }
  113. else
  114. rcomp = s.substring(i).trim();
  115. boolean comp;
  116. if (op.equals("<="))
  117. comp = evaluateInteger(lcomp) <= evaluateInteger(rcomp);
  118. else if (op.equals(">="))
  119. comp = evaluateInteger(lcomp) >= evaluateInteger(rcomp);
  120. else if (op.equals("=="))
  121. comp = evaluateInteger(lcomp) == evaluateInteger(rcomp);
  122. else if (op.equals("!="))
  123. comp = evaluateInteger(lcomp) != evaluateInteger(rcomp);
  124. else if (op.charAt(0) == '<')
  125. comp = evaluateInteger(lcomp) < evaluateInteger(rcomp);
  126. else // >
  127. comp = evaluateInteger(lcomp) > evaluateInteger(rcomp);
  128. return evaluateBoolean(lstring + String.valueOf(comp) + rstring);
  129. }
  130. // check for or operator
  131. i = s.indexOf("||");
  132. if (i >= 0)
  133. return evaluateBoolean(s.substring(0,i).trim()) || evaluateBoolean(s.substring(i+2).trim());
  134. // we must have an and operator
  135. i = s.indexOf("&&");
  136. if (i >= 0)
  137. return evaluateBoolean(s.substring(0,i).trim()) && evaluateBoolean(s.substring(i+2).trim());
  138. // exhausted all boolean operations, must have an integer expression which is evaluated according to to-do list
  139. return WheneverCode.code.getN(evaluateInteger(s));
  140. }
  141.  
  142. /*
  143.   * Performs the action expression in the actionString.
  144.   */
  145. private void action() throws SyntaxException
  146. {
  147. if (actionString.indexOf(PRINT) == 0)
  148. doPrint(actionString.substring(PRINT.length()).trim());
  149. else
  150. doLines(actionString);
  151. return;
  152. }
  153.  
  154. /*
  155.   * Adds or subtracts lots of lines from the to-do list according to the specifications in the argument.
  156.   */
  157. private void doLines(String s) throws SyntaxException
  158. {
  159. StringTokenizer tok = new StringTokenizer(s, ",");
  160. while (tok.hasMoreTokens())
  161. doLine(tok.nextToken());
  162. }
  163.  
  164. /*
  165.   * Adds or subtracts a line from the to-do list according to the specifications in the argument.
  166.   */
  167. private void doLine(String s) throws SyntaxException
  168. {
  169. int numTimes = 1;
  170. int lineNumber = 0;
  171. int i;
  172. if ((i = s.indexOf("#")) >= 0)
  173. {
  174. numTimes = evaluateInteger(s.substring(i+1));
  175. lineNumber = evaluateInteger(s.substring(0,i));
  176. }
  177. else
  178. lineNumber = evaluateInteger(s);
  179. if (WheneverCode.traceLevel >= 2)
  180. System.out.println("[Adding line " + String.valueOf(lineNumber) + ", " + String.valueOf(numTimes) + " times]");
  181. WheneverCode.code.changeNumToDo(lineNumber, numTimes);
  182. }
  183.  
  184. /*
  185.   * Evaluates the argument string as an integer expression.
  186.   */
  187. private int evaluateInteger(String s) throws SyntaxException
  188. {
  189. try
  190. {
  191. return Integer.parseInt(s);
  192. }
  193. {
  194. if (WheneverCode.traceLevel > 4)
  195. {
  196. System.out.println("[passed in: " + s + "]");
  197. }
  198. int i, j;
  199. if ((i = s.indexOf("read()")) >= 0)
  200. {
  201. Integer readNumber = 0;
  202. try {
  203. int readByte = (byteLeftOver) ? leftOverByte : System.in.read();
  204. byteLeftOver = false;
  205. if (lastReadNumber)
  206. {
  207. // skip whitespace after a number
  208. while ((readByte == 10) || (readByte == 32) || (readByte == 13))
  209. {
  210. readByte = System.in.read();
  211. }
  212. }
  213. if (readByte >= 48 && readByte < 58)
  214. {
  215. // Are reading a number
  216. while (readByte >= 48 && readByte < 58)
  217. {
  218. readNumber = 10 * readNumber + (readByte - 48);
  219. readByte = System.in.read();
  220. }
  221. byteLeftOver = true;
  222. leftOverByte = readByte;
  223. lastReadNumber = true;
  224. }
  225. else
  226. {
  227. readNumber = readByte;
  228. lastReadNumber = false;
  229. }
  230. }
  231. catch (IOException ioe)
  232. {
  233. }
  234. return evaluateInteger(s.substring(0,i) + String.valueOf(readNumber) + s.substring(i + 6));
  235. }
  236. else if ((i = s.indexOf("N(")) >= 0)
  237. {
  238. j = i + 1;
  239. int depth = 1;
  240. try
  241. {
  242. while (depth > 0)
  243. {
  244. j++;
  245. if (s.charAt(j) == '(')
  246. depth++;
  247. if (s.charAt(j) == ')')
  248. depth--;
  249. }
  250. }
  251. {
  252. throw new SyntaxException("Mismatched parentheses in arithmetic expression function call");
  253. }
  254. if (WheneverCode.traceLevel > 3)
  255. {
  256. System.out.println("[N() argument: " + s.substring(i+2,j) + "]");
  257. System.out.println("[N() substituted: " + s.substring(0,i) + String.valueOf(WheneverCode.code.getNumToDo(evaluateInteger(s.substring(i+2,j)))) + s.substring(j+1) + "]");
  258. }
  259. return evaluateInteger(s.substring(0,i) + String.valueOf(WheneverCode.code.getNumToDo(evaluateInteger(s.substring(i+2,j)))) + s.substring(j+1));
  260. }
  261. else if ((i = s.indexOf("(")) >= 0)
  262. {
  263. j = i;
  264. int depth = 1;
  265. try
  266. {
  267. while (depth > 0)
  268. {
  269. j++;
  270. if (s.charAt(j) == '(')
  271. depth++;
  272. if (s.charAt(j) == ')')
  273. depth--;
  274. }
  275. }
  276. {
  277. throw new SyntaxException("Mismatched parentheses in arithmetic expression");
  278. }
  279. if (WheneverCode.traceLevel > 3)
  280. {
  281. System.out.println("[() argument: " + s.substring(i+1,j) + "]");
  282. System.out.println("[() substituted: " + s.substring(0,i) + String.valueOf(evaluateInteger(s.substring(i+1,j))) + s.substring(j+1) + "]");
  283. }
  284. return evaluateInteger(s.substring(0,i) + String.valueOf(evaluateInteger(s.substring(i+1,j))) + s.substring(j+1));
  285. }
  286. else if ((s.indexOf('+') >= 0) || (s.indexOf('_') >= 0)) // we have + and/or - signs
  287. {
  288. try
  289. {
  290. if (tok.nextToken() != StreamTokenizer.TT_NUMBER)
  291. throw new SyntaxException("Bad arithmetic expression (1)");
  292. String start = String.valueOf((int)tok.nval);
  293. tok.nextToken();
  294. while (((char)tok.ttype != '+') && ((char)tok.ttype != '_'))
  295. {
  296. if (tok.ttype == StreamTokenizer.TT_NUMBER)
  297. start += String.valueOf((int)tok.nval);
  298. else
  299. start += String.valueOf((char)tok.ttype);
  300. tok.nextToken();
  301. if (tok.ttype == StreamTokenizer.TT_EOF) // only unary minuses!
  302. return multiply(s);
  303. }
  304. int op = tok.ttype;
  305. String remainder = "";
  306. while (tok.nextToken() != StreamTokenizer.TT_EOF)
  307. {
  308. if (tok.ttype == StreamTokenizer.TT_NUMBER)
  309. remainder += String.valueOf((int)tok.nval);
  310. else if (tok.ttype > 0)
  311. remainder += String.valueOf((char)tok.ttype);
  312. else
  313. throw new SyntaxException("Bad arithmetic expression (3)");
  314. }
  315. if (WheneverCode.traceLevel > 3)
  316. System.out.println("[arguments: (" + start + ") " + String.valueOf((char)op) + " (" + remainder + ") ]");
  317. if ((char)op == '+')
  318. return evaluateInteger(start) + evaluateInteger(remainder);
  319. else
  320. return evaluateInteger(start) - evaluateInteger(remainder);
  321. }
  322. catch (IOException exc)
  323. {
  324. throw new SyntaxException("I/O exception reading arithmetic expression");
  325. }
  326. }
  327. else // we have * and/or / signs
  328. return multiply(s);
  329. }
  330. }
  331.  
  332. /*
  333.   * Evaluates the argument string as an integer expression.
  334.   * Argument string may only contain * and / binary operators and unary minuses.
  335.   */
  336. private int multiply(String s) throws SyntaxException
  337. {
  338. int i = s.indexOf("*");
  339. int j = s.indexOf("/");
  340. if (i >= 0 && (j < 0 || i < j))
  341. {
  342. if (WheneverCode.traceLevel > 3)
  343. System.out.println("[* arguments: " + s.substring(0,i).trim() + ", " + s.substring(i+1).trim() + "]");
  344. return evaluateInteger(s.substring(0,i).trim()) * evaluateInteger(s.substring(i+1).trim());
  345. }
  346. else
  347. {
  348. if (WheneverCode.traceLevel > 3)
  349. System.out.println("[/ arguments: " + s.substring(0,j).trim() + ", " + s.substring(j+1).trim() + "]");
  350. return (int)(evaluateInteger(s.substring(0,j).trim()) / evaluateInteger(s.substring(j+1).trim()));
  351. }
  352. }
  353.  
  354. /*
  355.   * Prints the String expression specified by the argument.
  356.   */
  357. private void doPrint(String s) throws SyntaxException
  358. {
  359. if (s.charAt(0) != '(' || s.charAt(s.length()-1) != ')')
  360. throw new SyntaxException("Print statement must be enclosed in parentheses");
  361. s = s.substring(1, s.length()-1).trim();
  362. //System.out.println(s);
  363. // construct the output string by concatenating items
  364. String out = "";
  365. while (s.length() > 0)
  366. {
  367. // if item begins with a string literal it begins with a double quote
  368. if (s.charAt(0) == '"')
  369. {
  370. // get index of closing double quote
  371. int i = s.indexOf('"', 1);
  372. if (i < 0) // make sure quote is closed
  373. throw new SyntaxException("String must be delimited by double quotes");
  374. // add string literal to output
  375. out += s.substring(1, i);
  376. // check if any more stuff needs to be added
  377. if (i+1 == s.length())
  378. s = ""; // entire output string is processed
  379. else
  380. { // there is more to be concatenated
  381. s = s.substring(i+1).trim();
  382. // check for concatenation operator
  383. if (s.charAt(0) != '+')
  384. throw new SyntaxException("Illegal string concatenation, + expected");
  385. // remove + sign
  386. s = s.substring(1).trim();
  387. }
  388. }
  389. else // item does not begin with a string literal
  390. {
  391. // get index of opening double quote
  392. int i = s.indexOf('"');
  393. if (i < 0)
  394. { // there are no more string literals - all stuff is an integer expression
  395. out += String.valueOf(evaluateInteger(s));
  396. s = "";
  397. }
  398. else
  399. { // there is a concatenated string literal
  400. // check for concatenation operator
  401. if (s.charAt(s.substring(0,i).trim().length()-1) != '+')
  402. throw new SyntaxException("Illegal string concatenation, + expected");
  403. out += evaluateInteger(s.substring(0,s.substring(0,i).trim().length()-1).trim());
  404. s = s.substring(i);
  405. }
  406. }
  407. }
  408. // print the output!
  409. System.out.println(out);
  410. }
  411. }
  412.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty