diff --git a/0-lang0py/lang0py.py b/0-lang0py/lang0py.py index f274d6c..d0fb409 100644 --- a/0-lang0py/lang0py.py +++ b/0-lang0py/lang0py.py @@ -43,6 +43,10 @@ def skipchar(char): assert char == peek(), (LINE, char, peek()) skip() +def emitln(data): + emit(data) + emit(eol) + def lexident(): word = '' while True: @@ -135,21 +139,21 @@ def parsestatif(indent): emit(' ' * indent) emit('if ') parseexprvarref() - emit(':\n') + emitln(':') skipchar(eol) parseblock(indent + 1) def parsestatforever(indent): emit(' ' * indent) - emit('while True:\n') + emitln('while True:') skipchar(eol) parseblock(indent + 1) def parsestatbreak(indent): emit(' ' * indent) - emit('break\n') + emitln('break') skipchar(eol) def parsestatreturn(indent): @@ -172,7 +176,7 @@ def parsestattrace(indent): emit(var_name) emit('", ') emit(var_name) - emit(')\n') + emitln(')') def parsestat(indent): call = lexident() @@ -227,7 +231,7 @@ def parsestat(indent): skipchar(eol) - emit(')\n') + emitln(')') def parseblock(indent): while True: @@ -267,71 +271,71 @@ def parsefunc(): # Ahead declaration skipchar('/') skipchar(eol) - emit("):\n") - emit(" pass # ahead declaration\n") - emit("\n") + emitln("):") + emitln(" pass # ahead declaration") + emit(eol) return skipchar(':') skipchar(eol) - emit('):\n') + emitln('):') parseblock(1) - emit("\n") + emit(eol) def emitheader(): - emit("import os\n") - emit("import sys\n") - emit("\n") - emit("def eq(a, b):\n") - emit(" return a == b\n") - emit("\n") - emit("def lt(a, b):\n") - emit(" return a[0] < b[0]\n") - emit("\n") - emit("def addstringchar(a, b):\n") - emit(" return a + b[0]\n") - emit("\n") - emit("def emit(string):\n") - emit(" sys.stdout.write(string)\n") - emit("\n") - emit("def trace(header, value):\n") - emit(" if os.environ.get('TRACE'):\n") - emit(" sys.stderr.write(f'{header}={value!r}\\n')\n") - emit("\n") - emit("eof = chr(0)\n") - emit("eol = chr(10)\n") - emit("quote = chr(34)\n") - emit("PEEK = None\n") - emit("LINE = 1\n") - emit("\n") - emit("def peek():\n") - emit(" global PEEK\n") - emit(" if PEEK is None:\n") - emit(" char = sys.stdin.read(1)\n") - emit(" trace('char', char)\n") - emit(" if not char:\n") - emit(" PEEK = eof\n") - emit(" else:\n") - emit(" PEEK = char\n") - emit(" return PEEK\n") - emit("\n") - emit("peek()\n") - emit("\n") - emit("def skip():\n") - emit(" global LINE\n") - emit(" global PEEK\n") - emit(" if eol == PEEK:\n") - emit(" LINE += 1\n") - emit(" PEEK = None\n") - emit("\n") - emit("def skipchar(char):\n") - emit(" global LINE\n") - emit(" assert char == peek(), (LINE, char, peek())\n") - emit(" skip()\n") - emit("\n") + emitln("import os") + emitln("import sys") + emitln("") + emitln("def eq(a, b):") + emitln(" return a == b") + emitln("") + emitln("def lt(a, b):") + emitln(" return a[0] < b[0]") + emitln("") + emitln("def addstringchar(a, b):") + emitln(" return a + b[0]") + emitln("") + emitln("def emit(string):") + emitln(" sys.stdout.write(string)") + emitln("") + emitln("def trace(header, value):") + emitln(" if os.environ.get('TRACE'):") + emitln(" sys.stderr.write(f'{header}={value!r}\\n')") + emitln("") + emitln("eof = chr(0)") + emitln("eol = chr(10)") + emitln("quote = chr(34)") + emitln("PEEK = None") + emitln("LINE = 1") + emitln("") + emitln("def peek():") + emitln(" global PEEK") + emitln(" if PEEK is None:") + emitln(" char = sys.stdin.read(1)") + emitln(" trace('char', char)") + emitln(" if not char:") + emitln(" PEEK = eof") + emitln(" else:") + emitln(" PEEK = char") + emitln(" return PEEK") + emitln("") + emitln("peek()") + emitln("") + emitln("def skip():") + emitln(" global LINE") + emitln(" global PEEK") + emitln(" if eol == PEEK:") + emitln(" LINE += 1") + emitln(" PEEK = None") + emitln("") + emitln("def skipchar(char):") + emitln(" global LINE") + emitln(" assert char == peek(), (LINE, char, peek())") + emitln(" skip()") + emitln("") def emitfooter(): emit("if __name__ == '__main__':\n") diff --git a/1-lang0py/lang0py.lang0 b/1-lang0py/lang0py.lang0 index c7f8a4e..5afba2d 100644 --- a/1-lang0py/lang0py.lang0 +++ b/1-lang0py/lang0py.lang0 @@ -1,3 +1,8 @@ +emitln data: + emit data + emit eol +/ + increaseindent indent: calc indent addstringchar indent " " calc indent addstringchar indent " " @@ -119,7 +124,7 @@ parsestatif indent: emit indent emit "if " parseexprvarref - emit ":\n" + emitln ":" skipchar eol calc indent increaseindent indent parseblock indent @@ -127,7 +132,7 @@ parsestatif indent: parsestatforever indent: emit indent - emit "while True:\n" + emitln "while True:" skipchar eol calc indent increaseindent indent parseblock indent @@ -135,7 +140,7 @@ parsestatforever indent: parsestatbreak indent: emit indent - emit "break\n" + emitln "break" skipchar eol / @@ -162,7 +167,7 @@ parsestattrace indent: emit quote emit ", " emit varname - emit ")\n" + emitln ")" skipchar eol / @@ -238,7 +243,7 @@ parsestat indent: set first "0" / skipchar eol - emit ")\n" + emitln ")" / parseblock indent: @@ -307,74 +312,74 @@ parsefunc: if iseoblock skipchar "/" skipchar eol - emit "):\n" - emit " pass # ahead declaration\n" + emitln "):" + emitln " pass # ahead declaration" emit eol return / skipchar ":" skipchar eol - emit "):\n" + emitln "):" parseblock " " emit eol / emitheader: - emit "import os\n" - emit "import sys\n" - emit eol - emit "def eq(a, b):\n" - emit " return a == b\n" - emit eol - emit "def lt(a, b):\n" - emit " return a[0] < b[0]\n" - emit eol - emit "def addstringchar(a, b):\n" - emit " return a + b[0]\n" - emit eol - emit "def emit(string):\n" - emit " sys.stdout.write(string)\n" - emit eol - emit "def trace(header, value):\n" - emit " if os.environ.get('TRACE'):\n" - emit " sys.stderr.write(f'{header}={value!r}\\n')\n" - emit eol - emit "eof = chr(0)\n" - emit "eol = chr(10)\n" - emit "quote = chr(34)\n" - emit "PEEK = None\n" - emit "LINE = 1\n" - emit eol - emit "def peek():\n" - emit " global PEEK\n" - emit " if PEEK is None:\n" - emit " char = sys.stdin.read(1)\n" - emit " trace('char', char)\n" - emit " if not char:\n" - emit " PEEK = eof\n" - emit " else:\n" - emit " PEEK = char\n" - emit " return PEEK\n" - emit eol - emit "peek()\n" - emit eol - emit "def skip():\n" - emit " global LINE\n" - emit " global PEEK\n" - emit " if eol == PEEK:\n" - emit " LINE += 1\n" - emit " PEEK = None\n" - emit eol - emit "def skipchar(char):\n" - emit " global LINE\n" - emit " assert char == peek(), (LINE, char, peek())\n" - emit " skip()\n" - emit eol + emitln "import os" + emitln "import sys" + emitln "" + emitln "def eq(a, b):" + emitln " return a == b" + emitln "" + emitln "def lt(a, b):" + emitln " return a[0] < b[0]" + emitln "" + emitln "def addstringchar(a, b):" + emitln " return a + b[0]" + emitln "" + emitln "def emit(string):" + emitln " sys.stdout.write(string)" + emitln "" + emitln "def trace(header, value):" + emitln " if os.environ.get('TRACE'):" + emitln " sys.stderr.write(f'{header}={value!r}\')" + emitln "" + emitln "eof = chr(0)" + emitln "eol = chr(10)" + emitln "quote = chr(34)" + emitln "PEEK = None" + emitln "LINE = 1" + emitln "" + emitln "def peek():" + emitln " global PEEK" + emitln " if PEEK is None:" + emitln " char = sys.stdin.read(1)" + emitln " trace('char', char)" + emitln " if not char:" + emitln " PEEK = eof" + emitln " else:" + emitln " PEEK = char" + emitln " return PEEK" + emitln "" + emitln "peek()" + emitln "" + emitln "def skip():" + emitln " global LINE" + emitln " global PEEK" + emitln " if eol == PEEK:" + emitln " LINE += 1" + emitln " PEEK = None" + emitln "" + emitln "def skipchar(char):" + emitln " global LINE" + emitln " assert char == peek(), (LINE, char, peek())" + emitln " skip()" + emitln "" / emitfooter: - emit "if __name__ == '__main__':\n" - emit " main()\n" + emitln "if __name__ == '__main__':" + emitln " main()" / main: diff --git a/2-lang0c/lang0c.lang0 b/2-lang0c/lang0c.lang0 index 3809d16..fdf9287 100644 --- a/2-lang0c/lang0c.lang0 +++ b/2-lang0c/lang0c.lang0 @@ -1,3 +1,8 @@ +emitln data: + emit data + emit eol +/ + increaseindent indent: calc indent addstringchar indent " " calc indent addstringchar indent " " @@ -155,34 +160,34 @@ parsestatif indent: emit indent emit "if ( 0 < strlen(" parseexprvarref - emit ") )\n" + emitln ") )" emit indent - emit "{\n" + emitln "{" skipchar eol calc indentt increaseindent indent parseblock indentt emit indent - emit "}\n" + emitln "}" return / parsestatforever indent: declare indentt emit indent - emit "while (1)\n" + emitln "while (1)" emit indent - emit "{\n" + emitln "{" skipchar eol calc indentt increaseindent indent parseblock indentt emit indent - emit "}\n" + emitln "}" return / parsestatbreak indent: emit indent - emit "break;\n" + emitln "break;" skipchar eol return / @@ -220,7 +225,7 @@ parsestattrace indent: emit quote emit ", var_" emit varname - emit ");\n" + emitln ");" skipchar eol return / @@ -307,7 +312,7 @@ parsestat indent: set first "0" / skipchar eol - emit ");\n" + emitln ");" return / @@ -389,113 +394,114 @@ parsefunc: if iseoblock skipchar "/" skipchar eol - emit ");" - emit "\n" + emitln ");" return / skipchar ":" skipchar eol - emit ")\n{\n" + emitln ")" + emitln "{" parseblock " " - emit "}\n\n" + emitln "}" + emit eol return / emitheader: - emit "#include \n" - emit "#include \n" - emit "#include \n" - emit "#include \n" - emit eol - emit eol - emit "char var_eof[2] = {-1, 0};\n" - emit "char var_eol[2] = {10, 0};\n" - emit "char var_quote[2] = {34, 0};\n" - emit "char var_false[1] = {0};\n" - emit "char var_true[2] = {'1', 0};\n" - emit eol - emit eol - emit "char * eq(char * a, char * b)\n" - emit "{\n" - emit " return (strcmp(a, b) == 0) ? var_true : var_false;\n" - emit "}\n" - emit "\n" - emit "char * lt(char * a, char * b)\n" - emit "{\n" - emit " return (strcmp(a, b) < 0) ? var_true : var_false;\n" - emit "}\n" - emit "char * not(char * a)\n" - emit "{\n" - emit " return (strcmp(a, var_true) != 0) ? var_true : var_false;\n" - emit "}\n" - emit "\n" - emit "char * addstringchar(char * str, char * chr)\n" - emit "{\n" - emit " int str_len = strlen(str);\n" - emit " assert(strlen(chr) == 1);\n" - emit " char * res = malloc((str_len + 2) * sizeof(char));\n" - emit " strcpy(res, str);\n" - emit " res[str_len + 0] = chr[0];\n" - emit " res[str_len + 1] = 0;\n" - emit " return res;\n" - emit "}\n" - emit "\n" - emit "char * emit(char * str)\n" - emit "{\n" - emit " fputs(str, stdout);\n" - emit " return 0;\n" - emit "}\n" - emit "\n" - emit "char * trace(char * var_name, char * var_value)\n" - emit "{\n" + emitln "#include " + emitln "#include " + emitln "#include " + emitln "#include " + emitln "" + emitln "" + emitln "char var_eof[2] = {-1, 0};" + emitln "char var_eol[2] = {10, 0};" + emitln "char var_quote[2] = {34, 0};" + emitln "char var_false[1] = {0};" + emitln "char var_true[2] = {'1', 0};" + emitln "" + emitln "" + emitln "char * eq(char * a, char * b)" + emitln "{" + emitln " return (strcmp(a, b) == 0) ? var_true : var_false;" + emitln "}" + emitln "" + emitln "char * lt(char * a, char * b)" + emitln "{" + emitln " return (strcmp(a, b) < 0) ? var_true : var_false;" + emitln "}" + emitln "char * not(char * a)" + emitln "{" + emitln " return (strcmp(a, var_true) != 0) ? var_true : var_false;" + emitln "}" + emitln "" + emitln "char * addstringchar(char * str, char * chr)" + emitln "{" + emitln " int str_len = strlen(str);" + emitln " assert(strlen(chr) == 1);" + emitln " char * res = malloc((str_len + 2) * sizeof(char));" + emitln " strcpy(res, str);" + emitln " res[str_len + 0] = chr[0];" + emitln " res[str_len + 1] = 0;" + emitln " return res;" + emitln "}" + emitln "" + emitln "char * emit(char * str)" + emitln "{" + emitln " fputs(str, stdout);" + emitln " return 0;" + emitln "}" + emitln "" + emitln "char * trace(char * var_name, char * var_value)" + emitln "{" emit " const char * env_trace = getenv(" emit quote emit "TRACE" emit quote - emit ");\n" - emit " if( !env_trace ) return 0;\n" - emit " fputs(var_name, stderr);\n" + emitln ");" + emitln " if( !env_trace ) return 0;" + emitln " fputs(var_name, stderr);" emit " fputs(" emit quote emit "=" emit quote - emit ", stderr);\n" - emit " fputs(var_value, stderr);\n" - emit " fputs(var_eol, stderr);\n" - emit " return 0;\n" - emit "}\n" - emit eol - emit "int LINE = 1;\n" - emit eol - emit "char * peek()\n" - emit "{\n" - emit " char * res = malloc(2*sizeof(char));\n" - emit " res[0] = getc(stdin);\n" - emit " res[1] = 0;\n" - emit " ungetc(res[0], stdin);\n" - emit " return res;\n" - emit "}\n" - emit "\n" - emit "void skip()\n" - emit "{\n" - emit " char c = getc(stdin);\n" - emit " if( c == 10 ) LINE += 1;\n" - emit "}\n" - emit "\n" - emit "void skipchar(char * chr)\n" - emit "{\n" - emit " assert(strlen(chr) == 1);\n" - emit " char * act = peek();\n" - emit " assert(strlen(act) == 1);\n" - emit " if( chr[0] == act[0] ) {skip(); return;};\n" + emitln ", stderr);" + emitln " fputs(var_value, stderr);" + emitln " fputs(var_eol, stderr);" + emitln " return 0;" + emitln "}" + emitln "" + emitln "int LINE = 1;" + emitln "" + emitln "char * peek()" + emitln "{" + emitln " char * res = malloc(2*sizeof(char));" + emitln " res[0] = getc(stdin);" + emitln " res[1] = 0;" + emitln " ungetc(res[0], stdin);" + emitln " return res;" + emitln "}" + emitln "" + emitln "void skip()" + emitln "{" + emitln " char c = getc(stdin);" + emitln " if( c == 10 ) LINE += 1;" + emitln "}" + emitln "" + emitln "void skipchar(char * chr)" + emitln "{" + emitln " assert(strlen(chr) == 1);" + emitln " char * act = peek();" + emitln " assert(strlen(act) == 1);" + emitln " if( chr[0] == act[0] ) {skip(); return;};" emit " fprintf(stderr, " emit quote emit "Expected '%c' on line %d but saw '%c' instead%c" emit quote - emit ", chr[0], LINE, act[0], 10);\n" - emit " exit(1);\n" - emit "}\n" - emit "\n" + emitln ", chr[0], LINE, act[0], 10);" + emitln " exit(1);" + emitln "}" + emitln "" return /