import os import sys def emit(string): sys.stdout.write(string) def trace(header, value): if os.environ.get('TRACE'): sys.stderr.write(f'{header}={value!r}\n') eof = chr(0) eol = chr(10) quote = chr(34) PEEK = None LINE = 1 def peek(): global PEEK if PEEK is None: char = sys.stdin.read(1) trace('char', char) if not char: PEEK = eof else: PEEK = char return PEEK def skip(): global LINE global PEEK if eol == PEEK: LINE += 1 PEEK = None def skipchar(char): global LINE assert char == peek(), (LINE, char, peek()) skip() def lexident(): word = '' while True: char = peek() if char < 'a' or char > 'z': break word += char skip() return word def parseconststring(): skipchar(quote) emit(quote) escaped = False while True: char = peek() if char == eof: break if char == quote: break emit(char) skip() skipchar(quote) emit(quote) def parseexprvarref(): var = lexident() emit(var) def parseexprcall(): funcname = lexident() emit(funcname) emit('(') first = True while ' ' == peek(): skip() if not first: emit(', ') if quote == peek(): parseconststring() else: parseexprvarref() first = False emit(')') def parsestatset(indent): skipchar(' ') var = lexident() skipchar(' ') emit(' ' * indent) emit(var) emit(' = ') parseconststring() emit(eol) skipchar(eol) def parsestatcalc(indent): skipchar(' ') var = lexident() skipchar(' ') emit(' ' * indent) emit(var) emit(' = ') parseexprcall() emit(eol) skipchar(eol) def parsestatif(indent): skipchar(' ') emit(' ' * indent) emit('if ') parseexprvarref() emit(':\n') skipchar(eol) parseblock(indent + 1) def parsestatforever(indent): emit(' ' * indent) emit('while True:\n') skipchar(eol) parseblock(indent + 1) def parsestatbreak(indent): emit(' ' * indent) emit('break\n') skipchar(eol) def parsestatreturn(indent): emit(' ' * indent) emit('return ') if ' ' == peek(): skip() parseexprvarref() emit(eol) skipchar(eol) def parsestatemit(indent): skipchar(' ') emit(' ' * indent) emit('emit(') if quote == peek(): parseconststring() else: parseexprvarref() skipchar(eol) emit(')\n') def parsestattrace(indent): skipchar(' ') emit(' ' * indent) emit('trace("') var_name = lexident() skipchar(eol) emit(var_name) emit('", ') emit(var_name) emit(')\n') def parsestatskipchar(indent): skipchar(' ') emit(' ' * indent) emit('skipchar(') if quote == peek(): parseconststring() else: parseexprvarref() emit(')\n') skipchar(eol) def parsestat(indent): call = lexident() trace('call', call) if call == "set": parsestatset(indent) return if call == "calc": parsestatcalc(indent) return if call == "if": parsestatif(indent) return if call == "forever": parsestatforever(indent) return if call == "break": parsestatbreak(indent) return if call == "return": parsestatreturn(indent) return if call == "emit": parsestatemit(indent) return if call == "trace": parsestattrace(indent) return if call == "skipchar": parsestatskipchar(indent) return emit(' ' * indent) emit(call) emit('(') first = True while ' ' == peek(): skip() if not first: emit(", ") if '"' == peek(): parseconststring() else: parseexprvarref() first = False skipchar(eol) emit(')\n') def parseblock(indent): while True: while eol == peek(): skip() for _ in range(indent - 1): skipchar('\t') if '/' == peek(): skip() skipchar(eol) break skipchar('\t') parsestat(indent) def parsefunc(): funcname = lexident() trace('funcname', funcname) emit('def ') emit(funcname) emit('(') first = True while ' ' == peek(): skip() var = lexident() if not first: emit(", ") emit(var) first = False skipchar(':') skipchar(eol) emit('):\n') parseblock(1) emit("\n") 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("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") def emitfooter(): emit("if __name__ == '__main__':\n") emit(" main()\n") def main(): emitheader() while True: if eof == peek(): break while eol == peek(): skip() parsefunc() emitfooter() if __name__ == '__main__': main()