414 lines
6.2 KiB
Plaintext
414 lines
6.2 KiB
Plaintext
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[0] < b[0]\n"
|
|
emit "\n"
|
|
emit "def addstringchar(a, b):\n"
|
|
emit " return a + b[0]\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
|
|
/
|