lang0/2-lang0c/lang0c.lang0
Johan B.W. de Vries 6055cddab2 Extends the test framework to prepare for compilation tests
Feat: add now can add two full strings

Fix: it2 would have different working for emit eof

Fix: eq and lt would return bools on it0 and it1

Fix: Functions always return something (there is no such
thing as an empty type).

Fix: Return value from main is now always ignored.

Fix: Output from check is same on all iterations
2025-05-04 14:33:10 +02:00

696 lines
11 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 add indent " "
return indent
/
lexident:
declare char
declare isbeforea
declare isafterz
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 add word char
skip
/
return word
/
parseconststring:
declare char
declare iseof
declare isquote
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
return
/
parseexprvarref:
declare varname
calc varname lexident
emit "var_"
emit varname
return
/
parseexprcall:
declare char
declare first
declare funcname
declare isspace
declare isnotspace
declare isfirst
declare isnotfirst
declare isquote
declare isnotquote
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 ")"
return
/
parsestatdeclare indent:
declare var
skipchar " "
calc var lexident
emit indent
emit "char * var_"
emit var
emit ";"
emit eol
skipchar eol
return
/
parsestatset indent:
declare var
skipchar " "
calc var lexident
skipchar " "
emit indent
emit "var_"
emit var
emit " = "
parseconststring
emit ";"
emit eol
skipchar eol
return
/
parsestatcalc indent:
declare var
skipchar " "
calc var lexident
skipchar " "
emit indent
emit "var_"
emit var
emit " = "
parseexprcall
emit ";"
emit eol
skipchar eol
return
/
parseblock indent/
parsestatif indent:
declare indentt
skipchar " "
emit indent
emit "if ( 0 < strlen("
parseexprvarref
emitln ") )"
emit indent
emitln "{"
skipchar eol
calc indentt increaseindent indent
parseblock indentt
emit indent
emitln "}"
return
/
parsestatforever indent:
declare indentt
emit indent
emitln "while (1)"
emit indent
emitln "{"
skipchar eol
calc indentt increaseindent indent
parseblock indentt
emit indent
emitln "}"
return
/
parsestatbreak indent:
emit indent
emitln "break;"
skipchar eol
return
/
parsestatreturn indent:
declare char
declare isspace
declare isnotquote
declare isquote
declare isnotspace
emit indent
emit "return "
calc char peek
calc isspace eq char " "
calc isnotspace not isspace
if isspace
skip
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
/
if isnotspace
emit quote
emit quote
/
emit ";"
emit eol
skipchar eol
return
/
parsestatcheck indent:
declare char
declare funcname
declare iscolon
declare iseol
declare isnotquote
declare isquote
declare notfirst
skipchar " "
emit indent
emit "if( 0 == strlen("
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 ":"
emitln ")) )"
emit indent
emitln "{"
emit indent
emit " fprintf(stderr, "
emit quote
emit "%s"
emit quote
emit ", "
emit quote
emit "ERROR:"
emit quote
emitln ");"
forever
skipchar " "
emit indent
emit " fprintf(stderr, "
emit quote
emit " %s"
emit quote
emit ", "
calc char peek
calc isquote eq char quote
calc isnotquote not isquote
if isquote
parseconststring
/
if isnotquote
parseexprvarref
/
emitln ");"
calc char peek
calc iseol eq char eol
if iseol
break
/
/
emit indent
emit " fprintf(stderr, "
emit quote
emit "%s"
emit quote
emit ", var_eol"
emitln ");"
emit indent
emitln " exit(1);"
emit indent
emitln "}"
/
parsestattrace indent:
declare varname
emit indent
emit "trace("
emit quote
skipchar " "
calc varname lexident
emit varname
emit quote
emit ", var_"
emit varname
emitln ");"
skipchar eol
return
/
parsestat indent:
declare call
declare char
declare first
declare iscall
declare isfirst
declare isspace
declare isquote
declare isnotfirst
declare isnotspace
declare isnotquote
calc call lexident
trace call
calc iscall eq call "declare"
if iscall
parsestatdeclare indent
return
/
calc iscall eq call "set"
if iscall
parsestatset indent
return
/
calc iscall eq call "calc"
if iscall
parsestatcalc indent
return
/
calc iscall eq call "if"
if iscall
parsestatif indent
return
/
calc iscall eq call "forever"
if iscall
parsestatforever indent
return
/
calc iscall eq call "break"
if iscall
parsestatbreak indent
return
/
calc iscall eq call "return"
if iscall
parsestatreturn indent
return
/
calc iscall eq call "check"
if iscall
parsestatcheck indent
return
/
calc iscall eq call "trace"
if iscall
parsestattrace 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
emitln ");"
return
/
parseblock indent:
declare char
declare copy
declare iseol
declare isnoteol
declare isdone
declare iseoblock
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
/
return
/
parsefunc:
declare char
declare first
declare funcname
declare iseoblock
declare isfirst
declare ismain
declare isnotmain
declare isspace
declare isnotfirst
declare isnotspace
declare var
calc funcname lexident
calc ismain eq funcname "main"
calc isnotmain not ismain
trace funcname
emit "char * "
if ismain
emit "__main"
/
if isnotmain
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"
/
calc char peek
calc iseoblock eq char "/"
if iseoblock
skipchar "/"
skipchar eol
emitln ");"
return
/
skipchar ":"
skipchar eol
emitln ")"
emitln "{"
parseblock " "
emitln "}"
emit eol
return
/
emitheader:
emitln "#include <assert.h>"
emitln "#include <stdio.h>"
emitln "#include <stdlib.h>"
emitln "#include <string.h>"
emitln ""
emitln ""
emitln "char var_eof[2] = {0xFF, 0};"
emitln "char var_eol[2] = {10, 0};"
emitln "char var_quote[2] = {34, 0};"
emitln "char var_false[1] = {0};"
emitln "char var_true[2] = {'1', 0};"
emitln ""
emitln ""
emitln "char * eq(char * a, char * b)"
emitln "{"
emitln " return (strcmp(a, b) == 0) ? var_true : var_false;"
emitln "}"
emitln ""
emitln "char * lt(char * a, char * b)"
emitln "{"
emitln " return (strcmp(a, b) < 0) ? var_true : var_false;"
emitln "}"
emitln "char * not(char * a)"
emitln "{"
emitln " return (strcmp(a, var_true) != 0) ? var_true : var_false;"
emitln "}"
emitln ""
emitln "char * add(char * lft, char * rgt)"
emitln "{"
emitln " int lft_len = strlen(lft);"
emitln " int rgt_len = strlen(rgt);"
emitln " char * res = malloc((lft_len + rgt_len + 1) * sizeof(char));"
emitln " strcpy(res, lft);"
emitln " strcpy(res + lft_len, rgt);"
emitln " res[lft_len + rgt_len] = 0;"
emitln " return res;"
emitln "}"
emitln ""
emitln "char * emit(char * str)"
emitln "{"
emitln " fputs(str, stdout);"
emitln " return 0;"
emitln "}"
emitln ""
emitln "char * trace(char * var_name, char * var_value)"
emitln "{"
emit " const char * env_trace = getenv("
emit quote
emit "TRACE"
emit quote
emitln ");"
emitln " if( !env_trace ) return 0;"
emitln " fputs(var_name, stderr);"
emit " fputs("
emit quote
emit "="
emit quote
emitln ", stderr);"
emitln " fputs(var_value, stderr);"
emitln " fputs(var_eol, stderr);"
emitln " return 0;"
emitln "}"
emitln ""
emitln "int STDINCOLNO = 1;"
emitln "int STDINLINENO = 1;"
emitln "char * STDINPEEK = 0;"
emitln ""
emitln "char * _readchar()"
emitln "{"
emitln " char * res = malloc(2*sizeof(char));"
emitln " res[0] = getc(stdin);"
emitln " res[1] = 0;"
emitln " return res;"
emitln "}"
emitln ""
emitln "char * peek()"
emitln "{"
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read"
emitln " return STDINPEEK;"
emitln "}"
emitln ""
emitln "void skip()"
emitln "{"
emitln " if( !STDINPEEK ) STDINPEEK = _readchar(); // First byte read, not even peek()'d"
emitln " if( STDINPEEK[0] == 10 ) {"
emitln " STDINLINENO += 1;"
emitln " STDINCOLNO = 0;"
emitln " }"
emitln " STDINCOLNO += 1;"
emitln " STDINPEEK = _readchar();"
emitln "}"
emitln ""
emitln "char * stdinlineno()"
emitln "{"
emitln " char * res = malloc(8*sizeof(char));"
emit " sprintf(res, "
emit quote
emit "%d"
emit quote
emitln ", STDINLINENO);"
emitln " return res;"
emitln "}"
emitln ""
emitln "char * stdincolno()"
emitln "{"
emitln " char * res = malloc(8*sizeof(char));"
emit " sprintf(res, "
emit quote
emit "%d"
emit quote
emitln ", STDINCOLNO);"
emitln " return res;"
emitln "}"
emitln ""
return
/
emitfooter:
emitln "int main() {"
emitln " __main();"
emitln " return 0;"
emitln "}"
return
/
main:
declare char
declare iseof
declare iseol
declare isnoteol
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
return
/