#* A script to translate the "Brainf***" language into plain c. This version of the script uses a one to one compilation of commands. so ++++ will be translated into 4 "c" statements, which is not efficient. * Valid brainf commands >> ">" p++ "<" p-- "+" *p++ - *p-- "[]" while *p > 0 . putchar , getchar TESTING * translate a Brainf*** program to c, compile and execute ---- pep -f ../brainf.toclang.pss -i '.,,,' > test.c; gcc test.c -o test; ./test ,,,,f NOTES Other things to think about, include array bounds checking, and handling of EOF. This script demonstrates pep/nom parsing and translating one of the simplest possible formal languages. The script could be greatly reduced but some error messages are printed with line and character number. Hardly any parsing is required, just for "[" and "]" I put a line:char number message into the attribute for each [ or ], and then use that message if the brackets are unbalanced. This technique could be useful for other languages. This is because we dont need that tape-cell (token attribute) for anything else. HISTORY 30 july 2022 Made the script generate compilable c code and tested with some simple scripts. 14 july 2022 wrote this script. *# read; ">","<","+","-",",","." { ">" { clear; add "p++;"; } "<" { clear; add "p--;"; } "+" { clear; # do bounds checking here add "if ((p < data) || (p > (data+SIZE*sizeof(int)))) {\n"; add ' printf("data pointer out of bounds\\n"); \n'; add " exit(1);\n"; add "}\n"; add "(*p)++;"; } "-" { # also do bounds checking here clear; add "(*p)--;"; } "." { clear; add "putc(*p, stdout);"; } "," { clear; # also check for getc == EOF # which can also mean an error add "if (feof(stdin)) { exit(0); } \n"; add "if (*p == EOF) { exit(1); } \n"; add "*p = getc(stdin);"; } put; clear; add "com*"; push; .reparse } "[","]" { put; add "*"; push; add "unbalanced bracket '"; --; get; add "' "; add "near line:char "; lines; add ":"; chars; put; ++; clear; .reparse } # ignore any other character but parse as a dummy command # so that the ignored char will end up in the output. !"" { #* replace "\n" "\\n"; replace "\t" "\\t"; replace "\f" "\\f"; replace "\r" "\\r"; put; clear; add "// ignored character '"; get; add "'"; put; clear; add "com*"; push; *# clear; } parse> # for debugging, add a c-style comment add "// line "; lines; add " char "; chars; add ": "; print; clear; unstack; print; stack; add "\n"; print; clear; pop; pop; # brackets with nothing in them is really an error because # can create an infinite loop and does nothing anyway. "[*]*" { clear; add "Empty bracket '[]' "; add "near line:char "; lines; add ":"; chars; add "\n"; print; quit; } "com*com*","comset*com*" { clear; get; add "\n"; ++; get; --; put; clear; add "comset*"; push; .reparse } pop; "[*com*]*","[*comset*]*" { # indent the braced code clear; add " "; ++; get; replace "\n" "\n "; put; clear; add "while (*p > 0) {\n"; get; --; add "\n}"; put; clear; add "com*"; push; .reparse } (eof) { "com*","comset*" { clear; # indent the generated code add " "; get; replace "\n" "\n "; put; clear; add "/* Code translated from the 'Brainf***' esoteric language \n"; add " by the pep/nom parser with the script: \n"; add " bumble.sf.net/books/pars/eg/brainf.toclang.pss */\n\n"; add "#include \n"; add "#include \n"; add "#define SIZE 65000 \n"; add "int main(int argc, char *argv[]) {\n"; add " int data[SIZE];\n"; add " int* p = data;\n"; get; add "\n}\n"; print; quit; } "[*comset*","[*com*",B"[*[*" { # get the saved error message from the [ token cell clear; get; add "\n"; print; quit; } "comset*]*","com*]*",E"]*]*" { # get the saved error message from the ] token cell clear; ++; get; add "\n"; print; quit; } put; add " The 'Brainf' code didnt parse well: Legal Brainf commands are > increment pointer < decrement pointer + increment value at pointer - [ ] . , (optional command) '#' print state Everything else is ignored. The input parsed as tokens:\n "; print; clear; get; add "\n"; print; quit; } push; push; push;