This commit is contained in:
Johan B.W. de Vries 2025-01-12 14:40:57 +01:00
parent 5939b7cba5
commit 3112636825
6 changed files with 3388 additions and 3 deletions

View File

@ -1,17 +1,31 @@
TEE := TEE :=
run: run: it1 it2
it0:
echo "Hand made"
it1:
cat it1-in.lang0 | python3 it0-out.py $(if $(TEE),| tee,> ) it1-out0.py cat it1-in.lang0 | python3 it0-out.py $(if $(TEE),| tee,> ) it1-out0.py
cat it1-in.lang0 | python3 it1-out0.py $(if $(TEE),| tee,> ) it1-out1.py cat it1-in.lang0 | python3 it1-out0.py $(if $(TEE),| tee,> ) it1-out1.py
diff it1-out0.py it1-out1.py > it1-out1.diff diff it1-out0.py it1-out1.py > it1-out1.diff
cat it1-in.lang0 | python3 it1-out1.py $(if $(TEE),| tee,> ) it1-out2.py cat it1-in.lang0 | python3 it1-out1.py $(if $(TEE),| tee,> ) it1-out2.py
diff it1-out1.py it1-out2.py > it1-out2.diff diff it1-out1.py it1-out2.py > it1-out2.diff
cat it1-in.lang0 | python3 it1-out2.py $(if $(TEE),| tee,> ) it1-out3.py cat it1-in.lang0 | python3 it1-out2.py $(if $(TEE),| tee,> ) it1-out.py
diff it1-out2.py it1-out3.py > it1-out3.diff diff it1-out2.py it1-out.py > it1-out.diff
# See how much our hand written code differs from resulting code # See how much our hand written code differs from resulting code
-diff it0-out.py it1-out0.py > it0-out0.diff -diff it0-out.py it1-out0.py > it0-out0.diff
it2:
cat it2-in.lang0 | python3 it1-out.py $(if $(TEE),| tee,> ) it2-out0.py
cat it2-in.lang0 | python3 it2-out0.py $(if $(TEE),| tee,> ) it2-out1.c && gcc it2-out1.c -o it2-out1
cat it2-in.lang0 | it2-out1 $(if $(TEE),| tee,> ) it2-out2.c && gcc it2-out2.c -o it2-out2
cat it2-in.lang0 | it2-out2 $(if $(TEE),| tee,> ) it2-out.c && gcc it2-out.c -o it2-out
clean: clean:
-rm it1-out* -rm it1-out*
.PHONY: it2

384
it2-in.lang0 Normal file
View File

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

372
it2-out0.py Normal file
View File

@ -0,0 +1,372 @@
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()

453
it2-out1.c Normal file
View File

