1
0
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:
RevCurtisP 2018-02-05 22:49:13 -05:00 committed by GitHub
commit eec6b17878
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 229 additions and 45 deletions

5
c02.c
View File

@ -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

BIN
c02.exe

Binary file not shown.

138
c02.ppx
View File

@ -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>

BIN
c02.tag

Binary file not shown.

View File

@ -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

View File

@ -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
View File

@ -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 */

View File

@ -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
View File

@ -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")) {