fork(1) download
  1. import java.util.*;
  2. import java.lang.*;
  3. import java.io.*;
  4. import java.util.regex.*;
  5.  
  6. class Ideone
  7. {
  8. public static void main (String[] args) throws java.lang.Exception
  9. {
  10. try {
  11. Excutor excutor = new Excutor();
  12. String line;
  13. while ((line = in.readLine()) != null) {
  14. try {
  15. List<Token> tokens = Tokenizer.tokenize(line);
  16. if (excutor.doEditorCommand(tokens) < 0) {
  17. break;
  18. }
  19. } catch (SyntaxError er) {
  20. System.out.println(er);
  21. }
  22. }
  23. // System.out.println(excutor);
  24. } catch (Exception ex) {
  25. System.out.println(ex);
  26. }
  27.  
  28. }
  29. }
  30.  
  31. enum TokenType
  32. {
  33. INT, DBL, STR, NAME, SYMBL, SHARP, SEMICOLON,
  34. OP_BRKT, CL_BRKT, COMMA, COLON, UNKNOWN
  35. }
  36.  
  37. final class Token
  38. {
  39. final TokenType type;
  40. final String token;
  41. public Token(TokenType type, String token)
  42. {
  43. this.type = type;
  44. this.token = token;
  45. }
  46. public TokenType getType() { return type; }
  47. public String getToken() { return token; }
  48. @Override
  49. public String toString()
  50. {
  51. return "[" + type + " : " + token + "]";
  52. }
  53. }
  54.  
  55. class SyntaxError extends java.lang.Exception
  56. {
  57. public SyntaxError(String msg) { super(msg); }
  58. public SyntaxError(Throwable ex) { super(ex); }
  59. public SyntaxError(List<Token> tokens, int index)
  60. {
  61. super("token index(" + index + "): " + tokens.toString());
  62. }
  63. }
  64.  
  65. final class TokenError extends SyntaxError
  66. {
  67. public TokenError(String line) { super(line); }
  68. }
  69.  
  70. final class Tokenizer
  71. {
  72. private static Pattern p_space = Pattern.compile("^\\s+");
  73. private static Pattern p_int = Pattern.compile("^\\d+");
  74. private static Pattern p_dbl = Pattern.compile("^\\d*\\.\\d+");
  75. private static Pattern p_str = Pattern.compile("^\"(\"\"|[^\"])*\"");
  76. private static Pattern p_name = Pattern.compile("^[A-Za-z][A-Za-z0-9]*\\$?");
  77. private static Pattern p_symbl = Pattern.compile("^(>=|<=|<>|[=<>+\\*/-])");
  78.  
  79. public static List<Token> tokenize(String line) throws TokenError
  80. {
  81. List<Token> list = new ArrayList<Token>();
  82. Matcher m = null;
  83. TokenType type = null;
  84. String token = null;
  85. int offset = 0;
  86.  
  87. while (line.length() > 0) {
  88. if ((m = p_space.matcher(line)).lookingAt()) {
  89. line = line.substring(m.end());
  90. continue;
  91. } else if ((m = p_dbl.matcher(line)).lookingAt()) {
  92. type = TokenType.DBL;
  93. } else if ((m = p_int.matcher(line)).lookingAt()) {
  94. type = TokenType.INT;
  95. } else if ((m = p_str.matcher(line)).lookingAt()) {
  96. type = TokenType.STR;
  97. } else if ((m = p_name.matcher(line)).lookingAt()) {
  98. type = TokenType.NAME;
  99. } else if ((m = p_symbl.matcher(line)).lookingAt()) {
  100. type = TokenType.SYMBL;
  101. } else {
  102. m = null;
  103. offset = 1;
  104. if (line.startsWith(token = "(")) {
  105. type = TokenType.OP_BRKT;
  106. } else if (line.startsWith(token = ")")) {
  107. type = TokenType.CL_BRKT;
  108. } else if (line.startsWith(token = ":")) {
  109. type = TokenType.COLON;
  110. } else if (line.startsWith(token = ",")) {
  111. type = TokenType.COMMA;
  112. } else if (line.startsWith(token = "#")) {
  113. type = TokenType.SHARP;
  114. } else if (line.startsWith(token = ";")) {
  115. type = TokenType.SEMICOLON;
  116. } else {
  117. throw new TokenError(line);
  118. }
  119. }
  120. if (m != null) {
  121. token = m.group();
  122. if (TokenType.NAME.equals(type)) {
  123. token = token.toUpperCase();
  124. }
  125. offset = m.end();
  126. }
  127. list.add(new Token(type, token));
  128. line = line.substring(offset);
  129. }
  130. return list;
  131. }
  132. }
  133.  
  134. final class ExcuteError extends SyntaxError
  135. {
  136. public ExcuteError(Throwable ex) { super(ex); }
  137. public ExcuteError(String msg) { super(msg); }
  138. }
  139.  
  140. class VarArray<T>
  141. {
  142.  
  143. }
  144.  
  145. enum ResultType
  146. {
  147. INT, DBL, STR
  148. }
  149.  
  150. class Result
  151. {
  152. private int offset;
  153. private int intvalue = 0;
  154. private double dblvalue = 0;
  155. private String strvalue = null;
  156. private ResultType type;
  157.  
  158. public ResultType getType()
  159. {
  160. return type;
  161. }
  162.  
  163. public int getOffset()
  164. {
  165. return offset;
  166. }
  167.  
  168. public Number getNumValue()
  169. {
  170. if (ResultType.INT.equals(type)) {
  171. return Integer.valueOf(intvalue);
  172. } else if (ResultType.DBL.equals(type)) {
  173. return Double.valueOf(dblvalue);
  174. } else {
  175. return null;
  176. }
  177. }
  178. public String getStrValue()
  179. {
  180. return strvalue;
  181. }
  182. }
  183.  
  184. final class Excutor
  185. {
  186. private NavigableMap<Integer, List<Token>> program = new TreeMap<Integer, List<Token>>();
  187.  
  188. private Map<String, VarArray<String>> strarrs = new HashMap<String, VarArray<String>>();
  189. private Map<String, VarArray<Number>> numarrs = new HashMap<String, VarArray<Number>>();
  190. private Map<String, String> strvars = new HashMap<String, String>();
  191. private Map<String, Number> numvars = new HashMap<String, Number>();
  192.  
  193. private Integer programcounter = null;
  194. private Deque<Integer> programcounterstack = new ArrayDeque<Integer>();
  195.  
  196. private int arraybase = 0;
  197. private boolean jumpflag = false;
  198.  
  199. public Excutor() {}
  200.  
  201. private void printLine(Integer linenum, List<Token> tokens)
  202. {
  203. System.out.printf("%05d ", linenum.intValue());
  204. TokenType before = null, type;
  205. for (int i = 1; i < tokens.size(); i++) {
  206. Token token = tokens.get(i);
  207. type = token.getType();
  208. if (TokenType.NAME.equals(before)) {
  209. switch (type) {
  210. case NAME:
  211. case INT:
  212. case DBL:
  213. case SHARP:
  214. case STR:
  215. System.out.print(' ');
  216. break;
  217. default:
  218. break;
  219. }
  220. }
  221. System.out.print(tokens.get(i).getToken());
  222. before = type;
  223. }
  224. System.out.println();
  225. }
  226.  
  227. private Result calc(List<Token> tokens, int index) throws SyntaxError
  228. {
  229. return null;
  230. }
  231.  
  232. public int doEditorCommand(List<Token> tokens) throws SyntaxError
  233. {
  234. if (tokens == null || tokens.isEmpty()) {
  235. return 0;
  236. }
  237.  
  238. Token first = tokens.get(0);
  239. String token = first.getToken();
  240. TokenType type = first.getType();
  241.  
  242. if (TokenType.INT.equals(type)) {
  243. Integer tmpint = Integer.valueOf(token);
  244. if (tmpint.intValue() < 1) {
  245. throw new SyntaxError(token);
  246. }
  247. program.put(tmpint, tokens);
  248. return 0;
  249. } else if (TokenType.NAME.equals(type) == false) {
  250. throw new ExcuteError(token);
  251. }
  252. switch (token) {
  253. case "CONT": // プログラムの再開
  254. case "EXIT": // インタプリタの終了
  255. return -1;
  256. case "LIST": // プログラムの表示
  257. do_list(tokens);
  258. break;
  259. case "LOAD": // プログラムのロード
  260. case "NEW": // プログラムと変数の全消去
  261. case "RENUM": // プログラムの行番号再割り当て
  262. break;
  263. case "RUN": // プログラムの実行
  264. do_run(tokens);
  265. break;
  266. case "SAVE": // プログラムの保存
  267. break;
  268. default:
  269. excute(tokens, 0);
  270. break;
  271. }
  272. System.out.println("Ok");
  273. return 0;
  274. }
  275.  
  276. private void do_list(List<Token> tokens) throws SyntaxError
  277. {
  278. Integer start = null;
  279. Integer end = null;
  280. Token first, second, third;
  281. Map<Integer, List<Token>> list = null;
  282. try {
  283. switch (tokens.size()) {
  284. case 1:
  285. list = program;
  286. break;
  287. case 2:
  288. first = tokens.get(1);
  289. if (TokenType.INT.equals(first.getType()) == false) {
  290. throw new SyntaxError(tokens ,1);
  291. }
  292. start = Integer.valueOf(first.getToken());
  293. if (start.intValue() < 1) {
  294. throw new SyntaxError(tokens ,1);
  295. }
  296. list = program.tailMap(start);
  297. break;
  298. case 3:
  299. if ("-".equals(tokens.get(1).getToken()) == false) {
  300. throw new SyntaxError(tokens ,1);
  301. }
  302. second = tokens.get(2);
  303. if (TokenType.INT.equals(second.getType()) == false) {
  304. throw new SyntaxError(tokens ,2);
  305. }
  306. end = Integer.valueOf(second.getToken());
  307. if (end.intValue() < 1) {
  308. throw new SyntaxError(tokens ,2);
  309. }
  310. list = program.headMap(end, true);
  311. break;
  312. case 4:
  313. first = tokens.get(1);
  314. if (TokenType.INT.equals(first.getType()) == false) {
  315. throw new SyntaxError(tokens ,1);
  316. }
  317. start = Integer.valueOf(first.getToken());
  318. if (start.intValue() < 1) {
  319. throw new SyntaxError(tokens ,1);
  320. }
  321. if ("-".equals(tokens.get(2).getToken()) == false) {
  322. throw new SyntaxError(tokens ,2);
  323. }
  324. third = tokens.get(3);
  325. if (TokenType.INT.equals(third.getType()) == false) {
  326. throw new SyntaxError(tokens ,3);
  327. }
  328. end = Integer.valueOf(third.getToken());
  329. if (end.intValue() < 1) {
  330. throw new SyntaxError(tokens ,3);
  331. }
  332. list = program.subMap(start, true, end, true);
  333. break;
  334. default:
  335. throw new SyntaxError(tokens, 0);
  336. }
  337. } catch (SyntaxError er) {
  338. throw er;
  339. } catch (Exception ex) {
  340. throw new ExcuteError(ex);
  341. }
  342.  
  343. if (list == null) {
  344. return;
  345. }
  346.  
  347. for (Integer key: list.keySet()) {
  348. printLine(key, list.get(key));
  349. }
  350.  
  351. }
  352.  
  353. private void do_run(List<Token> tokens) throws SyntaxError
  354. {
  355. switch (tokens.size()) {
  356. case 1:
  357. programcounter = program.ceilingKey(Integer.valueOf(1));
  358. if (programcounter == null) {
  359. throw new SyntaxError("Program is not found");
  360. }
  361. break;
  362. case 2:
  363. Token first = tokens.get(1);
  364. if (TokenType.INT.equals(first.getType()) == false) {
  365. throw new SyntaxError("Illegal Argument");
  366. }
  367. programcounter = Integer.valueOf(first.getToken());
  368. if (programcounter.intValue() < 1) {
  369. throw new SyntaxError("Wrong Line Number");
  370. }
  371. if (program.containsKey(programcounter) == false) {
  372. throw new SyntaxError("Not found Line Number");
  373. }
  374. break;
  375. default:
  376. throw new SyntaxError("Illegal Arguments");
  377. }
  378.  
  379. List<Token> line = null;
  380. try {
  381. while (programcounter != null) {
  382. line = program.get(programcounter);
  383. excute(line, 1);
  384. if (jumpflag == false) {
  385. programcounter = program.higherKey(programcounter);
  386. } else {
  387. jumpflag = false;
  388. }
  389. }
  390. } catch (SyntaxError er) {
  391. System.out.println(line);
  392. throw er;
  393. }
  394.  
  395. }
  396.  
  397. private int excute(List<Token> tokens, int index) throws SyntaxError
  398. {
  399. if (index < 0 || index >= tokens.size()) {
  400. return tokens.size();
  401. }
  402. Token first = tokens.get(index);
  403. TokenType type = first.getType();
  404.  
  405. while (TokenType.COLON.equals(type)) {
  406. index++;
  407. if (index == tokens.size()) {
  408. return index;
  409. }
  410. first = tokens.get(index);
  411. type = first.getType();
  412. }
  413.  
  414. if (TokenType.NAME.equals(type) == false) {
  415. throw new SyntaxError(first.toString());
  416. }
  417. String cmd = first.getToken();
  418. int offset = index;
  419. switch (cmd) {
  420. case "BASE": // 配列の下限(0/1)の設定
  421. offset = cmd_base(tokens, index + 1);
  422. break;
  423. case "BREAK": // FORループの脱出
  424. case "DATA": // データの列挙
  425. case "DIM": // 配列変数の宣言
  426. case "ELSE": // IF文のELSE節の開始
  427. case "END": // プログラムの終了
  428. case "FILE": // ファイルの割り当て
  429. case "FOR": // 繰り返し
  430. break;
  431. case "GO": // GOTOの分割トークン
  432. if (index + 2 >= tokens.size()) {
  433. throw new SyntaxError(tokens, index);
  434. }
  435. if ("TO".equals(tokens.get(index + 1).getToken()) == false) {
  436. throw new SyntaxError(tokens, index);
  437. }
  438. offset = cmd_goto(tokens, index + 2);
  439. break;
  440. case "GOTO": // ジャンプ
  441. offset = cmd_goto(tokens, index + 1);
  442. break;
  443. case "GOSUB": // サブルーチンジャンプ
  444. offset = cmd_gosub(tokens, index + 1);
  445. break;
  446. case "IF": // 条件節
  447. case "INPUT": // キーボードからの値の入力
  448. break;
  449. case "LET": // 変数への代入
  450. offset = cmd_let(tokens, index + 1);
  451. break;
  452. case "NEXT": // FOR文の末端
  453. case "PRINT": // 画面へ値を出力
  454. break;
  455. case "REM": // コメント行
  456. offset = tokens.size();
  457. break;
  458. case "RESTORE": // データ・ファイルの読み込み位置のリセット
  459. break;
  460. case "RETURN": // サブルーチンからの脱出
  461. offset = cmd_return(tokens, index);
  462. break;
  463. case "STOP": // プログラムの中断
  464. break;
  465. default:
  466. offset = cmd_let(tokens, index);
  467. break;
  468. }
  469. return offset;
  470. }
  471.  
  472. @Override
  473. public String toString()
  474. {
  475. return program.toString().replaceAll("(\\d+=\\[\\[)", "\n$1");
  476. }
  477.  
  478. private int cmd_goto(List<Token> tokens, int index) throws SyntaxError
  479. {
  480. if (index >= tokens.size()) {
  481. throw new SyntaxError(tokens, index);
  482. }
  483. if (index + 1 < tokens.size()) {
  484. if (TokenType.COLON.equals(tokens.get(index + 1).getType()) == false) {
  485. throw new SyntaxError(tokens, index + 1);
  486. }
  487. }
  488. Token first = tokens.get(index);
  489. if (TokenType.INT.equals(first.getType()) == false) {
  490. throw new SyntaxError(tokens, index);
  491. }
  492. Integer next = Integer.valueOf(first.getToken());
  493. if (program.containsKey(next) == false) {
  494. throw new SyntaxError(tokens, index);
  495. }
  496. programcounter = next;
  497. jumpflag = true;
  498. return tokens.size();
  499. }
  500.  
  501. private int cmd_gosub(List<Token> tokens, int index) throws SyntaxError
  502. {
  503. if (index >= tokens.size()) {
  504. throw new SyntaxError(tokens, index);
  505. }
  506. if (index + 1 < tokens.size()) {
  507. if (TokenType.COLON.equals(tokens.get(index + 1).getType()) == false) {
  508. throw new SyntaxError(tokens, index + 1);
  509. }
  510. }
  511. Token first = tokens.get(index);
  512. if (TokenType.INT.equals(first.getType()) == false) {
  513. throw new SyntaxError(tokens, index);
  514. }
  515. Integer next = Integer.valueOf(first.getToken());
  516. if (program.containsKey(next) == false) {
  517. throw new SyntaxError(tokens, index);
  518. }
  519. try {
  520. programcounterstack.push(programcounter);
  521. programcounter = next;
  522. jumpflag = true;
  523. return tokens.size();
  524. } catch (Exception ex) {
  525. throw new ExcuteError(ex);
  526. }
  527. }
  528.  
  529. private int cmd_return(List<Token> tokens, int index) throws SyntaxError
  530. {
  531. if (index < tokens.size()) {
  532. if (TokenType.COLON.equals(tokens.get(index).getType()) == false) {
  533. throw new SyntaxError(tokens, index);
  534. }
  535. }
  536. try {
  537. Integer back = programcounterstack.pop();
  538. programcounter = program.higherKey(back);
  539. jumpflag = true;
  540. return tokens.size();
  541. } catch (Exception ex) {
  542. throw new ExcuteError(ex);
  543. }
  544. }
  545.  
  546.  
  547. private int cmd_base(List<Token> tokens, int index) throws SyntaxError
  548. {
  549. try {
  550. Token first = tokens.get(index);
  551. if (TokenType.INT.equals(first.getType()) == false) {
  552. throw new SyntaxError(tokens, index);
  553. }
  554. int tmpint = Integer.parseInt(first.getToken());
  555. if (tmpint != 0 && tmpint != 1) {
  556. throw new SyntaxError(tokens, index + 1);
  557. }
  558. arraybase = tmpint;
  559. return excute(tokens, index + 1);
  560. } catch (SyntaxError er) {
  561. throw er;
  562. } catch (Exception ex) {
  563. throw new ExcuteError(ex);
  564. }
  565. }
  566.  
  567. private int cmd_let(List<Token> tokens, int index) throws SyntaxError
  568. {
  569. try {
  570. Token first = tokens.get(index);
  571. String name = first.getToken();
  572. // if (checkKeyword(name)) // 予約語チェック
  573. // throw new SyntaxError("Wrong variable name: " + name);
  574. index++;
  575. if (name.lastIndexOf("$") > 0) {
  576. if (strarrs.containsKey(name)) {
  577. if (TokenType.OP_BRKT.equals(tokens.get(index).getType()) == false) {
  578. throw new SyntaxError(tokens, index);
  579. }
  580. } else {
  581. if ("=".equals(tokens.get(index).getToken()) == false) {
  582. throw new SyntaxError(tokens, index);
  583. }
  584. index++;
  585. // Result result = calc(tokens, index);
  586. // if (result.getType() != "STRING")
  587. // throw new ExcuteError();
  588. // offset = result.getOffset();
  589. // strvars.put(name, result.getStrValue());
  590. }
  591. } else {
  592. if (numarrs.containsKey(name)) {
  593. if (TokenType.OP_BRKT.equals(tokens.get(index).getType()) == false) {
  594. throw new SyntaxError(tokens, index);
  595. }
  596. } else {
  597. if ("=".equals(tokens.get(index).getToken()) == false) {
  598. throw new SyntaxError(tokens ,index);
  599. }
  600. // Result result = calc(tokens, index);
  601. // if (result.getType() != "NUMBER")
  602. // throw new ExcuteError();
  603. // offset = result.getOffset();
  604. // numvars.put(name, result.getNumValue());
  605. }
  606. }
  607. // return excute(tokens, index);
  608. return tokens.size();
  609. } catch (SyntaxError er) {
  610. throw er;
  611. } catch (Exception ex) {
  612. ex.printStackTrace();
  613. throw new ExcuteError(tokens.toString());
  614. }
  615.  
  616. }
  617.  
  618. }
