mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-29 01:49:19 +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();
|
getwrd();
|
||||||
ACMNT(word);
|
ACMNT(word);
|
||||||
DEBUG("Parsing Word '%s'\n", word);
|
DEBUG("Parsing Word '%s'\n", word);
|
||||||
if (xstmnt[0])
|
if (xstmnt[0] && !wordis(xstmnt))
|
||||||
if (wordis(xstmnt))
|
|
||||||
xstmnt[0] = 0;
|
|
||||||
else
|
|
||||||
ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE);
|
ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE);
|
||||||
if (!pmodfr() && !ptype(MTNONE))
|
if (!pmodfr() && !ptype(MTNONE))
|
||||||
pstmnt(); //Parse Statement
|
pstmnt(); //Parse Statement
|
||||||
|
138
c02.ppx
138
c02.ppx
@ -2,32 +2,7 @@
|
|||||||
<settings version="1.0">
|
<settings version="1.0">
|
||||||
<category name="expr.h" />
|
<category name="expr.h" />
|
||||||
<category name="cond.h" />
|
<category name="cond.h" />
|
||||||
<category name="asm.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="Window">
|
<category name="Window">
|
||||||
<property name="Left" type="integer">78</property>
|
<property name="Left" type="integer">78</property>
|
||||||
<property name="Top" type="integer">78</property>
|
<property name="Top" type="integer">78</property>
|
||||||
@ -37,7 +12,116 @@
|
|||||||
<property name="Active" type="integer">0</property>
|
<property name="Active" type="integer">0</property>
|
||||||
</category>
|
</category>
|
||||||
</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="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="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>
|
</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
|
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
|
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
|
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.
|
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
|
WHILE LOOPS
|
||||||
|
|
||||||
The while statement is used to conditionally execute code in a loop. When
|
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
|
while() if (rdkey()) break; //Wait for a keypress
|
||||||
|
|
||||||
Note: While loops are compiled using the 6502 JMP statements, so the code
|
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
|
DO WHILE LOOPS
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ C02 only supports one data type: unsigned char.
|
|||||||
POINTERS
|
POINTERS
|
||||||
|
|
||||||
C02 does not support pointer type variables or parameters. However, the
|
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
|
DECLARATIONS
|
||||||
|
|
||||||
@ -28,3 +28,10 @@ EXPRESSIONS
|
|||||||
C02 supports the addition, subtraction, bitwise-and, bitwise-or, and
|
C02 supports the addition, subtraction, bitwise-and, bitwise-or, and
|
||||||
exclusive-or operators. The multiplication, division, and binary shift
|
exclusive-or operators. The multiplication, division, and binary shift
|
||||||
operators are not supported. These can be implemented through functions.
|
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 */
|
/* Pop Label from Stack and Emit on Next Line */
|
||||||
int poplbl()
|
int poplbl()
|
||||||
{
|
{
|
||||||
@ -102,12 +100,27 @@ int poplbl()
|
|||||||
else if (lbtype == LTDWHL)
|
else if (lbtype == LTDWHL)
|
||||||
strcpy(endlbl, lblnam[lblcnt]);
|
strcpy(endlbl, lblnam[lblcnt]);
|
||||||
//strcpy(cndlbl, lblnam[lblcnt]);
|
//strcpy(cndlbl, lblnam[lblcnt]);
|
||||||
|
else if (lbtype == LTCASE)
|
||||||
|
strcpy(cndlbl, lblnam[lblcnt]);
|
||||||
else
|
else
|
||||||
setlbl(lblnam[lblcnt]);
|
setlbl(lblnam[lblcnt]);
|
||||||
inblck = lblblk[lblcnt-1];
|
if (lbtype != LTCASE)
|
||||||
|
inblck = lblblk[lblcnt-1];
|
||||||
return lbtype;
|
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 *
|
/* Push Label onto Stack *
|
||||||
* Args: lbltyp - Label type *
|
* Args: lbltyp - Label type *
|
||||||
* Uses: curlbl - Label to push */
|
* 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
|
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, LTFUNC}; //Label Types
|
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label 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
|
||||||
|
56
stmnt.c
56
stmnt.c
@ -204,7 +204,7 @@ void pfor() {
|
|||||||
|
|
||||||
/* parse and compile if statement */
|
/* parse and compile if statement */
|
||||||
void pif() {
|
void pif() {
|
||||||
DEBUG("Parsing IF statement '%c'\n", nxtchr);
|
DEBUG("Parsing IF statement\n", 0);
|
||||||
expect('(');
|
expect('(');
|
||||||
newlbl(cndlbl); //Create New Label
|
newlbl(cndlbl); //Create New Label
|
||||||
pshlbl(LTIF,cndlbl); //Push Onto Stack
|
pshlbl(LTIF,cndlbl); //Push Onto Stack
|
||||||
@ -214,7 +214,7 @@ void pif() {
|
|||||||
|
|
||||||
/* parse and compile else statement */
|
/* parse and compile else statement */
|
||||||
void pelse() {
|
void pelse() {
|
||||||
DEBUG("Parsing ELSE statement '%c'\n", nxtchr);
|
DEBUG("Parsing ELSE statement\n", 0);
|
||||||
strcpy(lbltmp, lblasm); //Save Line Label
|
strcpy(lbltmp, lblasm); //Save Line Label
|
||||||
lblasm[0] = 0; //and Clear It
|
lblasm[0] = 0; //and Clear It
|
||||||
newlbl(skplbl); //Create Skip Label
|
newlbl(skplbl); //Create Skip Label
|
||||||
@ -306,6 +306,47 @@ void pretrn() {
|
|||||||
lsrtrn = TRUE; //Set RETURN flag
|
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 */
|
/* parse and compile while statement */
|
||||||
void pwhile() {
|
void pwhile() {
|
||||||
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
|
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
|
||||||
@ -385,15 +426,18 @@ void pstmnt()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (wordis("SWITCH")) {
|
if (wordis("SWITCH")) {
|
||||||
punimp();
|
ERROR("SWITCH not implemented. Use SELECT.\n", word, EXIT_FAILURE);
|
||||||
return;
|
}
|
||||||
|
if (wordis("SELECT")) {
|
||||||
|
pslct();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (wordis("CASE")) {
|
if (wordis("CASE")) {
|
||||||
punimp();
|
pcase();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (wordis("DEFAULT")) {
|
if (wordis("DEFAULT")) {
|
||||||
punimp();
|
pdflt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (wordis("WHILE")) {
|
if (wordis("WHILE")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user