import os import sys def emit(string): sys.stdout.write(string) sys.stdout.flush() 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 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 emitln(data): emit(data) emit(eol) 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 parsestatdeclare(indent): skipchar(' ') var = lexident() skipchar(eol) 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() emitln(':') skipchar(eol) parseblock(indent + 1) def parsestatforever(indent): emit(' ' * indent) emitln('while True:') skipchar(eol) parseblock(indent + 1) def parsestatbreak(indent): emit(' ' * indent) emitln('break') skipchar(eol) def parsestatreturn(indent): emit(' ' * indent) emit('return ') if ' ' == peek(): skip() parseexprvarref() emit(eol) skipchar(eol) def parsestattrace(indent): skipchar(' ') emit(' ' * indent) emit('trace("') var_name = lexident() skipchar(eol) emit(var_name) emit('", ') emit(var_name) emitln(')') def parsestat(indent): call = lexident() trace('call', call) if call == "declare": parsestatdeclare(indent) return 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 == "trace": parsestattrace(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) emitln(')') 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 if '/' == peek(): # Ahead declaration skipchar('/') skipchar(eol) emitln("):") emitln(" pass # ahead declaration") emit(eol) return skipchar(':') skipchar(eol) emitln('):') parseblock(1) emit(eol) def 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("") 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()