Success #stdin #stdout 0.1s 380288KB
stdin
00010 LET J4=1
00030 PRINT
00100 BASE 0
00110 LET X=0
00120 LET J=0
00130 LET K=0
00140 X1=0
00150 LET X3=0
00160 LET J9=RND(CLK(J9))
00170 DIM C(7),C$(7),W(100),D(50,50),P(100),I$(100),B(100,6),B$(100)
00180 DIM E(100),F(100),X5(100),X6(100),X2(100),X4(100)
00190 LET G=INT(RND(0)*24+2)
00200 LET H=INT(RND(0)*24+2)
00210 FILE #1="DNG1"
00220 FILE #2="DNG2",#3="DNG3",#4="DNG4",#5="DNG5",#6="DNG6"
00230 RESTORE #4
00240 FILE #7="GMSTR"
00245 RESTORE #7
00250 RESTORE #1
00260 RESTORE #2
00261 RESTORE #3
00262 RESTORE #4
00263 RESTORE #5
00264 RESTORE #6
00270 DATA "STR","DEX","CON","CHAR","WIS","INT","GOLD"
list
run
stdout
00010 LET J4=1
00030 PRINT
00100 BASE 0
00110 LET X=0
00120 LET J=0
00130 LET K=0
00140 X1=0
00150 LET X3=0
00160 LET J9=RND(CLK(J9))
00170 DIM C(7),C$(7),W(100),D(50,50),P(100),I$(100),B(100,6),B$(100)
00180 DIM E(100),F(100),X5(100),X6(100),X2(100),X4(100)
00190 LET G=INT(RND(0)*24+2)
00200 LET H=INT(RND(0)*24+2)
00210 FILE #1="DNG1"
00220 FILE #2="DNG2",#3="DNG3",#4="DNG4",#5="DNG5",#6="DNG6"
00230 RESTORE #4
00240 FILE #7="GMSTR"
00245 RESTORE #7
00250 RESTORE #1
00260 RESTORE #2
00261 RESTORE #3
00262 RESTORE #4
00263 RESTORE #5
00264 RESTORE #6
00270 DATA "STR","DEX","CON","CHAR","WIS","INT","GOLD"
Ok
Ok