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 fileget(path): with open(f'./{path}', encoding='ASCII') as fil: return fil.read() 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() 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 parsestattrace(indent): skipchar(' ') emit(' ' * indent) emit('trace("') var_name = lexident() skipchar(eol) emit(var_name) emit('", ') emit(var_name) emit(')\n') 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) 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 if '/' == peek(): # Ahead declaration skipchar('/') skipchar(eol) emit("):\n") emit(" pass # ahead declaration\n") emit("\n") return skipchar(':') skipchar(eol) emit('):\n') parseblock(1) emit("\n") def emitheader(): header = fileget("it0-in-header.py") emit(header) def emitfooter(): footer = fileget("it0-in-footer.py") emit(footer) def main(): emitheader() while True: if eof == peek(): break while eol == peek(): skip() parsefunc() emitfooter() if __name__ == '__main__': main()