Adds emitln to reduce complexity

This commit is contained in:
Johan B.W. de Vries 2025-02-02 15:30:40 +01:00
parent 17841954de
commit a08084230e
3 changed files with 230 additions and 215 deletions

View File

@ -43,6 +43,10 @@ def skipchar(char):
assert char == peek(), (LINE, char, peek()) assert char == peek(), (LINE, char, peek())
skip() skip()
def emitln(data):
emit(data)
emit(eol)
def lexident(): def lexident():
word = '' word = ''
while True: while True:
@ -135,21 +139,21 @@ def parsestatif(indent):
emit(' ' * indent) emit(' ' * indent)
emit('if ') emit('if ')
parseexprvarref() parseexprvarref()
emit(':\n') emitln(':')
skipchar(eol) skipchar(eol)
parseblock(indent + 1) parseblock(indent + 1)
def parsestatforever(indent): def parsestatforever(indent):
emit(' ' * indent) emit(' ' * indent)
emit('while True:\n') emitln('while True:')
skipchar(eol) skipchar(eol)
parseblock(indent + 1) parseblock(indent + 1)
def parsestatbreak(indent): def parsestatbreak(indent):
emit(' ' * indent) emit(' ' * indent)
emit('break\n') emitln('break')
skipchar(eol) skipchar(eol)
def parsestatreturn(indent): def parsestatreturn(indent):
@ -172,7 +176,7 @@ def parsestattrace(indent):
emit(var_name) emit(var_name)
emit('", ') emit('", ')
emit(var_name) emit(var_name)
emit(')\n') emitln(')')
def parsestat(indent): def parsestat(indent):
call = lexident() call = lexident()
@ -227,7 +231,7 @@ def parsestat(indent):
skipchar(eol) skipchar(eol)
emit(')\n') emitln(')')
def parseblock(indent): def parseblock(indent):
while True: while True:
@ -267,71 +271,71 @@ def parsefunc():
# Ahead declaration # Ahead declaration
skipchar('/') skipchar('/')
skipchar(eol) skipchar(eol)
emit("):\n") emitln("):")
emit(" pass # ahead declaration\n") emitln(" pass # ahead declaration")
emit("\n") emit(eol)
return return
skipchar(':') skipchar(':')
skipchar(eol) skipchar(eol)
emit('):\n') emitln('):')
parseblock(1) parseblock(1)
emit("\n") emit(eol)
def emitheader(): def emitheader():
emit("import os\n") emitln("import os")
emit("import sys\n") emitln("import sys")
emit("\n") emitln("")
emit("def eq(a, b):\n") emitln("def eq(a, b):")
emit(" return a == b\n") emitln(" return a == b")
emit("\n") emitln("")
emit("def lt(a, b):\n") emitln("def lt(a, b):")
emit(" return a[0] < b[0]\n") emitln(" return a[0] < b[0]")
emit("\n") emitln("")
emit("def addstringchar(a, b):\n") emitln("def addstringchar(a, b):")
emit(" return a + b[0]\n") emitln(" return a + b[0]")
emit("\n") emitln("")
emit("def emit(string):\n") emitln("def emit(string):")
emit(" sys.stdout.write(string)\n") emitln(" sys.stdout.write(string)")
emit("\n") emitln("")
emit("def trace(header, value):\n") emitln("def trace(header, value):")
emit(" if os.environ.get('TRACE'):\n") emitln(" if os.environ.get('TRACE'):")
emit(" sys.stderr.write(f'{header}={value!r}\\n')\n") emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
emit("\n") emitln("")
emit("eof = chr(0)\n") emitln("eof = chr(0)")
emit("eol = chr(10)\n") emitln("eol = chr(10)")
emit("quote = chr(34)\n") emitln("quote = chr(34)")
emit("PEEK = None\n") emitln("PEEK = None")
emit("LINE = 1\n") emitln("LINE = 1")
emit("\n") emitln("")
emit("def peek():\n") emitln("def peek():")
emit(" global PEEK\n") emitln(" global PEEK")
emit(" if PEEK is None:\n") emitln(" if PEEK is None:")
emit(" char = sys.stdin.read(1)\n") emitln(" char = sys.stdin.read(1)")
emit(" trace('char', char)\n") emitln(" trace('char', char)")
emit(" if not char:\n") emitln(" if not char:")
emit(" PEEK = eof\n") emitln(" PEEK = eof")
emit(" else:\n") emitln(" else:")
emit(" PEEK = char\n") emitln(" PEEK = char")
emit(" return PEEK\n") emitln(" return PEEK")
emit("\n") emitln("")
emit("peek()\n") emitln("peek()")
emit("\n") emitln("")
emit("def skip():\n") emitln("def skip():")
emit(" global LINE\n") emitln(" global LINE")
emit(" global PEEK\n") emitln(" global PEEK")
emit(" if eol == PEEK:\n") emitln(" if eol == PEEK:")
emit(" LINE += 1\n") emitln(" LINE += 1")
emit(" PEEK = None\n") emitln(" PEEK = None")
emit("\n") emitln("")
emit("def skipchar(char):\n") emitln("def skipchar(char):")
emit(" global LINE\n") emitln(" global LINE")
emit(" assert char == peek(), (LINE, char, peek())\n") emitln(" assert char == peek(), (LINE, char, peek())")
emit(" skip()\n") emitln(" skip()")
emit("\n") emitln("")
def emitfooter(): def emitfooter():
emit("if __name__ == '__main__':\n") emit("if __name__ == '__main__':\n")

