emitln data: emit data emit eol / increaseindent indent: calc indent addstringchar indent " " calc indent addstringchar indent " " calc indent addstringchar indent " " calc indent addstringchar indent " " return indent / lexident: declare word set word "" forever calc char peek calc isbeforea lt char "a" if isbeforea break / calc isafterz lt "z" char if isafterz break / calc word addstringchar word char skip / return word / parseconststring: skipchar quote emit quote forever calc char peek calc iseof eq char eof if iseof break / calc isquote eq char quote if isquote break / emit char skip / skipchar quote emit quote / parseexprvarref: calc varname lexident emit varname / parseexprcall: calc funcname lexident emit funcname emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / set first "0" / emit ")" / parsestatdeclare indent: skipchar " " calc var lexident skipchar eol / parsestatset indent: skipchar " " calc var lexident skipchar " " emit indent emit var emit " = " parseconststring emit eol skipchar eol / parsestatcalc indent: skipchar " " calc var lexident skipchar " " emit indent emit var emit " = " parseexprcall emit eol skipchar eol / parseblock indent/ parsestatif indent: skipchar " " emit indent emit "if " parseexprvarref emitln ":" skipchar eol calc indent increaseindent indent parseblock indent / parsestatforever indent: emit indent emitln "while True:" skipchar eol calc indent increaseindent indent parseblock indent / parsestatbreak indent: emit indent emitln "break" skipchar eol / parsestatreturn indent: emit indent emit "return " calc char peek calc isspace eq char " " if isspace skip calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / / emit eol skipchar eol / parsestatcheck indent: declare char declare funcname declare iscolon declare isnotquote declare isquote declare notfirst skipchar " " emit indent emit "assert " calc funcname lexident emit funcname emit "(" set notfirst "" forever skipchar " " calc char peek calc iscolon eq char ":" if iscolon break / if notfirst emit ", " / calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / set notfirst "1" / skipchar ":" emit "), (" set notfirst "" forever skipchar " " if notfirst emit ", " / calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / calc char peek calc iseol eq char eol if iseol break / set notfirst "1" / emitln ")" / parsestattrace indent: emit indent emit "trace(" emit quote skipchar " " calc varname lexident emit varname emit quote emit ", " emit varname emitln ")" skipchar eol / parsestat indent: calc call lexident trace call calc isset eq call "declare" if isset parsestatdeclare indent return / calc isset eq call "set" if isset parsestatset indent return / calc iscalc eq call "calc" if iscalc parsestatcalc indent return / calc isif eq call "if" if isif parsestatif indent return / calc isforever eq call "forever" if isforever parsestatforever indent return / calc isbreak eq call "break" if isbreak parsestatbreak indent return / calc isreturn eq call "return" if isreturn parsestatreturn indent return / calc istrace eq call "trace" if istrace parsestattrace indent return / calc ischeck eq call "check" if ischeck parsestatcheck indent return / emit indent emit call emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / calc char peek calc isquote eq char quote calc isnotquote not isquote if isquote parseconststring / if isnotquote parseexprvarref / set first "0" / skipchar eol emitln ")" / parseblock indent: forever forever calc char peek calc iseol eq char eol calc isnoteol not iseol if isnoteol break / skip / set copy " " forever calc isdone eq copy indent if isdone break / skipchar "\t" calc copy increaseindent copy / calc char peek calc iseoblock eq char "/" if iseoblock skip skipchar eol break / skipchar "\t" parsestat indent / / parsefunc: calc funcname lexident calc char peek calc iseoblock eq char "/" if iseoblock return / trace funcname emit "def " emit funcname emit "(" set first "1" forever calc char peek calc isspace eq char " " calc isnotspace not isspace if isnotspace break / skip calc var lexident calc isfirst eq first "1" calc isnotfirst not isfirst if isnotfirst emit ", " / emit var set first "0" / calc char peek calc iseoblock eq char "/" if iseoblock skipchar "/" skipchar eol emitln "):" emitln " pass # ahead declaration" emit eol return / skipchar ":" skipchar eol emitln "):" parseblock " " emit eol / emitheader: 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 " sys.stdout.flush()" 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 "" / emitfooter: emitln "if __name__ == '__main__':" emitln " main()" / main: emitheader forever calc char peek calc iseof eq char eof if iseof break / forever calc char peek calc iseol eq char eol calc isnoteol not iseol if isnoteol break / skip / parsefunc / emitfooter /