lang0/it2-out0.py
Johan B.W. de Vries 3112636825 Idea
2025-01-12 14:40:57 +01:00

373 lines
7.4 KiB
Python

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()