View File

@ -1,3 +1,8 @@
emitln data:
emit data
emit eol
/
increaseindent indent: increaseindent indent:
calc indent addstringchar indent " " calc indent addstringchar indent " "
calc indent addstringchar indent " " calc indent addstringchar indent " "
@ -119,7 +124,7 @@ parsestatif indent:
emit indent emit indent
emit "if " emit "if "
parseexprvarref parseexprvarref
emit ":\n" emitln ":"
skipchar eol skipchar eol
calc indent increaseindent indent calc indent increaseindent indent
parseblock indent parseblock indent
@ -127,7 +132,7 @@ parsestatif indent:
parsestatforever indent: parsestatforever indent:
emit indent emit indent
emit "while True:\n" emitln "while True:"
skipchar eol skipchar eol
calc indent increaseindent indent calc indent increaseindent indent
parseblock indent parseblock indent
@ -135,7 +140,7 @@ parsestatforever indent:
parsestatbreak indent: parsestatbreak indent:
emit indent emit indent
emit "break\n" emitln "break"
skipchar eol skipchar eol
/ /
@ -162,7 +167,7 @@ parsestattrace indent:
emit quote emit quote
emit ", " emit ", "
emit varname emit varname
emit ")\n" emitln ")"
skipchar eol skipchar eol
/ /
@ -238,7 +243,7 @@ parsestat indent:
set first "0" set first "0"
/ /
skipchar eol skipchar eol
emit ")\n" emitln ")"
/ /
parseblock indent: parseblock indent:
@ -307,74 +312,74 @@ parsefunc:
if iseoblock if iseoblock
skipchar "/" skipchar "/"
skipchar eol skipchar eol
emit "):\n" emitln "):"
emit " pass # ahead declaration\n" emitln " pass # ahead declaration"
emit eol emit eol
return return
/ /
skipchar ":" skipchar ":"
skipchar eol skipchar eol
emit "):\n" emitln "):"
parseblock " " parseblock " "
emit eol emit eol
/ /
emitheader: emitheader:
emit "import os\n" emitln "import os"
emit "import sys\n" emitln "import sys"
emit eol emitln ""
emit "def eq(a, b):\n" emitln "def eq(a, b):"
emit " return a == b\n" emitln " return a == b"
emit eol emitln ""
emit "def lt(a, b):\n" emitln "def lt(a, b):"
emit " return a[0] < b[0]\n" emitln " return a[0] < b[0]"
emit eol emitln ""
emit "def addstringchar(a, b):\n" emitln "def addstringchar(a, b):"
emit " return a + b[0]\n" emitln " return a + b[0]"
emit eol emitln ""
emit "def emit(string):\n" emitln "def emit(string):"
emit " sys.stdout.write(string)\n" emitln " sys.stdout.write(string)"
emit eol emitln ""
emit "def trace(header, value):\n" emitln "def trace(header, value):"
emit " if os.environ.get('TRACE'):\n" emitln " if os.environ.get('TRACE'):"
emit " sys.stderr.write(f'{header}={value!r}\\n')\n" emitln " sys.stderr.write(f'{header}={value!r}\')"
emit eol emitln ""
emit "eof = chr(0)\n" emitln "eof = chr(0)"
emit "eol = chr(10)\n" emitln "eol = chr(10)"
emit "quote = chr(34)\n" emitln "quote = chr(34)"
emit "PEEK = None\n" emitln "PEEK = None"
emit "LINE = 1\n" emitln "LINE = 1"
emit eol emitln ""
emit "def peek():\n" emitln "def peek():"
emit " global PEEK\n" emitln " global PEEK"
emit " if PEEK is None:\n" emitln " if PEEK is None:"
emit " char = sys.stdin.read(1)\n" emitln " char = sys.stdin.read(1)"
emit " trace('char', char)\n" emitln " trace('char', char)"
emit " if not char:\n" emitln " if not char:"
emit " PEEK = eof\n" emitln " PEEK = eof"
emit " else:\n" emitln " else:"
emit " PEEK = char\n" emitln " PEEK = char"
emit " return PEEK\n" emitln " return PEEK"
emit eol emitln ""
emit "peek()\n" emitln "peek()"
emit eol emitln ""
emit "def skip():\n" emitln "def skip():"
emit " global LINE\n" emitln " global LINE"
emit " global PEEK\n" emitln " global PEEK"
emit " if eol == PEEK:\n" emitln " if eol == PEEK:"
emit " LINE += 1\n" emitln " LINE += 1"
emit " PEEK = None\n" emitln " PEEK = None"
emit eol emitln ""
emit "def skipchar(char):\n" emitln "def skipchar(char):"
emit " global LINE\n" emitln " global LINE"
emit " assert char == peek(), (LINE, char, peek())\n" emitln " assert char == peek(), (LINE, char, peek())"
emit " skip()\n" emitln " skip()"
emit eol emitln ""
/ /
emitfooter: emitfooter:
emit "if __name__ == '__main__':\n" emitln "if __name__ == '__main__':"
emit " main()\n" emitln " main()"
/ /
main: main:

