1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2025-02-20 12:29:04 +00:00

Merge pull request #2 from RevCurtisP/break-case

Modified BREAK to exit CASE blocks
This commit is contained in:
RevCurtisP 2018-02-07 22:59:55 -05:00 committed by GitHub
commit 512a31a458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 18 deletions

BIN
c02.exe

Binary file not shown.

View File

@ -525,10 +525,10 @@ When using the select keyword, it is followed by an expression (surrounded
by parenthesis) and an opening curly brace, which begins the select block. by parenthesis) and an opening curly brace, which begins the select block.
This must then be followed by a case statement. This must then be followed by a case statement.
Each use of the case keyword is followed by term and a colon. If the Each use of the case keyword is followed by one or more comma-separated
term is equal to select expression then the code immediately following terms and a colon. If the term is equal to select expression then the
the is executed, otherwise, program execution transfers to the next code immediately following the is executed, otherwise, program execution
case or default statement. transfers to the next case or default statement.
The code between two case statements or a case and default statement is The code between two case statements or a case and default statement is
called a case block. At the end of a case block, program execution called a case block. At the end of a case block, program execution
@ -541,16 +541,48 @@ default statement and the end of the select block (marked with a closing
curly-brace) is called the default block and is executed if none of curly-brace) is called the default block and is executed if none of
the case arguments matched the select expression. the case arguments matched the select expression.
If the constant 0 is to be used as an argument to any of the case
statements, using it as the first argument of the first case statement
will produce slightly more efficient code.
Example: Example:
puts("You pressed "); puts("You pressed ");
select (getc()) { select (getc()) {
case $00: putln("Nothing");
case $0D: putln("The Enter key"); case $0D: putln("The Enter key");
case ' ': putln("The space bar"); case ' ': putln("The space bar");
case 'A','a': putln ("The letter A");
case ltr: putln("The character in variable 'ltr'"); case ltr: putln("The character in variable 'ltr'");
case s[2]: putln("The third character of string 's'"); case s[2]: putln("The third character of string 's'");
default: putln("some other key"); default: putln("some other key");
} }
Unlike the switch statement in C, the break statement is not needed to
exit from a case block. It may be used, however, to prematurely exit a
case block if desired.
Example:
select (arg) {
case foo:
puts("fu");
if (!bar) break;
puts("bar");
default: //do nothing
}
In addition, fall through of case blocks can be duplicated using the goto
statement with a label.
select (num)
case 1:
putc('I');
goto two;
case 2:
two:
putc('I');
default: //do nothing
}
Note: It's possible for multiple case statement arguments to evaluate to Note: It's possible for multiple case statement arguments to evaluate to
the same value. In this case, only the first case block matching the the same value. In this case, only the first case block matching the
select expression will be executed. select expression will be executed.

11
label.c
View File

@ -13,20 +13,21 @@
#include "parse.h" #include "parse.h"
#include "label.h" #include "label.h"
const char lblflg[] = {LFNONE, LFNONE, LFBGN, LFEND, LFBGN, LFEND, LFEND, LFNONE, LFNONE}; //Label Type Flags
/* Find Last Label of Specified Types * /* Find Last Label of Specified Types *
* Args: lbtyp1: First label type * * Args: lbtyp1: First label type *
* lbtyp2: Second label type * * lbtyp2: Second label type *
* Sets: tmplbl - Label name * * Sets: tmplbl - Label name *
* Returns: Index into label table * * Returns: Index into label table *
* (-1 if not found) */ * (-1 if not found) */
int lstlbl(int lbtyp1, int lbtyp2) int lstlbl(int lbflag)
{ {
int i; int i;
DEBUG("Searching for label type %d ", lbtyp1); DEBUG("Searching for label flag %d\n", lbflag);
DEBUG("and label type %d\n",lbtyp2);
for (i = lblcnt - 1; i>-1; i--) { for (i = lblcnt - 1; i>-1; i--) {
if (lbltyp[i] == lbtyp1) break; //DEBUG("Comparing against flag %d", lblflg[lbltyp[i]]);
if (lbltyp[i] == lbtyp2) break; if (lblflg[lbltyp[i]] == lbflag) break;
} }
DEBUG("Search produced label index %d\n", i); DEBUG("Search produced label index %d\n", i);
if (i>=0) if (i>=0)

View File

@ -19,6 +19,7 @@ int lblnxt; //Sequence of next label to be generated
char lbltmp[LABLEN+1]; //Label Temporary Storage char lbltmp[LABLEN+1]; //Label Temporary Storage
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
enum lflags {LFNONE, LFBGN, LFEND}; //Label Flag Types
void prslbl(); //Parse Label From Code void prslbl(); //Parse Label From Code
void newlbl(char* lbname); //Generate New Block Label void newlbl(char* lbname); //Generate New Block Label

View File

@ -39,7 +39,8 @@ for (c=0; c<10; c++) {
} }
newlin(); newlin();
for (c=$18; c<$23; c++) { for (c=$18; c<$22; c++) {
if (c & 15 > 9) continue; //Skip $1A - $1F
prbyte(c); prbyte(c);
putc(' '); putc(' ');
select (c) { select (c) {
@ -48,8 +49,8 @@ for (c=$18; c<$23; c++) {
putln("BREAK ONE-NINE"); putln("BREAK ONE-NINE");
if (c==$19) break; if (c==$19) break;
putln("OOPS!"); putln("OOPS!");
case $22: putln("BLACKJACK!"); case $21: putln("BLACKJACK!");
default: //putln("*"); default: putln("*");
} }
} }

View File

@ -139,10 +139,10 @@ void prsasn(char trmntr)
} }
/* parse and compile 'break'/'continue' statement */ /* parse and compile 'break'/'continue' statement */
void pbrcnt(int lbtyp1, int lbtyp2) void pbrcnt(int lbflag)
{ {
DEBUG("Parsing BREAK/CONTINUE statement\n", 0); DEBUG("Parsing BREAK/CONTINUE statement\n", 0);
if (lstlbl(lbtyp1, lbtyp2) < 0) if (lstlbl(lbflag) < 0)
ERROR("Break/continue statement outside of loop\n", 0, EXIT_FAILURE); ERROR("Break/continue statement outside of loop\n", 0, EXIT_FAILURE);
DEBUG("Found Label '%s'\n", tmplbl); DEBUG("Found Label '%s'\n", tmplbl);
asmlin("JMP", tmplbl); asmlin("JMP", tmplbl);
@ -466,9 +466,9 @@ void pstmnt()
if (wordis("ASM")) if (wordis("ASM"))
pasm(); pasm();
else if (wordis("BREAK")) else if (wordis("BREAK"))
pbrcnt(LTEND, LTDWHL); pbrcnt(LFEND);
else if (wordis("CONTINUE")) else if (wordis("CONTINUE"))
pbrcnt(LTLOOP, LTDO); pbrcnt(LFBGN);
else if (wordis("GOTO")) else if (wordis("GOTO"))
pgoto(); pgoto();
else if (wordis("INLINE")) else if (wordis("INLINE"))