Feat: Adds mapclear, mapgetkey, mapsetkey
Feat: Error on undefined function Fix: All ids are now prefix to prevent native var clashes. Chore: __check helper function for ease of use
This commit is contained in:
parent
6055cddab2
commit
68e3c12d80
@ -39,6 +39,36 @@ def skip():
|
|||||||
|
|
||||||
PEEK = None
|
PEEK = None
|
||||||
|
|
||||||
|
def __check(func, args: list[str], msg: list[str]) -> None:
|
||||||
|
result = func(*args)
|
||||||
|
if result:
|
||||||
|
return
|
||||||
|
|
||||||
|
sys.stderr.write('ERROR: ' + ' '.join(msg) + '\n')
|
||||||
|
sys.stderr.flush()
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
MAPSTORE = {}
|
||||||
|
|
||||||
|
def mapclear(mapname: str) -> str:
|
||||||
|
MAPSTORE.pop(mapname)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def mapgetkey(mapname: str, key: str, default: str) -> str:
|
||||||
|
return MAPSTORE.get(mapname, {}).get(key, default)
|
||||||
|
|
||||||
|
def mapsetkey(mapname: str, key: str, value: str) -> str:
|
||||||
|
MAPSTORE.setdefault(mapname, {})
|
||||||
|
MAPSTORE[mapname][key] = value
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def registerid(id: str) -> str:
|
||||||
|
idname = mapgetkey("REGISTERID", id, "")
|
||||||
|
if idname:
|
||||||
|
return idname
|
||||||
|
idname = "id_" + id
|
||||||
|
return idname
|
||||||
|
|
||||||
def emitln(data):
|
def emitln(data):
|
||||||
emit(data)
|
emit(data)
|
||||||
emit(eol)
|
emit(eol)
|
||||||
@ -81,12 +111,15 @@ def parseconststring():
|
|||||||
emit(quote)
|
emit(quote)
|
||||||
|
|
||||||
def parseexprvarref():
|
def parseexprvarref():
|
||||||
var = lexident()
|
varname = lexident()
|
||||||
emit(var)
|
varid = registerid(varname)
|
||||||
|
emit(varid)
|
||||||
|
|
||||||
def parseexprcall():
|
def parseexprcall():
|
||||||
funcname = lexident()
|
funcname = lexident()
|
||||||
emit(funcname)
|
__check(mapgetkey, ["FUNCREG", funcname, ""], ["Function", funcname, "does not exist"])
|
||||||
|
funcid = registerid(funcname)
|
||||||
|
emit(funcid)
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
@ -109,11 +142,12 @@ def parsestatdeclare(indent):
|
|||||||
|
|
||||||
def parsestatset(indent):
|
def parsestatset(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
var = lexident()
|
varname = lexident()
|
||||||
|
varid = registerid(varname)
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(var)
|
emit(varid)
|
||||||
emit(' = ')
|
emit(' = ')
|
||||||
|
|
||||||
parseconststring()
|
parseconststring()
|
||||||
@ -123,11 +157,12 @@ def parsestatset(indent):
|
|||||||
|
|
||||||
def parsestatcalc(indent):
|
def parsestatcalc(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
var = lexident()
|
varname = lexident()
|
||||||
|
varid = registerid(varname)
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(var)
|
emit(varid)
|
||||||
emit(' = ')
|
emit(' = ')
|
||||||
|
|
||||||
parseexprcall()
|
parseexprcall()
|
||||||
@ -174,11 +209,13 @@ def parsestatreturn(indent):
|
|||||||
def parsestatcheck(indent):
|
def parsestatcheck(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit('if not ')
|
emit('__check(')
|
||||||
|
|
||||||
func_name = lexident()
|
funcname = lexident()
|
||||||
emit(func_name)
|
funcid = registerid(funcname)
|
||||||
emit('(')
|
trace("funcid", funcid)
|
||||||
|
emit(funcid)
|
||||||
|
emit(', [')
|
||||||
notfirst = False
|
notfirst = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -199,9 +236,7 @@ def parsestatcheck(indent):
|
|||||||
|
|
||||||
skipchar(':')
|
skipchar(':')
|
||||||
|
|
||||||
emitln('):')
|
emit('], [')
|
||||||
emit(' ' * (indent + 1))
|
|
||||||
emit('sys.stderr.write(\' \'.join(["ERROR:", ')
|
|
||||||
notfirst = False
|
notfirst = False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -218,23 +253,21 @@ def parsestatcheck(indent):
|
|||||||
if eol == peek():
|
if eol == peek():
|
||||||
break
|
break
|
||||||
notfirst = True
|
notfirst = True
|
||||||
emitln(']))')
|
|
||||||
emit(' ' * (indent + 1))
|
emitln('])')
|
||||||
emitln('sys.stderr.write(eol)')
|
|
||||||
emit(' ' * (indent + 1))
|
|
||||||
emitln('sys.exit(1)')
|
|
||||||
|
|
||||||
def parsestattrace(indent):
|
def parsestattrace(indent):
|
||||||
skipchar(' ')
|
skipchar(' ')
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit('trace("')
|
emit('__trace("')
|
||||||
|
|
||||||
var_name = lexident()
|
varname = lexident()
|
||||||
|
varid = registerid(varname)
|
||||||
skipchar(eol)
|
skipchar(eol)
|
||||||
|
|
||||||
emit(var_name)
|
emit(varname)
|
||||||
emit('", ')
|
emit('", ')
|
||||||
emit(var_name)
|
emit(varid)
|
||||||
emitln(')')
|
emitln(')')
|
||||||
|
|
||||||
def parsestat(indent):
|
def parsestat(indent):
|
||||||
@ -277,8 +310,10 @@ def parsestat(indent):
|
|||||||
parsestattrace(indent)
|
parsestattrace(indent)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
funcid = registerid(call)
|
||||||
|
|
||||||
emit(' ' * indent)
|
emit(' ' * indent)
|
||||||
emit(call)
|
emit(funcid)
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
@ -315,19 +350,22 @@ def parseblock(indent):
|
|||||||
|
|
||||||
def parsefunc():
|
def parsefunc():
|
||||||
funcname = lexident()
|
funcname = lexident()
|
||||||
|
funcid = registerid(funcname)
|
||||||
|
mapsetkey("FUNCREG", funcname, "1")
|
||||||
|
|
||||||
trace('funcname', funcname)
|
trace('funcname', funcname)
|
||||||
emit('def ')
|
emit('def ')
|
||||||
emit(funcname)
|
emit(funcid)
|
||||||
emit('(')
|
emit('(')
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
while ' ' == peek():
|
while ' ' == peek():
|
||||||
skip()
|
skip()
|
||||||
var = lexident()
|
varname = lexident()
|
||||||
|
varid = registerid(varname)
|
||||||
if not first:
|
if not first:
|
||||||
emit(", ")
|
emit(", ")
|
||||||
emit(var)
|
emit(varid)
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
if '/' == peek():
|
if '/' == peek():
|
||||||
@ -352,26 +390,26 @@ def emitheader():
|
|||||||
emitln("import os")
|
emitln("import os")
|
||||||
emitln("import sys")
|
emitln("import sys")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def eq(a: str, b: str) -> str:")
|
emitln("def __eq(a: str, b: str) -> str:")
|
||||||
emitln(" return '1' if a == b else ''")
|
emitln(" return '1' if a == b else ''")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def lt(a: str, b: str) -> str:")
|
emitln("def __lt(a: str, b: str) -> str:")
|
||||||
emitln(" return '1' if a < b else ''")
|
emitln(" return '1' if a < b else ''")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def add(a: str, b: str) -> str:")
|
emitln("def __add(a: str, b: str) -> str:")
|
||||||
emitln(" return a + b")
|
emitln(" return a + b")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def emit(string):")
|
emitln("def __emit(string):")
|
||||||
emitln(" sys.stdout.buffer.write(string.encode('latin_1'))")
|
emitln(" sys.stdout.buffer.write(string.encode('latin_1'))")
|
||||||
emitln(" sys.stdout.flush()")
|
emitln(" sys.stdout.flush()")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def trace(header, value):")
|
emitln("def __trace(header, value):")
|
||||||
emitln(" if os.environ.get('TRACE'):")
|
emitln(" if os.environ.get('TRACE'):")
|
||||||
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
|
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("eof = chr(0xFF)")
|
emitln("__EOF = chr(0xFF)")
|
||||||
emitln("eol = chr(10)")
|
emitln("__EOL = chr(10)")
|
||||||
emitln("quote = chr(34)")
|
emitln("__QUOTE = chr(34)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("STDINCOLNO = 0")
|
emitln("STDINCOLNO = 0")
|
||||||
emitln("STDINLINENO = 1")
|
emitln("STDINLINENO = 1")
|
||||||
@ -379,41 +417,103 @@ def emitheader():
|
|||||||
emitln("")
|
emitln("")
|
||||||
emitln("def _readchar():")
|
emitln("def _readchar():")
|
||||||
emitln(" char = sys.stdin.read(1)")
|
emitln(" char = sys.stdin.read(1)")
|
||||||
emitln(" trace('char', char)")
|
emitln(" __trace('char', char)")
|
||||||
emitln(" if not char:")
|
emitln(" if not char:")
|
||||||
emitln(" return eof")
|
emitln(" return __EOF")
|
||||||
emitln(" return char")
|
emitln(" return char")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def peek():")
|
emitln("def __peek():")
|
||||||
emitln(" return STDINPEEK")
|
emitln(" return STDINPEEK")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def skip():")
|
emitln("def __skip():")
|
||||||
emitln(" global STDINCOLNO")
|
emitln(" global STDINCOLNO")
|
||||||
emitln(" global STDINLINENO")
|
emitln(" global STDINLINENO")
|
||||||
emitln(" global STDINPEEK")
|
emitln(" global STDINPEEK")
|
||||||
emitln(" if eol == STDINPEEK:")
|
emitln(" if __EOL == STDINPEEK:")
|
||||||
emitln(" STDINLINENO += 1")
|
emitln(" STDINLINENO += 1")
|
||||||
emitln(" STDINCOLNO = 0")
|
emitln(" STDINCOLNO = 0")
|
||||||
emitln(" STDINCOLNO += 1")
|
emitln(" STDINCOLNO += 1")
|
||||||
emitln(" STDINPEEK = _readchar()")
|
emitln(" STDINPEEK = _readchar()")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def stdinlineno():")
|
emitln("def __stdinlineno():")
|
||||||
emitln(" global STDINLINENO")
|
emitln(" global STDINLINENO")
|
||||||
emitln(" return str(STDINLINENO)")
|
emitln(" return str(STDINLINENO)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("def stdincolno():")
|
emitln("def __stdincolno():")
|
||||||
emitln(" global STDINCOLNO")
|
emitln(" global STDINCOLNO")
|
||||||
emitln(" return str(STDINCOLNO)")
|
emitln(" return str(STDINCOLNO)")
|
||||||
emitln("")
|
emitln("")
|
||||||
emitln("skip()")
|
emitln("__skip()")
|
||||||
emitln("")
|
emitln("")
|
||||||
|
emitln("MAPSTORE = {}")
|
||||||
|
emitln("")
|
||||||
|
emitln("def __mapclear(mapname: str) -> str:")
|
||||||
|
emitln(" MAPSTORE.pop(mapname)")
|
||||||
|
emitln(" return ''")
|
||||||
|
emitln("")
|
||||||
|
emitln("def __mapgetkey(mapname: str, key: str, default: str) -> str:")
|
||||||
|
emitln(" return MAPSTORE.get(mapname, {}).get(key, default)")
|
||||||
|
emitln("")
|
||||||
|
emitln("def __mapsetkey(mapname: str, key: str, value: str) -> str:")
|
||||||
|
emitln(" MAPSTORE.setdefault(mapname, {})")
|
||||||
|
emitln(" MAPSTORE[mapname][key] = value")
|
||||||
|
emitln(" return ''")
|
||||||
|
emitln("")
|
||||||
|
emitln("def __not(a: str) -> str:")
|
||||||
|
emitln(" if a:")
|
||||||
|
emitln(" return ''")
|
||||||
|
emitln(" return '1'")
|
||||||
|
emitln("")
|
||||||
|
emitln("def __check(func, args: list[str], msg: list[str]) -> None:")
|
||||||
|
emitln(" result = func(*args)")
|
||||||
|
emitln(" if result:")
|
||||||
|
emitln(" return")
|
||||||
|
emitln("")
|
||||||
|
emitln(" sys.stderr.write('ERROR: ' + ' '.join(msg) + '\\n')")
|
||||||
|
emitln(" sys.stderr.flush()")
|
||||||
|
emitln(" exit(1)")
|
||||||
|
|
||||||
def emitfooter():
|
def emitfooter():
|
||||||
emit("if __name__ == '__main__':\n")
|
mainname = registerid("main")
|
||||||
emit(" main()\n")
|
emitln("if __name__ == '__main__':")
|
||||||
|
emit(" ")
|
||||||
|
emit(mainname)
|
||||||
|
emitln("()")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
emitheader()
|
emitheader()
|
||||||
|
|
||||||
|
# Standard library constants
|
||||||
|
mapsetkey("REGISTERID", "eof", "__EOF")
|
||||||
|
mapsetkey("REGISTERID", "eol", "__EOL")
|
||||||
|
mapsetkey("REGISTERID", "quote", "__QUOTE")
|
||||||
|
|
||||||
|
# Standard library functions
|
||||||
|
mapsetkey("FUNCREG", "add", "1")
|
||||||
|
mapsetkey("REGISTERID", "add", "__add")
|
||||||
|
mapsetkey("FUNCREG", "emit", "1")
|
||||||
|
mapsetkey("REGISTERID", "emit", "__emit")
|
||||||
|
mapsetkey("FUNCREG", "eq", "1")
|
||||||
|
mapsetkey("REGISTERID", "eq", "__eq")
|
||||||
|
mapsetkey("FUNCREG", "lt", "1")
|
||||||
|
mapsetkey("REGISTERID", "lt", "__lt")
|
||||||
|
mapsetkey("FUNCREG", "not", "1")
|
||||||
|
mapsetkey("REGISTERID", "not", "__not")
|
||||||
|
mapsetkey("FUNCREG", "mapclear", "1")
|
||||||
|
mapsetkey("REGISTERID", "mapclear", "__mapclear")
|
||||||
|
mapsetkey("FUNCREG", "mapgetkey", "1")
|
||||||
|
mapsetkey("REGISTERID", "mapgetkey", "__mapgetkey")
|
||||||
|
mapsetkey("FUNCREG", "mapsetkey", "1")
|
||||||
|
mapsetkey("REGISTERID", "mapsetkey", "__mapsetkey")
|
||||||
|
mapsetkey("FUNCREG", "peek", "1")
|
||||||
|
mapsetkey("REGISTERID", "peek", "__peek")
|
||||||
|
mapsetkey("FUNCREG", "skip", "1")
|
||||||
|
mapsetkey("REGISTERID", "skip", "__skip")
|
||||||
|
mapsetkey("FUNCREG", "stdincolno", "1")
|
||||||
|
mapsetkey("REGISTERID", "stdincolno", "__stdincolno")
|
||||||
|
mapsetkey("FUNCREG", "stdinlineno", "1")
|
||||||
|
mapsetkey("REGISTERID", "stdinlineno", "__stdinlineno")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if eof == peek():
|
if eof == peek():
|
||||||
break
|
break
|
||||||
|
|||||||
@ -36,5 +36,8 @@ lang0py.py: lang0py.lang0 lang0py2.exe
|
|||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
-diff lang0py2.py lang0py.py
|
-diff lang0py2.py lang0py.py
|
||||||
|
|
||||||
|
$(LANG0PY): $(CURDIR)/../0-lang0py/lang0py.py $(CURDIR)/../0-lang0py/lang0py.lang0
|
||||||
|
cd ../0-lang0py && make lang0py.exe
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f lang0py*.py lang0py*.c lang0py*.o lang0py*.exe
|
rm -f lang0py*.py lang0py*.c lang0py*.o lang0py*.exe
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
skipchar exp:
|
registerid id:
|
||||||
declare act
|
declare idname
|
||||||
declare lineno
|
declare newidx
|
||||||
declare colno
|
|
||||||
calc act peek
|
calc idname mapgetkey "REGISTERID" id ""
|
||||||
calc lineno stdinlineno
|
if idname
|
||||||
calc colno stdincolno
|
return idname
|
||||||
check eq exp act : "Unexpected character" act "expected" exp "at" lineno colno
|
/
|
||||||
skip
|
|
||||||
|
calc idname add "id_" id
|
||||||
|
return idname
|
||||||
/
|
/
|
||||||
|
|
||||||
emitln data:
|
emitln data:
|
||||||
@ -14,11 +16,6 @@ emitln data:
|
|||||||
emit eol
|
emit eol
|
||||||
/
|
/
|
||||||
|
|
||||||
increaseindent indent:
|
|
||||||
calc indent add indent " "
|
|
||||||
return indent
|
|
||||||
/
|
|
||||||
|
|
||||||
lexident:
|
lexident:
|
||||||
declare word
|
declare word
|
||||||
set word ""
|
set word ""
|
||||||
@ -38,6 +35,22 @@ lexident:
|
|||||||
return word
|
return word
|
||||||
/
|
/
|
||||||
|
|
||||||
|
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
|
||||||
|
/
|
||||||
|
|
||||||
|
increaseindent indent:
|
||||||
|
calc indent add indent " "
|
||||||
|
return indent
|
||||||
|
/
|
||||||
|
|
||||||
parseconststring:
|
parseconststring:
|
||||||
skipchar quote
|
skipchar quote
|
||||||
emit quote
|
emit quote
|
||||||
@ -60,12 +73,15 @@ parseconststring:
|
|||||||
|
|
||||||
parseexprvarref:
|
parseexprvarref:
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
emit varname
|
calc varid registerid varname
|
||||||
|
emit varid
|
||||||
/
|
/
|
||||||
|
|
||||||
parseexprcall:
|
parseexprcall:
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
emit funcname
|
calc funcid registerid funcname
|
||||||
|
check mapgetkey "FUNCREG" funcname "" : "Function" funcname "does not exist"
|
||||||
|
emit funcid
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -97,16 +113,18 @@ parseexprcall:
|
|||||||
|
|
||||||
parsestatdeclare indent:
|
parsestatdeclare indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc var lexident
|
calc varname lexident
|
||||||
|
calc varid registerid varname
|
||||||
skipchar eol
|
skipchar eol
|
||||||
/
|
/
|
||||||
|
|
||||||
parsestatset indent:
|
parsestatset indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc var lexident
|
calc varname lexident
|
||||||
|
calc varid registerid varname
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit var
|
emit varid
|
||||||
emit " = "
|
emit " = "
|
||||||
parseconststring
|
parseconststring
|
||||||
emit eol
|
emit eol
|
||||||
@ -115,10 +133,11 @@ parsestatset indent:
|
|||||||
|
|
||||||
parsestatcalc indent:
|
parsestatcalc indent:
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc var lexident
|
calc varname lexident
|
||||||
|
calc varid registerid varname
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit var
|
emit varid
|
||||||
emit " = "
|
emit " = "
|
||||||
parseexprcall
|
parseexprcall
|
||||||
emit eol
|
emit eol
|
||||||
@ -188,11 +207,12 @@ parsestatcheck indent:
|
|||||||
|
|
||||||
skipchar " "
|
skipchar " "
|
||||||
emit indent
|
emit indent
|
||||||
emit "if not "
|
emit "__check("
|
||||||
|
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
emit funcname
|
calc funcid registerid funcname
|
||||||
emit "("
|
emit funcid
|
||||||
|
emit ", ["
|
||||||
|
|
||||||
set notfirst ""
|
set notfirst ""
|
||||||
forever
|
forever
|
||||||
@ -222,10 +242,7 @@ parsestatcheck indent:
|
|||||||
|
|
||||||
skipchar ":"
|
skipchar ":"
|
||||||
|
|
||||||
emitln "):"
|
emit "], ["
|
||||||
calc indent increaseindent indent
|
|
||||||
emit indent
|
|
||||||
emit "sys.stderr.write(' '.join(['ERROR:', "
|
|
||||||
|
|
||||||
set notfirst ""
|
set notfirst ""
|
||||||
|
|
||||||
@ -255,23 +272,20 @@ parsestatcheck indent:
|
|||||||
set notfirst "1"
|
set notfirst "1"
|
||||||
/
|
/
|
||||||
|
|
||||||
emitln "]))"
|
emitln "])"
|
||||||
emit indent
|
|
||||||
emitln "sys.stderr.write(eol)"
|
|
||||||
emit indent
|
|
||||||
emitln "sys.exit(1)"
|
|
||||||
/
|
/
|
||||||
|
|
||||||
parsestattrace indent:
|
parsestattrace indent:
|
||||||
emit indent
|
emit indent
|
||||||
emit "trace("
|
emit "__trace("
|
||||||
emit quote
|
emit quote
|
||||||
skipchar " "
|
skipchar " "
|
||||||
calc varname lexident
|
calc varname lexident
|
||||||
|
calc varid registerid varname
|
||||||
emit varname
|
emit varname
|
||||||
emit quote
|
emit quote
|
||||||
emit ", "
|
emit ", "
|
||||||
emit varname
|
emit varid
|
||||||
emitln ")"
|
emitln ")"
|
||||||
skipchar eol
|
skipchar eol
|
||||||
/
|
/
|
||||||
@ -324,8 +338,9 @@ parsestat indent:
|
|||||||
parsestatcheck indent
|
parsestatcheck indent
|
||||||
return
|
return
|
||||||
/
|
/
|
||||||
|
calc callid registerid call
|
||||||
emit indent
|
emit indent
|
||||||
emit call
|
emit callid
|
||||||
emit "("
|
emit "("
|
||||||
set first "1"
|
set first "1"
|
||||||
forever
|
forever
|
||||||
@ -390,9 +405,11 @@ parseblock indent:
|
|||||||
|
|
||||||
parsefunc:
|
parsefunc:
|
||||||
calc funcname lexident
|
calc funcname lexident
|
||||||
|
calc funcid registerid funcname
|
||||||
trace funcname
|
trace funcname
|
||||||
|
mapsetkey "FUNCREG" funcname "1"
|
||||||
emit "def "
|
emit "def "
|
||||||
emit funcname
|
emit funcid
|
||||||
emit "("
|
emit "("
|
||||||
set isnotfirst ""
|
set isnotfirst ""
|
||||||
forever
|
forever
|
||||||
@ -403,11 +420,12 @@ parsefunc:
|
|||||||
break
|
break
|
||||||
/
|
/
|
||||||
skip
|
skip
|
||||||
calc var lexident
|
calc varname lexident
|
||||||
|
calc varid registerid varname
|
||||||
if isnotfirst
|
if isnotfirst
|
||||||
emit ", "
|
emit ", "
|
||||||
/
|
/
|
||||||
emit var
|
emit varid
|
||||||
set isnotfirst "1"
|
set isnotfirst "1"
|
||||||
/
|
/
|
||||||
calc char peek
|
calc char peek
|
||||||
@ -431,26 +449,31 @@ emitheader:
|
|||||||
emitln "import os"
|
emitln "import os"
|
||||||
emitln "import sys"
|
emitln "import sys"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def eq(a: str, b: str) -> str:"
|
emitln "def __eq(a: str, b: str) -> str:"
|
||||||
emitln " return '1' if a == b else ''"
|
emitln " return '1' if a == b else ''"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def lt(a: str, b: str) -> str:"
|
emitln "def __lt(a: str, b: str) -> str:"
|
||||||
emitln " return '1' if a < b else ''"
|
emitln " return '1' if a < b else ''"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def add(a: str, b :str) -> str:"
|
emitln "def __not(a: str) -> str:"
|
||||||
|
emitln " if a:"
|
||||||
|
emitln " return ''"
|
||||||
|
emitln " return '1'"
|
||||||
|
emitln ""
|
||||||
|
emitln "def __add(a: str, b :str) -> str:"
|
||||||
emitln " return a + b"
|
emitln " return a + b"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def emit(string):"
|
emitln "def __emit(string):"
|
||||||
emitln " sys.stdout.buffer.write(string.encode('latin_1'))"
|
emitln " sys.stdout.buffer.write(string.encode('latin_1'))"
|
||||||
emitln " sys.stdout.flush()"
|
emitln " sys.stdout.flush()"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def trace(header, value):"
|
emitln "def __trace(header, value):"
|
||||||
emitln " if os.environ.get('TRACE'):"
|
emitln " if os.environ.get('TRACE'):"
|
||||||
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "eof = chr(0xFF)"
|
emitln "__EOF = chr(0xFF)"
|
||||||
emitln "eol = chr(10)"
|
emitln "__EOL = chr(10)"
|
||||||
emitln "quote = chr(34)"
|
emitln "__QUOTE = chr(34)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "STDINCOLNO = 0"
|
emitln "STDINCOLNO = 0"
|
||||||
emitln "STDINLINENO = 1"
|
emitln "STDINLINENO = 1"
|
||||||
@ -458,43 +481,102 @@ emitheader:
|
|||||||
emitln ""
|
emitln ""
|
||||||
emitln "def _readchar():"
|
emitln "def _readchar():"
|
||||||
emitln " char = sys.stdin.read(1)"
|
emitln " char = sys.stdin.read(1)"
|
||||||
emitln " trace('char', char)"
|
emitln " __trace('char', char)"
|
||||||
emitln " if not char:"
|
emitln " if not char:"
|
||||||
emitln " return eof"
|
emitln " return __EOF"
|
||||||
emitln " return char"
|
emitln " return char"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def peek():"
|
emitln "def __peek():"
|
||||||
emitln " return STDINPEEK"
|
emitln " return STDINPEEK"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def skip():"
|
emitln "def __skip():"
|
||||||
emitln " global STDINCOLNO"
|
emitln " global STDINCOLNO"
|
||||||
emitln " global STDINLINENO"
|
emitln " global STDINLINENO"
|
||||||
emitln " global STDINPEEK"
|
emitln " global STDINPEEK"
|
||||||
emitln " if eol == STDINPEEK:"
|
emitln " if __EOL == STDINPEEK:"
|
||||||
emitln " STDINLINENO += 1"
|
emitln " STDINLINENO += 1"
|
||||||
emitln " STDINCOLNO = 0"
|
emitln " STDINCOLNO = 0"
|
||||||
emitln " STDINCOLNO += 1"
|
emitln " STDINCOLNO += 1"
|
||||||
emitln " STDINPEEK = _readchar()"
|
emitln " STDINPEEK = _readchar()"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def stdinlineno():"
|
emitln "def __stdinlineno():"
|
||||||
emitln " global STDINLINENO"
|
emitln " global STDINLINENO"
|
||||||
emitln " return str(STDINLINENO)"
|
emitln " return str(STDINLINENO)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "def stdincolno():"
|
emitln "def __stdincolno():"
|
||||||
emitln " global STDINCOLNO"
|
emitln " global STDINCOLNO"
|
||||||
emitln " return str(STDINCOLNO)"
|
emitln " return str(STDINCOLNO)"
|
||||||
emitln ""
|
emitln ""
|
||||||
emitln "skip()"
|
emitln "__skip()"
|
||||||
emitln ""
|
emitln ""
|
||||||
|
emitln ""
|
||||||
|
emitln "MAPSTORE = {}"
|
||||||
|
emitln ""
|
||||||
|
emitln "def __mapclear(mapname: str) -> str:"
|
||||||
|
emitln " MAPSTORE.pop(mapname)"
|
||||||
|
emitln " return ''"
|
||||||
|
emitln ""
|
||||||
|
emitln "def __mapgetkey(mapname: str, key: str, default: str) -> str:"
|
||||||
|
emitln " return MAPSTORE.get(mapname, {}).get(key, default)"
|
||||||
|
emitln ""
|
||||||
|
emitln "def __mapsetkey(mapname: str, key: str, value: str) -> str:"
|
||||||
|
emitln " MAPSTORE.setdefault(mapname, {})"
|
||||||
|
emitln " MAPSTORE[mapname][key] = value"
|
||||||
|
emitln " return ''"
|
||||||
|
emitln ""
|
||||||
|
emitln "def __check(func, args: list[str], msg: list[str]) -> None:"
|
||||||
|
emitln " result = func(*args)"
|
||||||
|
emitln " if result:"
|
||||||
|
emitln " return"
|
||||||
|
emitln ""
|
||||||
|
emitln " sys.stderr.write('ERROR: ' + ' '.join(msg) + '\\n')"
|
||||||
|
emitln " sys.stderr.flush()"
|
||||||
|
emitln " exit(1)"
|
||||||
/
|
/
|
||||||
|
|
||||||
emitfooter:
|
emitfooter:
|
||||||
|
declare mainname
|
||||||
|
calc mainname registerid "main"
|
||||||
|
|
||||||
emitln "if __name__ == '__main__':"
|
emitln "if __name__ == '__main__':"
|
||||||
emitln " main()"
|
emit " "
|
||||||
|
emit mainname
|
||||||
|
emitln "()"
|
||||||
/
|
/
|
||||||
|
|
||||||
main:
|
main:
|
||||||
emitheader
|
emitheader
|
||||||
|
|
||||||
|
mapsetkey "REGISTERID" "eof" "__EOF"
|
||||||
|
mapsetkey "REGISTERID" "eol" "__EOL"
|
||||||
|
mapsetkey "REGISTERID" "quote" "__QUOTE"
|
||||||
|
|
||||||
|
mapsetkey "FUNCREG" "add" "1"
|
||||||
|
mapsetkey "REGISTERID" "add" "__add"
|
||||||
|
mapsetkey "FUNCREG" "emit" "1"
|
||||||
|
mapsetkey "REGISTERID" "emit" "__emit"
|
||||||
|
mapsetkey "FUNCREG" "eq" "1"
|
||||||
|
mapsetkey "REGISTERID" "eq" "__eq"
|
||||||
|
mapsetkey "FUNCREG" "lt" "1"
|
||||||
|
mapsetkey "REGISTERID" "lt" "__lt"
|
||||||
|
mapsetkey "FUNCREG" "not" "1"
|
||||||
|
mapsetkey "REGISTERID" "not" "__not"
|
||||||
|
mapsetkey "FUNCREG" "mapclear" "1"
|
||||||
|
mapsetkey "REGISTERID" "mapclear" "__mapclear"
|
||||||
|
mapsetkey "FUNCREG" "mapgetkey" "1"
|
||||||
|
mapsetkey "REGISTERID" "mapgetkey" "__mapgetkey"
|
||||||
|
mapsetkey "FUNCREG" "mapsetkey" "1"
|
||||||
|
mapsetkey "REGISTERID" "mapsetkey" "__mapsetkey"
|
||||||
|
mapsetkey "FUNCREG" "peek" "1"
|
||||||
|
mapsetkey "REGISTERID" "peek" "__peek"
|
||||||
|
mapsetkey "FUNCREG" "skip" "1"
|
||||||
|
mapsetkey "REGISTERID" "skip" "__skip"
|
||||||
|
mapsetkey "FUNCREG" "stdincolno" "1"
|
||||||
|
mapsetkey "REGISTERID" "stdincolno" "__stdincolno"
|
||||||
|
mapsetkey "FUNCREG" "stdinlineno" "1"
|
||||||
|
mapsetkey "REGISTERID" "stdinlineno" "__stdinlineno"
|
||||||
|
|
||||||
|
|
||||||
forever
|
forever
|
||||||
calc char peek
|
calc char peek
|
||||||
calc iseof eq char eof
|
calc iseof eq char eof
|
||||||
|
|||||||
23
README.md
23
README.md
@ -155,6 +155,29 @@ Return true if the given strings are the same.
|
|||||||
|
|
||||||
Return true if a would sort before b.
|
Return true if a would sort before b.
|
||||||
|
|
||||||
|
#### mapclear mapname
|
||||||
|
|
||||||
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
|
Clears all values set in the map named `mapname`.
|
||||||
|
|
||||||
|
#### mapgetkey mapname key
|
||||||
|
|
||||||
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
|
Looks up `key` in the map named `mapname` and returns it.
|
||||||
|
If not found, returns an empty string.
|
||||||
|
|
||||||
|
#### mapsetkey mapname key value
|
||||||
|
|
||||||
|
Maps are global and can be used from any function.
|
||||||
|
|
||||||
|
Adds a mapping from `key` to `value` to the map named `mapname`.
|
||||||
|
|
||||||
|
#### not a
|
||||||
|
|
||||||
|
Returns "1" if a is empty; otherwise, returns "".
|
||||||
|
|
||||||
#### peek
|
#### peek
|
||||||
|
|
||||||
Checks stdin for the next character and returns it.
|
Checks stdin for the next character and returns it.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user