lang0/1-lang0py/lang0py.lang0
Johan B.W. de Vries 2eaa763a2c Remove skipchar, add stdinlineno / stdincolno
With the new check function, this helper method doesn't make
much sense to put in the standard library.

To replicate the same result, we do need to expose the current
line number; adding column number is a nice bonus.

Also; made it a bit clearer when a check failes in it2.

Also; the builtincheckfalse was not working.

Also; separated out the test input file to have more data.
2025-02-09 15:38:02 +01:00

507 lines
7.4 KiB
Plaintext

skipchar exp:
declare act
declare lineno
declare colno
calc act peek
calc lineno stdinlineno
calc colno stdincolno
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
skip
/
emitln data:
emit data
emit eol
/
increaseindent indent:
calc indent addstringchar indent " "
calc indent addstringchar indent " "
calc indent addstringchar indent " "
calc indent addstringchar indent " "
return indent
/
lexident:
declare word
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 ")"
/
parsestatdeclare indent:
skipchar " "
calc var lexident
skipchar eol
/
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
/
parseblock indent/
parsestatif indent:
skipchar " "
emit indent
emit "if "
parseexprvarref
emitln ":"
skipchar eol
calc indent increaseindent indent
parseblock indent
/
parsestatforever indent:
emit indent
emitln "while True:"
skipchar eol
calc indent increaseindent indent
parseblock indent
/
parsestatbreak indent:
emit indent
emitln "break"
skipchar eol
/
parsestatreturn indent:
emit indent
emit "return "
calc char peek
calc isspace eq char " "
if isspace
skip
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
/
emit eol
skipchar eol
/
parsestatcheck indent:
declare char
declare funcname
declare iscolon
declare isnotquote
declare isquote
declare notfirst
skipchar " "
emit indent
emit "assert "
calc funcname lexident
emit funcname
emit "("
set notfirst ""
forever
skipchar " "
calc char peek
calc iscolon eq char ":"
if iscolon
break
/
if notfirst
emit ", "
/
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
set notfirst "1"
/
skipchar ":"
emit "), ("
set notfirst ""
forever
skipchar " "
if notfirst
emit ", "
/
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
calc char peek
calc iseol eq char eol
if iseol
break
/
set notfirst "1"
/
emitln ")"
/
parsestattrace indent:
emit indent
emit "trace("
emit quote
skipchar " "
calc varname lexident
emit varname
emit quote
emit ", "
emit varname
emitln ")"
skipchar eol
/
parsestat indent:
calc call lexident
trace call
calc isset eq call "declare"
if isset
parsestatdeclare indent
return
/
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 istrace eq call "trace"
if istrace
parsestattrace indent
return
/
calc ischeck eq call "check"
if ischeck
parsestatcheck 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 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"
/
skipchar eol
emitln ")"
/
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 isnotfirst ""
forever
calc char peek
calc isspace eq char " "
calc isnotspace not isspace
if isnotspace
break
/
skip
calc var lexident
if isnotfirst
emit ", "
/
emit var
set isnotfirst "1"
/
calc char peek
calc iseoblock eq char "/"
if iseoblock
skipchar "/"
skipchar eol
emitln "):"
emitln " pass # ahead declaration"
emit eol
return
/
skipchar ":"
skipchar eol
emitln "):"
parseblock " "
emit eol
/
emitheader:
emitln "import os"
emitln "import sys"
emitln ""
emitln "def eq(a, b):"
emitln " return a == b"
emitln ""
emitln "def lt(a, b):"
emitln " return a[0] < b[0]"
emitln ""
emitln "def addstringchar(a, b):"
emitln " return a + b[0]"
emitln ""
emitln "def emit(string):"
emitln " sys.stdout.write(string)"
emitln " sys.stdout.flush()"
emitln ""
emitln "def trace(header, value):"
emitln " if os.environ.get('TRACE'):"
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
emitln ""
emitln "eof = chr(0)"
emitln "eol = chr(10)"
emitln "quote = chr(34)"
emitln ""
emitln "STDINCOLNO = 0"
emitln "STDINLINENO = 1"
emitln "STDINPEEK = None"
emitln ""
emitln "def _readchar():"
emitln " char = sys.stdin.read(1)"
emitln " trace('char', char)"
emitln " if not char:"
emitln " return eof"
emitln " return char"
emitln ""
emitln "def peek():"
emitln " return STDINPEEK"
emitln ""
emitln "def skip():"
emitln " global STDINCOLNO"
emitln " global STDINLINENO"
emitln " global STDINPEEK"
emitln " if eol == STDINPEEK:"
emitln " STDINLINENO += 1"
emitln " STDINCOLNO = 0"
emitln " STDINCOLNO += 1"
emitln " STDINPEEK = _readchar()"
emitln ""
emitln "def stdinlineno():"
emitln " global STDINLINENO"
emitln " return str(STDINLINENO)"
emitln ""
emitln "def stdincolno():"
emitln " global STDINCOLNO"
emitln " return str(STDINCOLNO)"
emitln ""
emitln "skip()"
emitln ""
/
emitfooter:
emitln "if __name__ == '__main__':"
emitln " main()"
/
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
/