View File

@ -1,3 +1,8 @@
emitln data:
emit data
emit eol
/
increaseindent indent: increaseindent indent:
calc indent addstringchar indent " " calc indent addstringchar indent " "
calc indent addstringchar indent " " calc indent addstringchar indent " "
@ -155,34 +160,34 @@ parsestatif indent:
emit indent emit indent
emit "if ( 0 < strlen(" emit "if ( 0 < strlen("
parseexprvarref parseexprvarref
emit ") )\n" emitln ") )"
emit indent emit indent
emit "{\n" emitln "{"
skipchar eol skipchar eol
calc indentt increaseindent indent calc indentt increaseindent indent
parseblock indentt parseblock indentt
emit indent emit indent
emit "}\n" emitln "}"
return return
/ /
parsestatforever indent: parsestatforever indent:
declare indentt declare indentt
emit indent emit indent
emit "while (1)\n" emitln "while (1)"
emit indent emit indent
emit "{\n" emitln "{"
skipchar eol skipchar eol
calc indentt increaseindent indent calc indentt increaseindent indent
parseblock indentt parseblock indentt
emit indent emit indent
emit "}\n" emitln "}"
return return
/ /
parsestatbreak indent: parsestatbreak indent:
emit indent emit indent
emit "break;\n" emitln "break;"
skipchar eol skipchar eol
return return
/ /
@ -220,7 +225,7 @@ parsestattrace indent:
emit quote emit quote
emit ", var_" emit ", var_"
emit varname emit varname
emit ");\n" emitln ");"
skipchar eol skipchar eol
return return
/ /
@ -307,7 +312,7 @@ parsestat indent:
set first "0" set first "0"
/ /
skipchar eol skipchar eol
emit ");\n" emitln ");"
return return
/ /
@ -389,113 +394,114 @@ parsefunc:
if iseoblock if iseoblock
skipchar "/" skipchar "/"
skipchar eol skipchar eol
emit ");" emitln ");"
emit "\n"
return return
/ /
skipchar ":" skipchar ":"
skipchar eol skipchar eol
emit ")\n{\n" emitln ")"
emitln "{"
parseblock " " parseblock " "
emit "}\n\n" emitln "}"
emit eol
return return
/ /
emitheader: emitheader:
emit "#include <assert.h>\n" emitln "#include <assert.h>"
emit "#include <stdio.h>\n" emitln "#include <stdio.h>"
emit "#include <stdlib.h>\n" emitln "#include <stdlib.h>"
emit "#include <string.h>\n" emitln "#include <string.h>"
emit eol emitln ""
emit eol emitln ""
emit "char var_eof[2] = {-1, 0};\n" emitln "char var_eof[2] = {-1, 0};"
emit "char var_eol[2] = {10, 0};\n" emitln "char var_eol[2] = {10, 0};"
emit "char var_quote[2] = {34, 0};\n" emitln "char var_quote[2] = {34, 0};"
emit "char var_false[1] = {0};\n" emitln "char var_false[1] = {0};"
emit "char var_true[2] = {'1', 0};\n" emitln "char var_true[2] = {'1', 0};"
emit eol emitln ""
emit eol emitln ""
emit "char * eq(char * a, char * b)\n" emitln "char * eq(char * a, char * b)"
emit "{\n" emitln "{"
emit " return (strcmp(a, b) == 0) ? var_true : var_false;\n" emitln " return (strcmp(a, b) == 0) ? var_true : var_false;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "char * lt(char * a, char * b)\n" emitln "char * lt(char * a, char * b)"
emit "{\n" emitln "{"
emit " return (strcmp(a, b) < 0) ? var_true : var_false;\n" emitln " return (strcmp(a, b) < 0) ? var_true : var_false;"
emit "}\n" emitln "}"
emit "char * not(char * a)\n" emitln "char * not(char * a)"
emit "{\n" emitln "{"
emit " return (strcmp(a, var_true) != 0) ? var_true : var_false;\n" emitln " return (strcmp(a, var_true) != 0) ? var_true : var_false;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "char * addstringchar(char * str, char * chr)\n" emitln "char * addstringchar(char * str, char * chr)"
emit "{\n" emitln "{"
emit " int str_len = strlen(str);\n" emitln " int str_len = strlen(str);"
emit " assert(strlen(chr) == 1);\n" emitln " assert(strlen(chr) == 1);"
emit " char * res = malloc((str_len + 2) * sizeof(char));\n" emitln " char * res = malloc((str_len + 2) * sizeof(char));"
emit " strcpy(res, str);\n" emitln " strcpy(res, str);"
emit " res[str_len + 0] = chr[0];\n" emitln " res[str_len + 0] = chr[0];"
emit " res[str_len + 1] = 0;\n" emitln " res[str_len + 1] = 0;"
emit " return res;\n" emitln " return res;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "char * emit(char * str)\n" emitln "char * emit(char * str)"
emit "{\n" emitln "{"
emit " fputs(str, stdout);\n" emitln " fputs(str, stdout);"
emit " return 0;\n" emitln " return 0;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "char * trace(char * var_name, char * var_value)\n" emitln "char * trace(char * var_name, char * var_value)"
emit "{\n" emitln "{"
emit " const char * env_trace = getenv(" emit " const char * env_trace = getenv("
emit quote emit quote
emit "TRACE" emit "TRACE"
emit quote emit quote
emit ");\n" emitln ");"
emit " if( !env_trace ) return 0;\n" emitln " if( !env_trace ) return 0;"
emit " fputs(var_name, stderr);\n" emitln " fputs(var_name, stderr);"
emit " fputs(" emit " fputs("
emit quote emit quote
emit "=" emit "="
emit quote emit quote
emit ", stderr);\n" emitln ", stderr);"
emit " fputs(var_value, stderr);\n" emitln " fputs(var_value, stderr);"
emit " fputs(var_eol, stderr);\n" emitln " fputs(var_eol, stderr);"
emit " return 0;\n" emitln " return 0;"
emit "}\n" emitln "}"
emit eol emitln ""
emit "int LINE = 1;\n" emitln "int LINE = 1;"
emit eol emitln ""
emit "char * peek()\n" emitln "char * peek()"
emit "{\n" emitln "{"
emit " char * res = malloc(2*sizeof(char));\n" emitln " char * res = malloc(2*sizeof(char));"
emit " res[0] = getc(stdin);\n" emitln " res[0] = getc(stdin);"
emit " res[1] = 0;\n" emitln " res[1] = 0;"
emit " ungetc(res[0], stdin);\n" emitln " ungetc(res[0], stdin);"
emit " return res;\n" emitln " return res;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "void skip()\n" emitln "void skip()"
emit "{\n" emitln "{"
emit " char c = getc(stdin);\n" emitln " char c = getc(stdin);"
emit " if( c == 10 ) LINE += 1;\n" emitln " if( c == 10 ) LINE += 1;"
emit "}\n" emitln "}"
emit "\n" emitln ""
emit "void skipchar(char * chr)\n" emitln "void skipchar(char * chr)"
emit "{\n" emitln "{"
emit " assert(strlen(chr) == 1);\n" emitln " assert(strlen(chr) == 1);"
emit " char * act = peek();\n" emitln " char * act = peek();"
emit " assert(strlen(act) == 1);\n" emitln " assert(strlen(act) == 1);"
emit " if( chr[0] == act[0] ) {skip(); return;};\n" emitln " if( chr[0] == act[0] ) {skip(); return;};"
emit " fprintf(stderr, " emit " fprintf(stderr, "
emit quote emit quote
emit "Expected '%c' on line %d but saw '%c' instead%c" emit "Expected '%c' on line %d but saw '%c' instead%c"
emit quote emit quote
emit ", chr[0], LINE, act[0], 10);\n" emitln ", chr[0], LINE, act[0], 10);"
emit " exit(1);\n" emitln " exit(1);"
emit "}\n" emitln "}"
emit "\n" emitln ""
return return
/ /