fork download
  1. /*
  2.  * スタックマシン?になっていればいいのだけれど・・・
  3.  *
  4.  * 1行目:
  5.  * 使う変数名列挙
  6.  * 変数名はアルファベット(A-Z)1文字で定義される
  7.  * (大文字小文字は区別されない、重複定義は許されない)
  8.  * アルファベット以外の文字は無視される
  9.  * 2行目以降:
  10.  * 変数への代入式 or 変数出力コマンド を 1行単位で書く
  11.  * 変数代入式は 変数名= で開始される
  12.  * 代入式右辺は 整数0-9 変数名A-Z 演算子*+-/ で構成され
  13.  * 上記以外の文字は許されない
  14.  * 編集出力コマンドは @変数名 で記述される
  15.  */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19.  
  20. /*
  21.  * 命令コード
  22.  *
  23.  * POP1 ... 1回目のpopで得られる値
  24.  * POP2 ... 2回目のpopで得られる値
  25.  */
  26. #define CMD_END (0) /* プログラムの終わり */
  27. #define CMD_PUSH (1) /* 次のコードを値としてpushする */
  28. #define CMD_LOAD (2) /* POP1のアドレスの変数の値をpushする */
  29. #define CMD_PRINT (3) /* POP1の値を出力する */
  30. #define CMD_ADD (4) /* POP2+POP1の結果をpushする */
  31. #define CMD_SUB (5) /* POP2-POP1の結果をpushする */
  32. #define CMD_MUL (6) /* POP2*POP1の結果をpushする */
  33. #define CMD_DIV (7) /* POP2/POP1の結果をpushする */
  34. #define CMD_STORE (8) /* POP1の値をPOP2のアドレスの変数へ格納する */
  35.  
  36. char cmd[][9] = {"END", "PUSH", "LOAD", "PRINT", "ADD",
  37. "SUB", "MUL", "DIV", "STORE"};
  38.  
  39. /*
  40.  * 構文解析遷移状態
  41.  */
  42. #define TERM_DEF (0) /* 変数定義 */
  43. #define TERM_TOP (1) /* 行頭 */
  44. #define TERM_PRT (2) /* 出力変数名の読み込み */
  45. #define TERM_SET (3) /* 代入文字=の読み込み */
  46. #define TERM_NUM (4) /* 数字の読み込み */
  47. #define TERM_SYB (5) /* 演算子の読み込み */
  48. #define TERM_EXP (6) /* 式の開始の読み込み */
  49. #define TERM_LF (99) /* 行末文字の読み込み*/
  50.  
  51. /*
  52.  * プログラム終了コード
  53.  */
  54. #define EXST_SUCCESS (0) /* 成功 */
  55. #define EXST_RTERR (1) /* 実行時エラー */
  56. #define EXST_NFEND (2) /* 終了命令なくプログラムの終了 */
  57.  
  58. #define SYNTAX_ERR (0)
  59.  
  60. int func1(FILE*,int[]); /* ソースコードをコンパイルする */
  61. void func2(int[], int); /* コンパイルされたコードを出力する */
  62. int func3(int[], int); /* コンパイルされたコードを実行する */
  63.  
  64. int main(void)
  65. {
  66. int p[1000] = {0};
  67. int c, r;
  68.  
  69. c = func1(stdin, p);
  70.  
  71. if (c == SYNTAX_ERR)
  72. {
  73. printf("Syntax Error\n");
  74. return 0;
  75. }
  76. printf("--Result--\n");
  77. r = func3(p, c);
  78. printf("--Exit Status--\n");
  79. switch (r)
  80. {
  81. case EXST_SUCCESS:
  82. {
  83. printf("Success\n");
  84. break;
  85. }
  86. case EXST_RTERR:
  87. {
  88. printf("Runtime Error\n");
  89. break;
  90. }
  91. case EXST_NFEND:
  92. {
  93. printf("Not found END command\n");
  94. break;
  95. }
  96. }
  97. printf("--Program Code--\n");
  98. func2(p, c);
  99.  
  100. return 0;
  101. }
  102.  
  103. int func1(FILE *file, int p[])
  104. {
  105. int w[100];
  106. int v[30] = {0};
  107. int c, i = 0, bi = 0, j, wi = 0;
  108. int t = TERM_DEF;
  109. int vr = 0, nm;
  110. while ((c = getc(file)) != EOF)
  111. {
  112. switch (t)
  113. {
  114. case TERM_DEF:
  115. {
  116. if (c == '\n')
  117. {
  118. if (i == 0)
  119. {
  120. printf("term: %d\n", t);
  121. return SYNTAX_ERR;
  122. }
  123. p[bi++] = i;
  124. for (j = 0; j < i; j++)
  125. {
  126. p[bi++] = 0;
  127. }
  128. t = TERM_TOP;
  129. }
  130. else if (isalpha(c))
  131. {
  132. vr = toupper(c) - 'A';
  133. if (v[vr] != 0)
  134. {
  135. printf("term: %d, %c\n", t, c);
  136. return SYNTAX_ERR;
  137. }
  138. v[vr] = ++i;
  139. }
  140. break;
  141. }
  142. case TERM_TOP:
  143. {
  144. if (c == '@')
  145. {
  146. t = TERM_PRT;
  147. }
  148. else if (isalpha(c))
  149. {
  150. vr = toupper(c) - 'A';
  151. if (v[vr] == 0)
  152. {
  153. printf("term: %d, char '%c'\n", t, c);
  154. return SYNTAX_ERR;
  155. }
  156. p[bi++] = CMD_PUSH;
  157. p[bi++] = v[vr];
  158. t = TERM_SET;
  159. }
  160. else
  161. {
  162. printf("term: %d, char '%c'\n", t, c);
  163. return SYNTAX_ERR;
  164. }
  165. break;
  166. }
  167. case TERM_PRT:
  168. {
  169. if (isalpha(c))
  170. {
  171. vr = toupper(c) - 'A';
  172. if (v[vr] == 0)
  173. {
  174. printf("term: %d, char '%c'\n", t, c);
  175. return SYNTAX_ERR;
  176. }
  177. p[bi++] = CMD_PUSH;
  178. p[bi++] = v[vr];
  179. p[bi++] = CMD_LOAD;
  180. p[bi++] = CMD_PRINT;
  181. t = TERM_LF;
  182. }
  183. else
  184. {
  185. printf("term: %d, char '%c'\n", t, c);
  186. return SYNTAX_ERR;
  187. }
  188. break;
  189. }
  190. case TERM_SET:
  191. {
  192. if (c == '=')
  193. {
  194. t = TERM_EXP;
  195. }
  196. else
  197. {
  198. printf("term: %d, char '%c'\n", t, c);
  199. return SYNTAX_ERR;
  200. }
  201. break;
  202. }
  203. case TERM_EXP:
  204. {
  205. if (isalpha(c))
  206. {
  207. vr = toupper(c) - 'A';
  208. if (v[vr] == 0)
  209. {
  210. printf("term: %d, char '%c'\n", t, c);
  211. return SYNTAX_ERR;
  212. }
  213. p[bi++] = CMD_PUSH;
  214. p[bi++] = v[vr];
  215. p[bi++] = CMD_LOAD;
  216. t = TERM_SYB;
  217. }
  218. else if (isdigit(c))
  219. {
  220. nm = c - '0';
  221. t = TERM_NUM;
  222. }
  223. else
  224. {
  225. printf("term: %d, char '%c'\n", t, c);
  226. return SYNTAX_ERR;
  227. }
  228. break;
  229. }
  230. case TERM_SYB:
  231. {
  232. switch (c)
  233. {
  234. case '+':
  235. case '-':
  236. {
  237. while (wi > 0)
  238. {
  239. p[bi++] = w[wi--];
  240. }
  241. w[++wi] = c == '+' ? CMD_ADD : CMD_SUB;
  242. t = TERM_EXP;
  243. break;
  244. }
  245. case '*':
  246. case '/':
  247. {
  248. while (w[wi] == '*' || w[wi] == '/')
  249. {
  250. p[bi++] = w[wi--];
  251. }
  252. w[++wi] = c == '*' ? CMD_MUL : CMD_DIV;
  253. t = TERM_EXP;
  254. break;
  255. }
  256. case '\n':
  257. {
  258. while (wi > 0)
  259. {
  260. p[bi++] = w[wi--];
  261. }
  262. p[bi++] = CMD_STORE;
  263. t = TERM_TOP;
  264. break;
  265. }
  266. default:
  267. {
  268. printf("term: %d, char '%c'\n", t, c);
  269. return SYNTAX_ERR;
  270. }
  271. }
  272. break;
  273. }
  274. case TERM_NUM:
  275. {
  276. if (isdigit(c))
  277. {
  278. nm = nm * 10 + (c - '0');
  279. }
  280. else
  281. {
  282. p[bi++] = CMD_PUSH;
  283. p[bi++] = nm;
  284. switch (c)
  285. {
  286. case '+':
  287. case '-':
  288. {
  289. while (wi > 0)
  290. {
  291. p[bi++] = w[wi--];
  292. }
  293. w[++wi] = c == '+' ? CMD_ADD : CMD_SUB;
  294. t = TERM_EXP;
  295. break;
  296. }
  297. case '*':
  298. case '/':
  299. {
  300. while (w[wi] == '*' || w[wi] == '/')
  301. {
  302. p[bi++] = w[wi--];
  303. }
  304. w[++wi] = c == '*' ? CMD_MUL : CMD_DIV;
  305. t = TERM_EXP;
  306. break;
  307. }
  308. case '\n':
  309. {
  310. while (wi > 0)
  311. {
  312. p[bi++] = w[wi--];
  313. }
  314. p[bi++] = CMD_STORE;
  315. t = TERM_TOP;
  316. break;
  317. }
  318. default:
  319. {
  320. printf("term: %d, char '%c'\n", t, c);
  321. return SYNTAX_ERR;
  322. }
  323. }
  324. }
  325. break;
  326. }
  327. case TERM_LF:
  328. {
  329. if (c == '\n')
  330. {
  331. t = TERM_TOP;
  332. }
  333. else
  334. {
  335. printf("term: %d, char '%c'\n", t, c);
  336. return SYNTAX_ERR;
  337. }
  338. break;
  339. }
  340. }
  341.  
  342. }
  343.  
  344. switch (t)
  345. {
  346. case TERM_NUM:
  347. {
  348. p[bi++] = CMD_PUSH;
  349. p[bi++] = nm;
  350. }
  351. case TERM_SYB:
  352. {
  353. while (wi > 0)
  354. {
  355. p[bi++] = w[wi--];
  356. }
  357. break;
  358. }
  359. case TERM_LF:
  360. case TERM_TOP:
  361. {
  362. break;
  363. }
  364. default:
  365. {
  366. return SYNTAX_ERR;
  367. }
  368. }
  369.  
  370. p[bi++] = CMD_END;
  371.  
  372. return bi;
  373. }
  374.  
  375. void func2(int p[], int c)
  376. {
  377. int i;
  378. int t = 0;
  379. int n;
  380. n = p[0];
  381. printf("%03d VAR COUNT: %d\n", 0, n);
  382. for (i = 0; i < n; i++)
  383. {
  384. printf("%03d VAR AREA: %d\n", i + 1, i + 1);
  385. }
  386.  
  387. for (i = n + 1; i < c; i++)
  388. {
  389. if (t)
  390. {
  391. printf("%03d DATA: %d\n", i, p[i]);
  392. t = 0;
  393. }
  394. else
  395. {
  396. printf("%03d CMD: %s\n", i, cmd[p[i]]);
  397. if (p[i] == CMD_PUSH)
  398. {
  399. t = 1;
  400. }
  401. }
  402. }
  403. }
  404.  
  405. int func3(int p[], int c)
  406. {
  407. int s[1000];
  408. int si = 0;
  409. int i;
  410. for (i = p[0] + 1; i < c; i++)
  411. {
  412. switch (p[i])
  413. {
  414. case CMD_END:
  415. {
  416. return EXST_SUCCESS;
  417. }
  418. case CMD_PUSH:
  419. {
  420. s[++si] = p[++i];
  421. break;
  422. }
  423. case CMD_LOAD:
  424. {
  425. s[si] = p[s[si]];
  426. break;
  427. }
  428. case CMD_STORE:
  429. {
  430. p[s[si - 1]] = s[si];
  431. si -= 2;
  432. break;
  433. }
  434. case CMD_ADD:
  435. {
  436. s[si - 1] += s[si];
  437. si--;
  438. break;
  439. }
  440. case CMD_SUB:
  441. {
  442. s[si - 1] -= s[si];
  443. si--;
  444. break;
  445. }
  446. case CMD_MUL:
  447. {
  448. s[si - 1] *= s[si];
  449. si--;
  450. break;
  451. }
  452. case CMD_DIV:
  453. {
  454. s[si - 1] /= s[si];
  455. si--;
  456. break;
  457. }
  458. case CMD_PRINT:
  459. {
  460. printf("%d\n", s[si--]);
  461. break;
  462. }
  463. default:
  464. {
  465. return EXST_RTERR;
  466. }
  467. }
  468. }
  469. return EXST_NFEND;
  470. }
  471.  
