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:
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.
|
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
11
label.c
@ -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)
|
||||||
|
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
|
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
|
||||||
|
@ -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("*");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
stmnt.c
8
stmnt.c
@ -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"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user