mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-25 21:33:44 +00:00
Merge pull request #1 from RevCurtisP/select
Implemented SELECT, CASE, and DEFAULT statements
This commit is contained in:
commit
eec6b17878
5
c02.c
5
c02.c
@ -54,10 +54,7 @@ void pword()
|
||||
getwrd();
|
||||
ACMNT(word);
|
||||
DEBUG("Parsing Word '%s'\n", word);
|
||||
if (xstmnt[0])
|
||||
if (wordis(xstmnt))
|
||||
xstmnt[0] = 0;
|
||||
else
|
||||
if (xstmnt[0] && !wordis(xstmnt))
|
||||
ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE);
|
||||
if (!pmodfr() && !ptype(MTNONE))
|
||||
pstmnt(); //Parse Statement
|
||||
|
138
c02.ppx
138
c02.ppx
@ -2,32 +2,7 @@
|
||||
<settings version="1.0">
|
||||
<category name="expr.h" />
|
||||
<category name="cond.h" />
|
||||
<category name="asm.h" />
|
||||
<category name="c02.c" />
|
||||
<category name="stmnt.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">-8</property>
|
||||
<property name="Top" type="integer">-31</property>
|
||||
<property name="Right" type="integer">952</property>
|
||||
<property name="Bottom" type="integer">422</property>
|
||||
<property name="Maximized" type="integer">1</property>
|
||||
<property name="Active" type="integer">1</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="asm.c" />
|
||||
<category name="vars.c" />
|
||||
<category name="parse.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">52</property>
|
||||
<property name="Top" type="integer">52</property>
|
||||
<property name="Right" type="integer">760</property>
|
||||
<property name="Bottom" type="integer">362</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="include.c" />
|
||||
<category name="expr.c">
|
||||
<category name="asm.h">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">78</property>
|
||||
<property name="Top" type="integer">78</property>
|
||||
@ -37,7 +12,116 @@
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="c02.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">0</property>
|
||||
<property name="Top" type="integer">0</property>
|
||||
<property name="Right" type="integer">952</property>
|
||||
<property name="Bottom" type="integer">310</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="stmnt.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">26</property>
|
||||
<property name="Top" type="integer">26</property>
|
||||
<property name="Right" type="integer">978</property>
|
||||
<property name="Bottom" type="integer">336</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="asm.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">52</property>
|
||||
<property name="Top" type="integer">52</property>
|
||||
<property name="Right" type="integer">760</property>
|
||||
<property name="Bottom" type="integer">362</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="vars.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">52</property>
|
||||
<property name="Top" type="integer">52</property>
|
||||
<property name="Right" type="integer">1004</property>
|
||||
<property name="Bottom" type="integer">362</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="parse.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">78</property>
|
||||
<property name="Top" type="integer">78</property>
|
||||
<property name="Right" type="integer">1030</property>
|
||||
<property name="Bottom" type="integer">388</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="include.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">104</property>
|
||||
<property name="Top" type="integer">104</property>
|
||||
<property name="Right" type="integer">1056</property>
|
||||
<property name="Bottom" type="integer">414</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="expr.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">130</property>
|
||||
<property name="Top" type="integer">130</property>
|
||||
<property name="Right" type="integer">1082</property>
|
||||
<property name="Bottom" type="integer">440</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="parse.h" />
|
||||
<category name="common.h" />
|
||||
<category name="common.h">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">-8</property>
|
||||
<property name="Top" type="integer">-31</property>
|
||||
<property name="Right" type="integer">952</property>
|
||||
<property name="Bottom" type="integer">422</property>
|
||||
<property name="Maximized" type="integer">1</property>
|
||||
<property name="Active" type="integer">1</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="files.c" />
|
||||
<category name="common.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">26</property>
|
||||
<property name="Top" type="integer">26</property>
|
||||
<property name="Right" type="integer">978</property>
|
||||
<property name="Bottom" type="integer">336</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="label.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">104</property>
|
||||
<property name="Top" type="integer">104</property>
|
||||
<property name="Right" type="integer">812</property>
|
||||
<property name="Bottom" type="integer">414</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
<category name="cond.c">
|
||||
<category name="Window">
|
||||
<property name="Left" type="integer">130</property>
|
||||
<property name="Top" type="integer">130</property>
|
||||
<property name="Right" type="integer">838</property>
|
||||
<property name="Bottom" type="integer">440</property>
|
||||
<property name="Maximized" type="integer">0</property>
|
||||
<property name="Active" type="integer">0</property>
|
||||
</category>
|
||||
</category>
|
||||
</settings>
|
||||
|
43
doc/c02.txt
43
doc/c02.txt
@ -513,9 +513,48 @@ Note: In order to optimize the compiled code, the if and else statements
|
||||
are to 6502 relative branch instructions. This limits the amount of
|
||||
generated code between the if statement and the end of the if/else block
|
||||
to slightly less than 127 characters. This should be sufficient in most
|
||||
cases, but larger code blocks can be accomodated using function calls or
|
||||
cases, but larger code blocks can be accommodated using function calls or
|
||||
goto statements.
|
||||
|
||||
SELECT, CASE, AND DEFAULT STATEMENTS
|
||||
|
||||
The select, case, an default statements are used to execute a specific
|
||||
block of code depending on the result of an expression.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
transfers to the end of the select block (the closing curly brace at
|
||||
the end of the default block).
|
||||
|
||||
The last case block must be followed by a default statement. When using
|
||||
the default keyword, it is followed by a colon. The code between the
|
||||
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.
|
||||
|
||||
Example:
|
||||
puts("You pressed ");
|
||||
select (getc()) {
|
||||
case $0D: putln("The Enter key");
|
||||
case ' ': putln("The space bar");
|
||||
case ltr: putln("The character in variable 'ltr'");
|
||||
case s[2]: putln("The third character of string 's'");
|
||||
default: putln("some other key");
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
WHILE LOOPS
|
||||
|
||||
The while statement is used to conditionally execute code in a loop. When
|
||||
@ -532,7 +571,7 @@ Examples:
|
||||
while() if (rdkey()) break; //Wait for a keypress
|
||||
|
||||
Note: While loops are compiled using the 6502 JMP statements, so the code
|
||||
blocks may be abritrarily large.
|
||||
blocks may be arbitrarily large.
|
||||
|
||||
DO WHILE LOOPS
|
||||
|
||||
|
@ -7,8 +7,8 @@ C02 only supports one data type: unsigned char.
|
||||
POINTERS
|
||||
|
||||
C02 does not support pointer type variables or parameters. However, the
|
||||
address-of operator may be used in function calls.
|
||||
|
||||
address-of operator may be used in function calls and the inline
|
||||
statement.
|
||||
|
||||
DECLARATIONS
|
||||
|
||||
@ -28,3 +28,10 @@ EXPRESSIONS
|
||||
C02 supports the addition, subtraction, bitwise-and, bitwise-or, and
|
||||
exclusive-or operators. The multiplication, division, and binary shift
|
||||
operators are not supported. These can be implemented through functions.
|
||||
|
||||
STATEMENTS
|
||||
|
||||
Instead of the switch statement, C02 uses the select statement. The
|
||||
select statement works almost identically to the switch statement except
|
||||
that case blocks do not fall through and the break statement does not
|
||||
exit a case block.
|
||||
|
19
label.c
19
label.c
@ -85,8 +85,6 @@ void reqlbl(char* lbname)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Pop Label from Stack and Emit on Next Line */
|
||||
int poplbl()
|
||||
{
|
||||
@ -102,12 +100,27 @@ int poplbl()
|
||||
else if (lbtype == LTDWHL)
|
||||
strcpy(endlbl, lblnam[lblcnt]);
|
||||
//strcpy(cndlbl, lblnam[lblcnt]);
|
||||
else if (lbtype == LTCASE)
|
||||
strcpy(cndlbl, lblnam[lblcnt]);
|
||||
else
|
||||
setlbl(lblnam[lblcnt]);
|
||||
inblck = lblblk[lblcnt-1];
|
||||
if (lbtype != LTCASE)
|
||||
inblck = lblblk[lblcnt-1];
|
||||
return lbtype;
|
||||
}
|
||||
|
||||
/* Get Top Label and Return Type */
|
||||
int toplbl(char *rtlbl)
|
||||
{
|
||||
if (lblcnt) {
|
||||
strcpy(rtlbl, lblnam[lblcnt-1]);
|
||||
DEBUG("Found top label %s\n", rtlbl);
|
||||
return lbltyp[lblcnt-1];
|
||||
}
|
||||
rtlbl[0] = 0; //Clear Label
|
||||
return LTNONE;
|
||||
}
|
||||
|
||||
/* Push Label onto Stack *
|
||||
* Args: lbltyp - Label type *
|
||||
* Uses: curlbl - Label to push */
|
||||
|
2
label.h
2
label.h
@ -18,7 +18,7 @@ int lblcnt; //Number of Labels in stack
|
||||
int lblnxt; //Sequence of next label to be generated
|
||||
char lbltmp[LABLEN+1]; //Label Temporary Storage
|
||||
|
||||
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTFUNC}; //Label Types
|
||||
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
|
||||
|
||||
void prslbl(); //Parse Label From Code
|
||||
void newlbl(char* lbname); //Generate New Block Label
|
||||
|
54
stmnt.c
54
stmnt.c
@ -204,7 +204,7 @@ void pfor() {
|
||||
|
||||
/* parse and compile if statement */
|
||||
void pif() {
|
||||
DEBUG("Parsing IF statement '%c'\n", nxtchr);
|
||||
DEBUG("Parsing IF statement\n", 0);
|
||||
expect('(');
|
||||
newlbl(cndlbl); //Create New Label
|
||||
pshlbl(LTIF,cndlbl); //Push Onto Stack
|
||||
@ -214,7 +214,7 @@ void pif() {
|
||||
|
||||
/* parse and compile else statement */
|
||||
void pelse() {
|
||||
DEBUG("Parsing ELSE statement '%c'\n", nxtchr);
|
||||
DEBUG("Parsing ELSE statement\n", 0);
|
||||
strcpy(lbltmp, lblasm); //Save Line Label
|
||||
lblasm[0] = 0; //and Clear It
|
||||
newlbl(skplbl); //Create Skip Label
|
||||
@ -306,6 +306,47 @@ void pretrn() {
|
||||
lsrtrn = TRUE; //Set RETURN flag
|
||||
}
|
||||
|
||||
/* parse and compile select statement */
|
||||
void pslct() {
|
||||
DEBUG("Parsing SELECT statement\n", 0);
|
||||
expect('(');
|
||||
prsxpr(')'); //Parse Expression
|
||||
newlbl(endlbl); //Create New Label
|
||||
pshlbl(LTSLCT,endlbl); //Push Onto Stack
|
||||
bgnblk(TRUE); //Check For and Begin Block
|
||||
strcpy(xstmnt, "CASE"); //Require Next Statement to be CASE
|
||||
}
|
||||
|
||||
/* process end of case block */
|
||||
void ecase() {
|
||||
if (poplbl(cndlbl) != LTCASE)
|
||||
ERROR("%s not at end of CASE block\n", word, EXIT_FAILURE);
|
||||
if (toplbl(endlbl) != LTSLCT)
|
||||
ERROR("Illegal nesting in SELECT statement\n", 0, EXIT_FAILURE);
|
||||
asmlin("JMP", endlbl); //Emit jump over default case
|
||||
setlbl(cndlbl); //Set entry point label to emit
|
||||
}
|
||||
|
||||
/* parse and compile select statement */
|
||||
void pcase() {
|
||||
if (strcmp(xstmnt, "CASE") == 0)
|
||||
xstmnt[0] = 0; //Clear xstmnt
|
||||
else
|
||||
ecase("CASE"); //Process end of case block
|
||||
prstrm(); //Parse CASE argument
|
||||
asmlin("CMP", term); //Emit Comparison
|
||||
expect(':');
|
||||
newlbl(cndlbl); //Create Conditional Label
|
||||
pshlbl(LTCASE, cndlbl); //and Push onto Stack
|
||||
asmlin("BNE", cndlbl); //Emit skip of CASE body
|
||||
}
|
||||
|
||||
/* parse and compile default statement */
|
||||
void pdflt() {
|
||||
expect(':');
|
||||
ecase(); //Process end of case block
|
||||
}
|
||||
|
||||
/* parse and compile while statement */
|
||||
void pwhile() {
|
||||
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
|
||||
@ -385,15 +426,18 @@ void pstmnt()
|
||||
return;
|
||||
}
|
||||
if (wordis("SWITCH")) {
|
||||
punimp();
|
||||
ERROR("SWITCH not implemented. Use SELECT.\n", word, EXIT_FAILURE);
|
||||
}
|
||||
if (wordis("SELECT")) {
|
||||
pslct();
|
||||
return;
|
||||
}
|
||||
if (wordis("CASE")) {
|
||||
punimp();
|
||||
pcase();
|
||||
return;
|
||||
}
|
||||
if (wordis("DEFAULT")) {
|
||||
punimp();
|
||||
pdflt();
|
||||
return;
|
||||
}
|
||||
if (wordis("WHILE")) {
|
||||
|
Loading…
Reference in New Issue
Block a user