From 9fc685a2237b789800b770f3bc1eecb8e1bfdf7b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 19 Aug 2021 07:52:26 +0000 Subject: c4: added switch statement --- miniany/c4.c | 50 +++++++++++++++++-- miniany/cc.c | 143 +++++++++++++++++++++++++++++++---------------------- miniany/torture.sh | 12 +++++ 3 files changed, 141 insertions(+), 64 deletions(-) create mode 100755 miniany/torture.sh diff --git a/miniany/c4.c b/miniany/c4.c index a36fb4a..9acba4e 100644 --- a/miniany/c4.c +++ b/miniany/c4.c @@ -18,6 +18,9 @@ char *p, *lp, // current position in source code *data; // data/bss pointer int *e, *le, // current position in emitted code + *cas, // case statement patch-up pointer + *brak, // break statement patch-up pointer + *def, // default statement patch-up pointer *id, // currently parsed identifier *sym, // symbol table (simple list of identifiers) tk, // current token @@ -31,7 +34,7 @@ int *e, *le, // current position in emitted code // tokens and classes (operators last and in precedence order) enum { Num = 128, Fun, Sys, Glo, Loc, Id, - Char, Else, Enum, If, Int, Return, Sizeof, Do, While, + Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Do, Switch, While, Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak }; @@ -59,7 +62,7 @@ void next() while (le < e) { printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," - "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,EXIT,"[*++le * 5]); + "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,EXIT,"[*++le * 5]); if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n"); } } @@ -293,7 +296,7 @@ void expr(int lev) void stmt() { - int *a, *b; + int *a, *b, *d, i; if (tk == If) { next(); @@ -333,6 +336,43 @@ void stmt() *++e = JMP; *++e = (int)a; *b = (int)(e + 1); } + else if (tk == Switch) { + next(); + if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } + expr(Assign); + if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } + a = cas; *++e = JMP; cas = ++e; + b = brak; d = def; brak = def = 0; + stmt(); + *cas = def ? (int)def : (int)(e + 1); cas = a; + while (brak) { a = (int *)*brak; *brak = (int)(e + 1); brak = a; } + brak = b; def = d; + } + else if (tk == Case) { + *++e = JMP; ++e; *e = (int)(e + 7); *++e = PSH; i = *cas; *cas = (int)e; + next(); + expr(Or); + if (e[-1] != IMM) { printf("%d: bad case immediate\n", line); exit(-1); } + *e = *e - i; *++e = SUB; *++e = BNZ; cas = ++e; *e = i + e[-3]; + if (tk == ':') { + next(); + } + else { + printf("%d: colon expected\n", line); exit(-1); + } + stmt(); + } + else if (tk == Break) { + next(); + if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } + *++e = JMP; *++e = (int)brak; brak = e; + } + else if (tk == Default) { + next(); + if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); } + def = e + 1; + stmt(); + } else if (tk == Return) { next(); if (tk != ';') expr(Assign); @@ -376,10 +416,10 @@ int main(int argc, char **argv) memset(e, 0, poolsz); memset(data, 0, poolsz); - p = "char else enum if int return sizeof do while " + p = "break case char default else enum if int return sizeof do switch while " "EOF EXIT_SUCCESS EXIT_FAILURE NULL " "open read close printf malloc free memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp exit void main"; - i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table + i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table // add library constants next(); id[Class] = Num; id[Type] = INT; id[Val] = -1; next(); id[Class] = Num; id[Type] = INT; id[Val] = 0; diff --git a/miniany/cc.c b/miniany/cc.c index e5b30c7..ba7ead2 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -114,15 +114,17 @@ void scanIdent( int c ) int keyword( char *ident ) { - if( *ident == 'i' ) { - if( strcmp( ident, "int" ) == 0 ) { - return S_INT; - } else { - return 0; - } + switch( ident[0] ) { + case 'i': + if( strcmp( ident, "int" ) == 0 ) { + return S_INT; + } else { + return 0; + } + break; + default: + return 0; } - - return 0; } int getToken( ) @@ -132,55 +134,76 @@ int getToken( ) c = skipWhite( ); - if( c == EOF ) { - t = S_EOI; - } else if( c == '+' ) { - t = S_PLUS; - } else if( c == '-' ) { - t = S_MINUS; - } else if( c == '*' ) { - t = S_STAR; - } else if ( c == '/' ) { - c = getChar( ); - if( c == '/' ) { - while( c != '\n' ) { - c = getChar( ); - } - t = getToken( ); - } else if( c == '*' ) { - do { - while( c != '*' ) { + switch( c ) { + case EOF: + t = S_EOI; + break; + case '+': + t = S_PLUS; + break; + case '-': + t = S_MINUS; + break; + case '*': + t = S_STAR; + break; + case '/': + c = getChar( ); + if( c == '/' ) { + while( c != '\n' ) { c = getChar( ); } + t = getToken( ); + } else if( c == '*' ) { + do { + while( c != '*' ) { + c = getChar( ); + } + c = getChar( ); + } while( c != '/' ); c = getChar( ); - } while( c != '/' ); - c = getChar( ); - t = getToken( ); - } else { - pushBack( c ); - t = S_SLASH; - } - } else if( c == ';' ) { - t = S_SEMICOLON; - } else if( c == '=' ) { - t = S_EQUALS; - } else if( isdigit( c ) ) { - scanNumber( c ); - t = S_NUM; - } else if( c >= 'a' && c <= 'z' ) { - scanIdent( c ); - if( ( t = keyword( ident ) ) ) { - } else { - t = S_IDENT; - } - } else { - t = S_ERR; - printErrorHeader( ); - putstring( "unknown token '" ); - putchar( c ); - putstring( "'" ); - putnl( ); - exit( EXIT_FAILURE ); + t = getToken( ); + } else { + pushBack( c ); + t = S_SLASH; + } + break; + case ';': + t = S_SEMICOLON; + break; + case '=': + t = S_EQUALS; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + scanNumber( c ); + t = S_NUM; + break; + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'Y': case 'Z': + case '_': + scanIdent( c ); + if( ( t = keyword( ident ) ) ) { + } else { + t = S_IDENT; + } + break; + default: + t = S_ERR; + printErrorHeader( ); + putstring( "unknown token '" ); + putchar( c ); + putstring( "'" ); + putnl( ); + exit( EXIT_FAILURE ); } if( DEBUG_SCANNER ) { @@ -253,11 +276,13 @@ void parseExpression( ) } } -//~ struct Symbol { - //~ char *name; -//~ }; +/* +struct Symbol { + char *name; +}; -//~ struct Symbol *symbol; +struct Symbol *symbol; +*/ void newSymbol( char *s ) { @@ -298,7 +323,7 @@ int main( int argc, char **argv ) row = 1; pushback = 0; DEBUG_SCANNER = 1; - //~ symbol = NULL; + /* symbol = NULL; */ ident = "12345678901234567890"; token = getToken( ); diff --git a/miniany/torture.sh b/miniany/torture.sh new file mode 100755 index 0000000..06c41c4 --- /dev/null +++ b/miniany/torture.sh @@ -0,0 +1,12 @@ +#!/bin/bash + + +for COMPILER in gcc clang pcc tcc; do + $COMPILER -m32 -o c4 c4.c + for MODE in freestanding hosted; do + for LEVEL in 0; do + ./build.sh cc $COMPILER $MODE $LEVEL + ./cc < cc.c + done + done +done -- cgit v1.2.3-54-g00ecf