bf2pre.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* brainfuck to Prelude compiler. Public domain by Alex Smith 2006. */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. /*
  5. This is a brainfuck to Prelude compiler.
  6. Brainfuck commands
  7. + Increment the current cell.
  8. - Decrement the current cell.
  9. < Make the previous cell current.
  10. > Make the next cell current.
  11. [ If the current cell is 0, skip past the matching ].
  12. ] If the current cell isn't 0, skip back tothe matching [.
  13. , Input a character to the current cell.
  14. This implementation assumes 0 on EOF.
  15. . Output the character at the current cell.
  16. Any other character is a comment.
  17. Prelude commands
  18. + Pop two values, add them, and push the result.
  19. - Pop two values, subtract them, and push the result.
  20. Top value subtracted from the second in this implementation.
  21. # Pop a value and discard it.
  22. ( If the top value on the stack is zero, skip past the matching ).
  23. ) If the top value on the stack is nonzero, skip back past the matching (.
  24. ^ Push the top value from the stack of the voice above this one.
  25. v Push the top value from the stack of the voice below this one.
  26. This implementation won't generate these aiming outside the program.
  27. This implementation assumes these push 0 on an empty stack.
  28. ? Input a character and push it.
  29. This implementation assumes 0 on EOF.
  30. ! Pop a value and output it as a character.
  31. 0..9 Pushes the appropriate one-digit number.
  32. . NOP (all other unrecognized characters are also NOPs)
  33. \n*\n This sequence is ignored.
  34. \n End input for one voice, switch to next voice.
  35. */
  36. char* voice1;
  37. char* voice2;
  38. char* tp;
  39. int v1s, v2s, v1c, v2c;
  40. int c;
  41. int cc;
  42. int curvoice=1;
  43. char loopstack[120];
  44. char lsp=0;
  45. void resync(int tovoice)
  46. {
  47. int ns=max(v1c,v2c)+5;
  48. if(ns>v1s)
  49. {tp=realloc(voice1,ns); if(!tp) goto errhandle; voice1=tp; v1s=ns;}
  50. if(ns>v2s)
  51. {tp=realloc(voice2,ns); if(!tp) goto errhandle; voice2=tp; v2s=ns;}
  52. while(v1c<v2c) voice1[v1c++]='.';
  53. while(v2c<v1c) voice2[v2c++]='.';
  54. if(curvoice==1&&tovoice==2)
  55. {
  56. voice2[v2c++]='^';
  57. voice1[v1c++]='#';
  58. }
  59. if(curvoice==2&&tovoice==1)
  60. {
  61. voice1[v1c++]='v';
  62. voice2[v2c++]='#';
  63. }
  64. curvoice=tovoice;
  65. return;
  66. errhandle:
  67. free(voice1);
  68. free(voice2);
  69. fprintf(stderr,"Out of memory.\n");
  70. exit(EXIT_FAILURE);
  71. }
  72. int main(void)
  73. {
  74. /* This compiles from stdin to stdout. */
  75. voice1=malloc(8); v1s=8; v1c=0;
  76. if(!voice1)
  77. {
  78. fprintf(stderr,"Out of memory.\n");
  79. return EXIT_FAILURE;
  80. }
  81. voice2=malloc(8); v2s=8; v2c=0;
  82. if(!voice2)
  83. {
  84. free(voice1);
  85. fprintf(stderr,"Out of memory.\n");
  86. return EXIT_FAILURE;
  87. }
  88. while((c=getchar())!=EOF)
  89. {
  90. cc=0;
  91. while(c=='-'||c=='+')
  92. {
  93. if(c=='-') cc--;
  94. if(c=='+') cc++;
  95. if(cc==-9||cc==9) break;
  96. c=getchar();
  97. }
  98. if(cc)
  99. {
  100. if(curvoice==1)
  101. {
  102. if(v1s-v1c<3)
  103. {v1s*=2; tp=realloc(voice1,v1s); if(!tp) break; voice1=tp;}
  104. voice1[v1c++]=abs(cc)+'0';
  105. voice1[v1c++]=cc>0?'+':'-';
  106. }
  107. else
  108. {
  109. if(v2s-v2c<3)
  110. {v2s*=2; tp=realloc(voice2,v2s); if(!tp) break; voice2=tp;}
  111. voice2[v2c++]=abs(cc)+'0';
  112. voice2[v2c++]=cc>0?'+':'-';
  113. }
  114. }
  115. if(c=='>')
  116. {
  117. if(curvoice!=1) resync(1);
  118. curvoice=2; /* voice1's stack is 'lefter' than voice2's */
  119. }
  120. if(c=='<')
  121. {
  122. if(curvoice!=2) resync(2);
  123. curvoice=1; /* voice1's stack is 'lefter' than voice2's */
  124. }
  125. if(c==',')
  126. {
  127. resync(curvoice); /* leaves at least 2 chars breathing room */
  128. if(curvoice==1)
  129. {voice1[v1c++]='#'; voice1[v1c++]='?';}
  130. else
  131. {voice2[v2c++]='#'; voice2[v2c++]='?';}
  132. }
  133. if(c=='.')
  134. {
  135. resync(curvoice);
  136. if(curvoice==1)
  137. {voice1[v1c++]='!'; voice2[v2c++]='^';}
  138. else
  139. {voice2[v2c++]='!'; voice1[v1c++]='v';}
  140. curvoice=3-curvoice;
  141. }
  142. if(c=='[')
  143. {
  144. loopstack[lsp++]=curvoice;
  145. if(lsp==120)
  146. {
  147. fprintf(stderr,"Loops too deeply nested.\n");
  148. free(voice1);
  149. free(voice2);
  150. return EXIT_FAILURE;
  151. }
  152. resync(curvoice);
  153. if(curvoice==1)
  154. {voice1[v1c++]='('; voice2[v2c++]='.';}
  155. else
  156. {voice2[v2c++]='('; voice1[v1c++]='.';}
  157. }
  158. if(c==']')
  159. {
  160. resync(loopstack[--lsp]);
  161. if(curvoice==1)
  162. {voice1[v1c++]=')'; voice2[v2c++]='.';}
  163. else
  164. {voice2[v2c++]=')'; voice1[v1c++]='.';}
  165. }
  166. }
  167. if(c!=EOF)
  168. {
  169. fprintf(stderr,"Out of memory.\n");
  170. free(voice1);
  171. free(voice2);
  172. return EXIT_FAILURE;
  173. }
  174. resync(curvoice); /* make both voices the same length */
  175. voice1[v1c]=0; voice2[v2c]=0;
  176. printf("%s\n%s\n",voice1,voice2);
  177. free(voice1);
  178. free(voice2);
  179. return EXIT_SUCCESS;
  180. }