First version
This commit is contained in:
parent
49662a9a78
commit
98166bfa2e
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/it0-out0.diff
|
||||
/it1-out*
|
||||
17
Makefile
Normal file
17
Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
TEE :=
|
||||
|
||||
run:
|
||||
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
|
||||
diff it1-out0.py it1-out1.py > it1-out1.diff
|
||||
cat it1-in.lang0 | python3 it1-out1.py $(if $(TEE),| tee,> ) it1-out2.py
|
||||
diff it1-out1.py it1-out2.py > it1-out2.diff
|
||||
cat it1-in.lang0 | python3 it1-out2.py $(if $(TEE),| tee,> ) it1-out3.py
|
||||
diff it1-out2.py it1-out3.py > it1-out3.diff
|
||||
|
||||
# See how much our hand written code differs from resulting code
|
||||
-diff it0-out.py it1-out0.py > it0-out0.diff
|
||||
|
||||
clean:
|
||||
-rm it1-out*
|
||||
362
it0-out.py
Normal file
362
it0-out.py
Normal file
@ -0,0 +1,362 @@
|
||||
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 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 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 parsestatemit(indent):
|
||||
skipchar(' ')
|
||||
emit(' ' * indent)
|
||||
emit('emit(')
|
||||
|
||||
if quote == peek():
|
||||
parseconststring()
|
||||
else:
|
||||
parseexprvarref()
|
||||
skipchar(eol)
|
||||
|
||||
emit(')\n')
|
||||
|
||||
def parsestattrace(indent):
|
||||
skipchar(' ')
|
||||
emit(' ' * indent)
|
||||
emit('trace("')
|
||||
|
||||
var_name = lexident()
|
||||
skipchar(eol)
|
||||
|
||||
emit(var_name)
|
||||
emit('", ')
|
||||
emit(var_name)
|
||||
emit(')\n')
|
||||
|
||||
def parsestatskipchar(indent):
|
||||
skipchar(' ')
|
||||
emit(' ' * indent)
|
||||
emit('skipchar(')
|
||||
if quote == peek():
|
||||
parseconststring()
|
||||
else:
|
||||
parseexprvarref()
|
||||
emit(')\n')
|
||||
skipchar(eol)
|
||||
|
||||
def parsestat(indent):
|
||||
call = lexident()
|
||||
trace('call', call)
|
||||
|
||||
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 == "emit":
|
||||
parsestatemit(indent)
|
||||
return
|
||||
|
||||
if call == "trace":
|
||||
parsestattrace(indent)
|
||||
return
|
||||
|
||||
if call == "skipchar":
|
||||
parsestatskipchar(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
|
||||
|
||||
skipchar(':')
|
||||
skipchar(eol)
|
||||
|
||||
emit('):\n')
|
||||
|
||||
parseblock(1)
|
||||
|
||||
emit("\n")
|
||||
|
||||
def emitheader():
|
||||
emit("import os\n")
|
||||
emit("import sys\n")
|
||||
emit("\n")
|
||||
emit("def eq(a, b):\n")
|
||||
emit(" return a == b\n")
|
||||
emit("\n")
|
||||
emit("def lt(a, b):\n")
|
||||
emit(" return a < b\n")
|
||||
emit("\n")
|
||||
emit("def addstringchar(a, b):\n")
|
||||
emit(" return a + b\n")
|
||||
emit("\n")
|
||||
emit("def emit(string):\n")
|
||||
emit(" sys.stdout.write(string)\n")
|
||||
emit("\n")
|
||||
emit("def trace(header, value):\n")
|
||||
emit(" if os.environ.get('TRACE'):\n")
|
||||
emit(" sys.stderr.write(f'{header}={value!r}\\n')\n")
|
||||
emit("\n")
|
||||
emit("eof = chr(0)\n")
|
||||
emit("eol = chr(10)\n")
|
||||
emit("quote = chr(34)\n")
|
||||
emit("PEEK = None\n")
|
||||
emit("LINE = 1\n")
|
||||
emit("\n")
|
||||
emit("def peek():\n")
|
||||
emit(" global PEEK\n")
|
||||
emit(" if PEEK is None:\n")
|
||||
emit(" char = sys.stdin.read(1)\n")
|
||||
emit(" trace('char', char)\n")
|
||||
emit(" if not char:\n")
|
||||
emit(" PEEK = eof\n")
|
||||
emit(" else:\n")
|
||||
emit(" PEEK = char\n")
|
||||
emit(" return PEEK\n")
|
||||
emit("\n")
|
||||
emit("def skip():\n")
|
||||
emit(" global LINE\n")
|
||||
emit(" global PEEK\n")
|
||||
emit(" if eol == PEEK:\n")
|
||||
emit(" LINE += 1\n")
|
||||
emit(" PEEK = None\n")
|
||||
emit("\n")
|
||||
emit("def skipchar(char):\n")
|
||||
emit(" global LINE\n")
|
||||
emit(" assert char == peek(), (LINE, char, peek())\n")
|
||||
emit(" skip()\n")
|
||||
emit("\n")
|
||||
|
||||
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()
|
||||
413
it1-in.lang0
Normal file
413
it1-in.lang0
Normal file
@ -0,0 +1,413 @@
|
||||
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 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 var
|
||||
emit " = "
|
||||
parseconststring
|
||||
emit eol
|
||||
skipchar eol
|
||||
/
|
||||
|
||||
parsestatcalc indent:
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit var
|
||||
emit " = "
|
||||
parseexprcall
|
||||
emit eol
|
||||
skipchar eol
|
||||
/
|
||||
|
||||
parsestatif indent:
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "if "
|
||||
parseexprvarref
|
||||
emit ":\n"
|
||||
skipchar eol
|
||||
calc indent increaseindent indent
|
||||
parseblock indent
|
||||
/
|
||||
|
||||
parsestatforever indent:
|
||||
emit indent
|
||||
emit "while True:\n"
|
||||
skipchar eol
|
||||
calc indent increaseindent indent
|
||||
parseblock indent
|
||||
/
|
||||
|
||||
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 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 "def "
|
||||
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 var
|
||||
set first "0"
|
||||
/
|
||||
skipchar ":"
|
||||
skipchar eol
|
||||
emit "):\n"
|
||||
parseblock " "
|
||||
emit "\n"
|
||||
/
|
||||
|
||||
emitheader:
|
||||
emit "import os\n"
|
||||
emit "import sys\n"
|
||||
emit "\n"
|
||||
emit "def eq(a, b):\n"
|
||||
emit " return a == b\n"
|
||||
emit "\n"
|
||||
emit "def lt(a, b):\n"
|
||||
emit " return a < b\n"
|
||||
emit "\n"
|
||||
emit "def addstringchar(a, b):\n"
|
||||
emit " return a + b\n"
|
||||
emit "\n"
|
||||
emit "def emit(string):\n"
|
||||
emit " sys.stdout.write(string)\n"
|
||||
emit "\n"
|
||||
emit "def trace(header, value):\n"
|
||||
emit " if os.environ.get('TRACE'):\n"
|
||||
emit " sys.stderr.write(f'{header}={value!r}\\n')\n"
|
||||
emit "\n"
|
||||
emit "eof = chr(0)\n"
|
||||
emit "eol = chr(10)\n"
|
||||
emit "quote = chr(34)\n"
|
||||
emit "PEEK = None\n"
|
||||
emit "LINE = 1\n"
|
||||
emit "\n"
|
||||
emit "def peek():\n"
|
||||
emit " global PEEK\n"
|
||||
emit " if PEEK is None:\n"
|
||||
emit " char = sys.stdin.read(1)\n"
|
||||
emit " trace('char', char)\n"
|
||||
emit " if not char:\n"
|
||||
emit " PEEK = eof\n"
|
||||
emit " else:\n"
|
||||
emit " PEEK = char\n"
|
||||
emit " return PEEK\n"
|
||||
emit "\n"
|
||||
emit "def skip():\n"
|
||||
emit " global LINE\n"
|
||||
emit " global PEEK\n"
|
||||
emit " if eol == PEEK:\n"
|
||||
emit " LINE += 1\n"
|
||||
emit " PEEK = None\n"
|
||||
emit "\n"
|
||||
emit "def skipchar(char):\n"
|
||||
emit " global LINE\n"
|
||||
emit " assert char == peek(), (LINE, char, peek())\n"
|
||||
emit " skip()\n"
|
||||
emit "\n"
|
||||
/
|
||||
|
||||
emitfooter:
|
||||
emit "if __name__ == '__main__':\n"
|
||||
emit " main()\n"
|
||||
/
|
||||
|
||||
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
|
||||
/
|
||||
Loading…
x
Reference in New Issue
Block a user