1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-11-25 06:31:25 +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.
This must then be followed by a case statement.
Each use of the case keyword is followed by term and a colon. If the
term is equal to select expression then the code immediately following
the is executed, otherwise, program execution transfers to the next
case or default statement.
Each use of the case keyword is followed by one or more comma-separated
terms and a colon. If the term is equal to select expression then the
code immediately following the is executed, otherwise, program execution
transfers to the next case or default statement.
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
@ -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
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:
puts("You pressed ");
select (getc()) {
case $00: putln("Nothing");
case $0D: putln("The Enter key");
case ' ': putln("The space bar");
case 'A','a': putln ("The letter A");
case ltr: putln("The character in variable 'ltr'");
case s[2]: putln("The third character of string 's'");
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
the same value. In this case, only the first case block matching the
select expression will be executed.

11
label.c
View File

@ -13,20 +13,21 @@
#include "parse.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 *
* Args: lbtyp1: First label type *
* lbtyp2: Second label type *
* Sets: tmplbl - Label name *
* Returns: Index into label table *
* (-1 if not found) */
int lstlbl(int lbtyp1, int lbtyp2)
int lstlbl(int lbflag)
{
int i;
DEBUG("Searching for label type %d ", lbtyp1);
DEBUG("and label type %d\n",lbtyp2);
DEBUG("Searching for label flag %d\n", lbflag);
for (i = lblcnt - 1; i>-1; i--) {
if (lbltyp[i] == lbtyp1) break;
if (lbltyp[i] == lbtyp2) break;
//DEBUG("Comparing against flag %d", lblflg[lbltyp[i]]);
if (lblflg[lbltyp[i]] == lbflag) break;
}
DEBUG("Search produced label index %d\n", i);
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
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 newlbl(char* lbname); //Generate New Block Label

View File

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

12
stmnt.c
View File

@ -139,10 +139,10 @@ void prsasn(char trmntr)
}
/* parse and compile 'break'/'continue' statement */
void pbrcnt(int lbtyp1, int lbtyp2)
void pbrcnt(int lbflag)
{
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);
DEBUG("Found Label '%s'\n", tmplbl);
asmlin("JMP", tmplbl);
@ -312,8 +312,8 @@ void pslct() {
expect('(');
prsxpr(')'); //Parse Expression
newlbl(endlbl); //Create New Label
pshlbl(LTSLCT,endlbl); //Push Onto Stack
bgnblk('{'); //Require Beginning of Block
pshlbl(LTSLCT,endlbl); //Push Onto Stack
bgnblk('{'); //Require Beginning of Block
strcpy(xstmnt, "CASE"); //Require Next Statement to be CASE
}
@ -466,9 +466,9 @@ void pstmnt()
if (wordis("ASM"))
pasm();
else if (wordis("BREAK"))
pbrcnt(LTEND, LTDWHL);
pbrcnt(LFEND);
else if (wordis("CONTINUE"))
pbrcnt(LTLOOP, LTDO);
pbrcnt(LFBGN);
else if (wordis("GOTO"))
pgoto();
else if (wordis("INLINE"))