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:
commit
512a31a458
40
doc/c02.txt
40
doc/c02.txt
@ -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
11
label.c
@ -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)
|
||||
|
1
label.h
1
label.h
@ -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
|
||||
|
@ -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
12
stmnt.c
@ -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"))
|
||||
|
Loading…
Reference in New Issue
Block a user