@ -0,0 +1,453 @@
char * addstringchar(char * str, char * chr)
{
}
void increaseindent(char * var_indent)
{
char * var_indent = addstringchar(var_indent, " ");
char * var_indent = addstringchar(var_indent, " ");
char * var_indent = addstringchar(var_indent, " ");
char * var_indent = addstringchar(var_indent, " ");
return var_indent;
}
void lexident()
{
char * var_word = "";
while (1)
{
char * var_char = peek();
char * var_isbeforea = lt(var_char, "a");
if (var_isbeforea)
{
break;
}
char * var_isafterz = lt("z", var_char);
if (var_isafterz)
{
break;
}
char * var_word = addstringchar(var_word, var_char);
skip();
}
return var_word;
}
void parseconststring()
{
skipchar(var_quote);
emit(var_quote);
while (1)
{
char * var_char = peek();
char * var_iseof = eq(var_char, var_eof);
if (var_iseof)
{
break;
}
char * var_isquote = eq(var_char, var_quote);
if (var_isquote)
{
break;
}
emit(var_char);
skip();
}
skipchar(var_quote);
emit(var_quote);
}
void parseexprvarref()
{
char * var_varname = lexident();
emit("var_");
emit(var_varname);
}
void parseexprcall()
{
char * var_funcname = lexident();
emit(var_funcname);
emit("(");
char * var_first = "1";
while (1)
{
char * var_char = peek();
char * var_isspace = eq(var_char, " ");
char * var_isnotspace = not(var_isspace);
if (var_isnotspace)
{
break;
}
skip();
char * var_isfirst = eq(var_first, "1");
char * var_isnotfirst = not(var_isfirst);
if (var_isnotfirst)
{
emit(", ");
}
char * var_char = peek();
char * var_isquote = eq(var_char, var_quote);
char * var_isnotquote = not(var_isquote);
if (var_isquote)
{
parseconststring();
}
if (var_isnotquote)
{
parseexprvarref();
}
char * var_first = "0";
}
emit(")");
}
void parsestatset(char * var_indent)
{
skipchar(" ");
char * var_var = lexident();
skipchar(" ");
emit(var_indent);
emit("char * var_");
emit(var_var);
emit(" = ");
parseconststring();
emit(";");
emit(var_eol);
skipchar(var_eol);
}
void parsestatcalc(char * var_indent)
{
skipchar(" ");
char * var_var = lexident();
skipchar(" ");
emit(var_indent);
emit("char * var_");
emit(var_var);
emit(" = ");
parseexprcall();
emit(";");
emit(var_eol);
skipchar(var_eol);
}
void parsestatif(char * var_indent)
{
skipchar(" ");
emit(var_indent);
emit("if (");
parseexprvarref();
emit(")\n");
emit(var_indent);
emit("{\n");
skipchar(var_eol);
char * var_indentt = increaseindent(var_indent);
parseblock(var_indentt);
emit(var_indent);
emit("}\n");
}
void parsestatforever(char * var_indent)
{
emit(var_indent);
emit("while (1)\n");
emit(var_indent);
emit("{\n");
skipchar(var_eol);
char * var_indentt = increaseindent(var_indent);
parseblock(var_indentt);
emit(var_indent);
emit("}\n");
}
void parsestatbreak(char * var_indent)
{
emit(var_indent);
emit("break;\n");
skipchar(var_eol);
}
void parsestatreturn(char * var_indent)
{
emit(var_indent);
emit("return ");
char * var_char = peek();
char * var_isspace = eq(var_char, " ");
if (var_isspace)
{
skip();
parseexprvarref();
}
emit(";");
emit(var_eol);
skipchar(var_eol);
}
void parsestatemit(char * var_indent)
{
emit(var_indent);
emit("emit(");
skipchar(" ");
char * var_char = peek();
char * var_isquote = eq(var_char, var_quote);
char * var_isnotquote = not(var_isquote);
if (var_isquote)
{
parseconststring();
}
if (var_isnotquote)
{
parseexprvarref();
}
emit(");\n");
skipchar(var_eol);
}
void parsestattrace(char * var_indent)
{
emit(var_indent);
emit("trace(");
emit(var_quote);
skipchar(" ");
char * var_varname = lexident();
emit(var_varname);
emit(var_quote);
emit(", ");
emit(var_varname);
emit(")\n");
skipchar(var_eol);
}
void parsestatskipchar(char * var_indent)
{
skipchar(" ");
emit(var_indent);
emit("skipchar(");
char * var_char = peek();
char * var_isquote = eq(var_char, var_quote);
char * var_isnotquote = not(var_isquote);
if (var_isquote)
{
parseconststring();
}
if (var_isnotquote)
{
parseexprvarref();
}
emit(");\n");
skipchar(var_eol);
}
void parsestat(char * var_indent)
{
char * var_call = lexident();
trace("call", call)
char * var_isset = eq(var_call, "set");
if (var_isset)
{
parsestatset(var_indent);
return ;
}
char * var_iscalc = eq(var_call, "calc");
if (var_iscalc)
{
parsestatcalc(var_indent);
return ;
}
char * var_isif = eq(var_call, "if");
if (var_isif)
{
parsestatif(var_indent);
return ;
}
char * var_isforever = eq(var_call, "forever");
if (var_isforever)
{
parsestatforever(var_indent);
return ;
}
char * var_isbreak = eq(var_call, "break");
if (var_isbreak)
{
parsestatbreak(var_indent);
return ;
}
char * var_isreturn = eq(var_call, "return");
if (var_isreturn)
{
parsestatreturn(var_indent);
return ;
}
char * var_isemit = eq(var_call, "emit");
if (var_isemit)
{
parsestatemit(var_indent);
return ;
}
char * var_istrace = eq(var_call, "trace");
if (var_istrace)
{
parsestattrace(var_indent);
return ;
}
char * var_isskipchar = eq(var_call, "skipchar");
if (var_isskipchar)
{
parsestatskipchar(var_indent);
return ;
}
emit(var_indent);
emit(var_call);
emit("(");
char * var_first = "1";
while (1)
{
char * var_char = peek();
char * var_isspace = eq(var_char, " ");
char * var_isnotspace = not(var_isspace);
if (var_isnotspace)
{
break;
}
skip();
char * var_char = peek();
char * var_isquote = eq(var_char, var_quote);
char * var_isnotquote = not(var_isquote);
if (var_isquote)
{
parseconststring();
}
if (var_isnotquote)
{
parseexprvarref();
}
char * var_isfirst = eq(var_first, "1");
char * var_isnotfirst = not(var_isfirst);
if (var_isnotfirst)
{
emit(", ");
}
char * var_first = "0";
}
skipchar(var_eol);
emit(");\n");
}
void parseblock(char * var_indent)
{
while (1)
{
while (1)
{
char * var_char = peek();
char * var_iseol = eq(var_char, var_eol);
char * var_isnoteol = not(var_iseol);
if (var_isnoteol)
{
break;
}
skip();
}
char * var_copy = " ";
while (1)
{
char * var_isdone = eq(var_copy, var_indent);
if (var_isdone)
{
break;
}
skipchar("\t");
char * var_copy = increaseindent(var_copy);
}
char * var_char = peek();
char * var_iseoblock = eq(var_char, "/");
if (var_iseoblock)
{
skip();
skipchar(var_eol);
break;
}
skipchar("\t");
parsestat(var_indent);
}
}
void parsefunc()
{
char * var_funcname = lexident();
trace("funcname", funcname)
emit("void ");
emit(var_funcname);
emit("(");
char * var_first = "1";
while (1)
{
char * var_char = peek();
char * var_isspace = eq(var_char, " ");
char * var_isnotspace = not(var_isspace);
if (var_isnotspace)
{
break;
}
skip();
char * var_var = lexident();
char * var_isfirst = eq(var_first, "1");
char * var_isnotfirst = not(var_isfirst);
if (var_isnotfirst)
{
emit(", ");
}
emit("char * var_");
emit(var_var);
char * var_first = "0";
}
skipchar(":");
skipchar(var_eol);
emit(")\n{\n");
parseblock(" ");
emit("}\n\n");
}
void emitheader()
{
emit("char * addstringchar(char * str, char * chr)\n");
emit("{\n");
emit("}\n");
emit("\n");
emit("\n");
}
void emitfooter()
{
emit("");
}
void main()
{
emitheader();
while (1)
{
char * var_char = peek();
char * var_iseof = eq(var_char, var_eof);
if (var_iseof)
{
break;
}
while (1)
{
char * var_char = peek();
char * var_iseol = eq(var_char, var_eol);
char * var_isnoteol = not(var_iseol);
if (var_isnoteol)
{
break;
}
skip();
}
parsefunc();
}
emitfooter();
}

2162
t-diagram.excalidraw Normal file

File diff suppressed because it is too large Load Diff

BIN
t-diagram.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB