import os import sys def eq(a, b): return a == b def lt(a, b): return a[0] < b[0] def addstringchar(a, b): return a + b[0] 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 increaseindent(indent): indent = addstringchar(indent, " ") indent = addstringchar(indent, " ") indent = addstringchar(indent, " ") indent = addstringchar(indent, " ") return indent def lexident(): word = "" while True: char = peek() isbeforea = lt(char, "a") if isbeforea: break isafterz = lt("z", char) if isafterz: break word = addstringchar(word, char) skip() return word def parseconststring(): skipchar(quote) emit(quote) while True: char = peek() iseof = eq(char, eof) if iseof: break isquote = eq(char, quote) if isquote: break emit(char) skip() skipchar(quote) emit(quote) def parseexprvarref(): varname = lexident() emit("var_") emit(varname) def parseexprcall(): funcname = lexident() emit(funcname) emit("(") first = "1" while True: char = peek() isspace = eq(char, " ") isnotspace = not(isspace) if isnotspace: break skip() isfirst = eq(first, "1") isnotfirst = not(isfirst) if isnotfirst: emit(", ") char = peek() isquote = eq(char, quote) isnotquote = not(isquote) if isquote: parseconststring() if isnotquote: parseexprvarref() first = "0" emit(")") def parsestatset(indent): skipchar(" ") var = lexident() skipchar(" ") emit(indent) emit("char * var_") emit(var) emit(" = ") parseconststring() emit(";") emit(eol) skipchar(eol) def parsestatcalc(indent): skipchar(" ") var = lexident() skipchar(" ") emit(indent) emit("char * var_") emit(var) emit(" = ") parseexprcall() emit(";") emit(eol) skipchar(eol) def parsestatif(indent): skipchar(" ") emit(indent) emit("if (") parseexprvarref() emit(")\n") emit(indent) emit("{\n") skipchar(eol) indentt = increaseindent(indent) parseblock(indentt) emit(indent) emit("}\n") def parsestatforever(indent): emit(indent) emit("while (1)\n") emit(indent) emit("{\n") skipchar(eol) indentt = increaseindent(indent) parseblock(indentt) emit(indent) emit("}\n") def parsestatbreak(indent): emit(indent) emit("break;\n") skipchar(eol) def parsestatreturn(indent): emit(indent) emit("return ") char = peek() isspace = eq(char, " ") if isspace: skip() parseexprvarref() emit(";") emit(eol) skipchar(eol) def parsestatemit(indent): emit(indent) emit("emit(") skipchar(" ") char = peek() isquote = eq(char, quote) isnotquote = not(isquote) if isquote: parseconststring() if isnotquote: parseexprvarref() emit(");\n") skipchar(eol) def parsestattrace(indent): emit(indent) emit("trace(") emit(quote) skipchar(" ") varname = lexident() emit(varname) emit(quote) emit(", ") emit(varname) emit(")\n") skipchar(eol) def parsestatskipchar(indent): skipchar(" ") emit(indent) emit("skipchar(") char = peek() isquote = eq(char, quote) isnotquote = not(isquote) if isquote: parseconststring() if isnotquote: parseexprvarref() emit(");\n") skipchar(eol) def parsestat(indent): call = lexident() trace("call", call) isset = eq(call, "set") if isset: parsestatset(indent) return iscalc = eq(call, "calc") if iscalc: parsestatcalc(indent) return isif = eq(call, "if") if isif: parsestatif(indent) return isforever = eq(call, "forever") if isforever: parsestatforever(indent) return isbreak = eq(call, "break") if isbreak: parsestatbreak(indent) return isreturn = eq(call, "return") if isreturn: parsestatreturn(indent) return isemit = eq(call, "emit") if isemit: parsestatemit(indent) return istrace = eq(call, "trace") if istrace: parsestattrace(indent) return isskipchar = eq(call, "skipchar") if isskipchar: parsestatskipchar(indent) return emit(indent) emit(call) emit("(") first = "1" while True: char = peek() isspace = eq(char, " ") isnotspace = not(isspace) if isnotspace: break skip() char = peek() isquote = eq(char, quote) isnotquote = not(isquote) if isquote: parseconststring() if isnotquote: parseexprvarref() isfirst = eq(first, "1") isnotfirst = not(isfirst) if isnotfirst: emit(", ") first = "0" skipchar(eol) emit(");\n") def parseblock(indent): while True: while True: char = peek() iseol = eq(char, eol) isnoteol = not(iseol) if isnoteol: break skip() copy = " " while True: isdone = eq(copy, indent) if isdone: break skipchar("\t") copy = increaseindent(copy) char = peek() iseoblock = eq(char, "/") if iseoblock: skip() skipchar(eol) break skipchar("\t") parsestat(indent) def parsefunc(): funcname = lexident() trace("funcname", funcname) emit("void ") emit(funcname) emit("(") first = "1" while True: char = peek() isspace = eq(char, " ") isnotspace = not(isspace) if isnotspace: break skip() var = lexident() isfirst = eq(first, "1") isnotfirst = not(isfirst) if isnotfirst: emit(", ") emit("char * var_") emit(var) first = "0" skipchar(":") skipchar(eol) emit(")\n{\n") parseblock(" ") emit("}\n\n") def emitheader(): emit("char * addstringchar(char * str, char * chr)\n") emit("{\n") emit("}\n") emit("\n") emit("\n") def emitfooter(): emit("") def main(): emitheader() while True: char = peek() iseof = eq(char, eof) if iseof: break while True: char = peek() iseol = eq(char, eol) isnoteol = not(iseol) if isnoteol: break skip() parsefunc() emitfooter() if __name__ == '__main__': main()