Success #stdin #stdout 0s 2256KB
stdin
a,b,c,d
a=12
b=11
c=5
d=a*b-c/c+100
@a
@b
@c
@d
stdout
--Result--
12
11
5
231
--Exit Status--
Success
--Program Code--
000 VAR COUNT: 4
001 VAR AREA: 1
002 VAR AREA: 2
003 VAR AREA: 3
004 VAR AREA: 4
005 CMD: PUSH
006 DATA: 1
007 CMD: PUSH
008 DATA: 12
009 CMD: STORE
010 CMD: PUSH
011 DATA: 2
012 CMD: PUSH
013 DATA: 11
014 CMD: STORE
015 CMD: PUSH
016 DATA: 3
017 CMD: PUSH
018 DATA: 5
019 CMD: STORE
020 CMD: PUSH
021 DATA: 4
022 CMD: PUSH
023 DATA: 1
024 CMD: LOAD
025 CMD: PUSH
026 DATA: 2
027 CMD: LOAD
028 CMD: MUL
029 CMD: PUSH
030 DATA: 3
031 CMD: LOAD
032 CMD: PUSH
033 DATA: 3
034 CMD: LOAD
035 CMD: DIV
036 CMD: SUB
037 CMD: PUSH
038 DATA: 100
039 CMD: ADD
040 CMD: STORE
041 CMD: PUSH
042 DATA: 1
043 CMD: LOAD
044 CMD: PRINT
045 CMD: PUSH
046 DATA: 2
047 CMD: LOAD
048 CMD: PRINT
049 CMD: PUSH
050 DATA: 3
051 CMD: LOAD
052 CMD: PRINT
053 CMD: PUSH
054 DATA: 4
055 CMD: LOAD
056 CMD: PRINT
057 CMD: END