mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-22 01:31:33 +00:00
Numerous modifications
This commit is contained in:
parent
bfc84d11c5
commit
9d8195415a
3
asm.c
3
asm.c
@ -24,13 +24,14 @@ void setcmt(char *s)
|
||||
/* Append string to comment */
|
||||
void addcmt(char *s)
|
||||
{
|
||||
strcat(cmtasm, " ");
|
||||
//strcat(cmtasm, " ");
|
||||
strcat(cmtasm, s);
|
||||
}
|
||||
|
||||
/* Append character to comment */
|
||||
void chrcmt(char c)
|
||||
{
|
||||
if (cmtasm[0] == 0 && c == ' ') return;
|
||||
int i = strlen(cmtasm);
|
||||
cmtasm[i++] = c;
|
||||
cmtasm[i] = 0;
|
||||
|
67
c02.c
67
c02.c
@ -41,8 +41,12 @@ void init()
|
||||
xstmnt[0] = 0;
|
||||
nxtwrd[0] = 0;
|
||||
nxtptr = 0;
|
||||
vrwrtn = FALSE;
|
||||
zpaddr = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Reads and parses the next Word in Source File */
|
||||
pword()
|
||||
{
|
||||
@ -55,11 +59,7 @@ pword()
|
||||
xstmnt[0] = 0;
|
||||
else
|
||||
ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE);
|
||||
if (wordis("void"))
|
||||
pdecl(VTVOID); //Parse 'void' declaration
|
||||
else if (wordis("char"))
|
||||
pdecl(VTCHAR); //Parse 'char' declaration
|
||||
else
|
||||
if (!pmodfr() && !ptype(MTNONE))
|
||||
pstmnt(); //Parse Statement
|
||||
}
|
||||
|
||||
@ -69,17 +69,22 @@ void pdrctv()
|
||||
skpchr(); //skip '#'
|
||||
getwrd(); //read directive into word
|
||||
DEBUG("Processing directive '%s'\n", word);
|
||||
if (wordis("define"))
|
||||
prsdef(); //Parse Define
|
||||
if (wordis("include"))
|
||||
if (wordis("DEFINE"))
|
||||
pdefin(); //Parse Define
|
||||
else if (wordis("INCLUDE"))
|
||||
pincfl(); //Parse Include File
|
||||
else if (wordis("error"))
|
||||
else if (wordis("ERROR")) {
|
||||
ERROR("Error \n", 0, EXIT_FAILURE);
|
||||
}
|
||||
else if (wordis("PRAGMA"))
|
||||
pprgma();
|
||||
else
|
||||
ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void epilog()
|
||||
{
|
||||
vartbl(); //Write Variable Table
|
||||
if (!vrwrtn) vartbl(); //Write Variable Table
|
||||
}
|
||||
|
||||
/* Compile Source Code*/
|
||||
@ -117,19 +122,44 @@ void usage()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse Command Line Argument */
|
||||
int popt(int arg, int argc, char *argv[])
|
||||
{
|
||||
char opt; //Option
|
||||
char optarg[32]; //Option Argument
|
||||
opt = argv[arg][1];
|
||||
//if strchr(opt, "i") {
|
||||
//if (strlen(argv[arg] > 2)
|
||||
//}
|
||||
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse Command Line Arguments *
|
||||
* Sets: srcnam - Source File Name (from first arg) *
|
||||
* outnam - Output File Name (from optional second arg) */
|
||||
void pargs(int argc, char *argv[])
|
||||
{
|
||||
DEBUG("Parsing %d Arguments\n", argc);
|
||||
if (argc < 2) usage(); //at least one argument is required
|
||||
strcpy(srcnam, argv[1]); //set Source File Name to first arg
|
||||
DEBUG("srcnam set to '%s'\n", srcnam);
|
||||
if (argc > 2) //if second argument exists
|
||||
strcpy(outnam, argv[2]); //set Out File Name to second arg
|
||||
else strcpy(outnam, ""); //else set to null string
|
||||
DEBUG("outnam set to '%s'\n", outnam);
|
||||
int arg;
|
||||
srcnam[0] = 0;
|
||||
outnam[0] = 0;
|
||||
DEBUG("Parsing %d arguments\n", argc);
|
||||
if (argc == 0) usage(); //at least one argument is required
|
||||
for (arg = 1; arg<argc; arg++) {
|
||||
DEBUG("Parsing argument %d\n", arg);
|
||||
if (argv[arg][0] == '-') {
|
||||
arg = popt(arg, argc, argv);
|
||||
}
|
||||
else if (srcnam[0] == 0) {
|
||||
strcpy(srcnam, argv[arg]); //set Source File Name to first arg
|
||||
DEBUG("srcnam set to '%s'\n", srcnam);
|
||||
}
|
||||
else if (outnam[0] == 0) {
|
||||
strcpy(outnam, argv[arg]); //set Out File Name to second arg
|
||||
DEBUG("outnam set to '%s'\n", outnam);
|
||||
}
|
||||
else
|
||||
ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -147,6 +177,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
compile();
|
||||
|
||||
logdef();
|
||||
logvar();
|
||||
|
||||
clssrc(); //Close Source File
|
||||
|
3
common.h
3
common.h
@ -8,7 +8,7 @@
|
||||
|
||||
#define FNAMLEN 255 //Maximum File Name Length
|
||||
#define LINELEN 255 //Maximum Input/Output Line Length
|
||||
#define DEFLEN 9 //Maximum Definition Text Length
|
||||
#define DEFLEN 6 //Maximum Definition Text Length
|
||||
#define MAXDEF 255 //Maximum Number of Definitions
|
||||
#define VARLEN 6 //Maximum Variable Length
|
||||
#define MAXVAR 255 //Maximum Number of Variables
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
|
||||
#define CPUARG "6502" //Target CPU Operand
|
||||
#define ORGOP "ORG" //Equate Pseudo-Op
|
||||
#define EQUOP "EQU" //Equate Pseudo-Op
|
||||
#define BYTEOP "DC" //Define Byte Pseudo-Op
|
||||
#define STROP "DS" //Define String Pseudo-Op
|
||||
|
6
cond.c
6
cond.c
@ -86,7 +86,7 @@ void prccmp()
|
||||
}
|
||||
|
||||
/* Parse Comparison */
|
||||
int prscmp(revrse)
|
||||
int prscmp(int revrse)
|
||||
{
|
||||
skpspc();
|
||||
cmpenc = enccmp(nxtchr); //Encode Comparison Character
|
||||
@ -131,12 +131,12 @@ void prscnd(char trmntr, int revrse)
|
||||
revrse = (revrse) ? FALSE: TRUE;
|
||||
DEBUG("Set revrse to %d\n", revrse);
|
||||
}
|
||||
prsxpr(0);
|
||||
if (!look('*'))
|
||||
prsxpr(0);
|
||||
if (look(':'))
|
||||
prsflg(revrse); //Parse Flag Operator
|
||||
else
|
||||
prscmp(revrse); //Parse Comparison Operator
|
||||
CCMNT(trmntr);
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
|
181
expr.c
181
expr.c
@ -17,17 +17,18 @@
|
||||
/* Parse value (constant or identifier) *
|
||||
* Sets: value - the value (as a string) *
|
||||
* valtyp - value type */
|
||||
void prsval()
|
||||
void prsval(int alwreg)
|
||||
{
|
||||
DEBUG("Parsing value\n", 0);
|
||||
//expdef(); //Check for and expand define -- BROKEN!
|
||||
skpspc();
|
||||
if (iscpre())
|
||||
prscon(0xff); //Parse Constant
|
||||
prscon(); //Parse Constant
|
||||
else if (isalph()) {
|
||||
prsvar(); //Parse Variable
|
||||
prsvar(alwreg); //Parse Variable
|
||||
}
|
||||
else
|
||||
expctd("constant or variable");
|
||||
DEBUG("Parsed value of type %d\n", valtyp);
|
||||
skpspc();
|
||||
}
|
||||
|
||||
@ -37,85 +38,112 @@ void prsval()
|
||||
void prsidx()
|
||||
{
|
||||
expect('[');
|
||||
prsval();
|
||||
prsval(TRUE);
|
||||
DEBUG("Parsed array index '%s'\n", value);
|
||||
expect(']');
|
||||
}
|
||||
|
||||
/* Parse term in expression *
|
||||
* Sets: term - the term (as a string) *
|
||||
* trmtxt - type of term */
|
||||
/* Check for, Parse, and Process index */
|
||||
void chkidx()
|
||||
{
|
||||
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp);
|
||||
if (valtyp == ARRAY) {
|
||||
prsidx();
|
||||
if (valtyp == CONSTANT) {
|
||||
strcat(term, "+");
|
||||
strcat(term, value);
|
||||
}
|
||||
else if (strcmp(value, "Y")==0)
|
||||
strcat(term, ",Y");
|
||||
else {
|
||||
if (strcmp(value, "A")==0)
|
||||
asmlin("TAX", "");
|
||||
else if (strcmp(value, "X")!=0)
|
||||
asmlin("LDX", value);
|
||||
strcat(term, ",X");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse term in expression *
|
||||
* Sets: term - the term (as a string) */
|
||||
void prstrm()
|
||||
{
|
||||
DEBUG("Parsing term\n", 0);
|
||||
prsval();
|
||||
prsval(FALSE);
|
||||
if (valtyp == FUNCTION) {
|
||||
ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE);
|
||||
}
|
||||
strcpy(term, value);
|
||||
DEBUG("Parsed term %s\n", term);
|
||||
trmtxt = valtyp;
|
||||
if (trmtxt == ARRAY) {
|
||||
prsidx();
|
||||
asmlin("LDX", value);
|
||||
strcat(term, ",X");
|
||||
}
|
||||
chkidx(); //Check for Array Index
|
||||
//chkpst = ispopr(); //Check for Post-Op
|
||||
skpspc();
|
||||
}
|
||||
|
||||
/* Compile Address Reference */
|
||||
void prcadr(char* symbol)
|
||||
void prcadr(int adract, char* symbol)
|
||||
{
|
||||
strcpy(word,"#<");
|
||||
strcat(word,symbol);
|
||||
asmlin("LDX", word);
|
||||
DEBUG("Processing address '%s'\n", word);
|
||||
strcpy(word,"#>");
|
||||
strcat(word,symbol);
|
||||
asmlin("LDY", word);
|
||||
if (adract == 1) {
|
||||
asmlin("LDA", word);
|
||||
asmlin("PHA", "");
|
||||
}
|
||||
else
|
||||
asmlin("LDY", word);
|
||||
strcpy(word,"#<");
|
||||
strcat(word,symbol);
|
||||
if (adract == 1) {
|
||||
asmlin("LDA", word);
|
||||
asmlin("PHA", "");
|
||||
}
|
||||
else
|
||||
asmlin("LDX", word);
|
||||
}
|
||||
|
||||
/* Parse and Compile Address of Operator */
|
||||
void prsadr()
|
||||
void prsadr(int adract)
|
||||
{
|
||||
prsvar();
|
||||
DEBUG("Parsing address of variable '%s'\n", value);
|
||||
prcadr(value); //Compile Address Reference
|
||||
DEBUG("Parsing address\n", 0);
|
||||
if (isnpre())
|
||||
prsnum(0xFFFF);
|
||||
else
|
||||
prsvar(FALSE);
|
||||
prcadr(adract, value); //Compile Address Reference
|
||||
}
|
||||
|
||||
/* Parse and Create Anonymous String */
|
||||
void prsstr()
|
||||
void prsstr(adract)
|
||||
{
|
||||
DEBUG("Parsing anonymous string\n", 0);
|
||||
newlbl(vrname); //Generate Variable Name
|
||||
value[0] = 0; //Use Variable Size 0
|
||||
setvar(VTCHAR); //Set Variable Name, Type, and Size
|
||||
prsdts(); //Parse Data String
|
||||
setdat(); //Set Variable Data
|
||||
varcnt++; //Increment Variable Counter
|
||||
prcadr(vrname); //Compile Address Reference
|
||||
newlbl(vrname); //Generate Variable Name
|
||||
value[0] = 0; //Use Variable Size 0
|
||||
setvar(VTCHAR); //Set Variable Name, Type, and Size
|
||||
prsdts(); //Parse Data String
|
||||
setdat(); //Set Variable Data
|
||||
varcnt++; //Increment Variable Counter
|
||||
prcadr(adract, vrname); //Compile Address Reference
|
||||
}
|
||||
|
||||
/* Parse Additional Function Parameters */
|
||||
void prsfnp()
|
||||
/* Check for and Process Address or String */
|
||||
int chkadr(adract)
|
||||
{
|
||||
if (look(',')) {
|
||||
if (look('&'))
|
||||
prsadr();
|
||||
else if (match('"'))
|
||||
prsstr();
|
||||
else {
|
||||
prstrm();
|
||||
asmlin("LDY", term);
|
||||
if (look(',')) {
|
||||
prsval();
|
||||
asmlin("LDX", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG("Checking for Address or String\n", 0);
|
||||
int result = TRUE;
|
||||
if (look('&'))
|
||||
prsadr(adract);
|
||||
else if (match('"'))
|
||||
prsstr(adract);
|
||||
else
|
||||
result = FALSE;
|
||||
skpspc();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse function call */
|
||||
void prsfnc()
|
||||
void prsfnc(char trmntr)
|
||||
{
|
||||
DEBUG("Processing Function Call '%s'...\n", term);
|
||||
if (fnscnt >= MAXFNS)
|
||||
@ -123,15 +151,25 @@ void prsfnc()
|
||||
strcpy(fnstck[fnscnt++], term);
|
||||
skpchr(); //skip open paren
|
||||
CCMNT('(');
|
||||
if (look('&'))
|
||||
prsadr();
|
||||
else if (match('"'))
|
||||
prsstr();
|
||||
else if (isvpre()) {
|
||||
prsxpr(0);
|
||||
prsfnp();
|
||||
}
|
||||
if (!chkadr(0) && isxpre() || match('*')) {
|
||||
if (!look('*')) prsxpr(0);
|
||||
if (look(',')) {
|
||||
if (!chkadr(0)) {
|
||||
if (!look('*')) {
|
||||
prstrm();
|
||||
asmlin("LDY", term);
|
||||
}
|
||||
if (look(',')) {
|
||||
if (!look('*')) {
|
||||
prsval(FALSE);
|
||||
asmlin("LDX", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expect(')');
|
||||
expect(trmntr);
|
||||
asmlin("JSR", fnstck[--fnscnt]);
|
||||
skpspc();
|
||||
}
|
||||
@ -140,20 +178,24 @@ void prsfnc()
|
||||
* First term can include function calls */
|
||||
void prsftm()
|
||||
{
|
||||
prsval();
|
||||
prsval(TRUE);
|
||||
DEBUG("Processing first term '%s'...\n", value);
|
||||
strcpy(term, value);
|
||||
trmtxt = valtyp;
|
||||
if (trmtxt == FUNCTION) {
|
||||
prsfnc(); //Parse Expression Function
|
||||
if (valtyp == FUNCTION) {
|
||||
prsfnc(0); //Parse Expression Function
|
||||
return;
|
||||
}
|
||||
if (trmtxt == ARRAY) {
|
||||
prsidx();
|
||||
asmlin("LDX", value);
|
||||
strcat(term, ",X");
|
||||
if (wordis("A"))
|
||||
return;
|
||||
//if (ispopr()) oper = prspst(0, term); //Check for Post-Operator
|
||||
if (wordis("X"))
|
||||
asmlin("TXA", "");
|
||||
else if (wordis("Y"))
|
||||
asmlin("TYA", "");
|
||||
else {
|
||||
chkidx(); //Check for Array Index
|
||||
asmlin("LDA", term);
|
||||
}
|
||||
asmlin("LDA", term);
|
||||
}
|
||||
|
||||
/* Process Arithmetic or Bitwise Operator *
|
||||
@ -185,6 +227,7 @@ void prcopr()
|
||||
printf("Unrecognized operator '%c'\n", oper);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
oper = 0;
|
||||
}
|
||||
|
||||
/* Parse and compile expression */
|
||||
@ -194,17 +237,17 @@ void prsxpr(char trmntr)
|
||||
skpspc();
|
||||
if (match('-')) {
|
||||
DEBUG("Processing unary minus", 0);
|
||||
asmlin("LDA", "#$00"); //Handle Unary Minus
|
||||
asmlin("LDA", "#$00"); //Handle Unary Minus
|
||||
}
|
||||
else
|
||||
prsftm(); //Parse First Term
|
||||
skpspc();
|
||||
while (isoper())
|
||||
{
|
||||
prsopr(); //Parse Operator
|
||||
prstrm(); //Parse Term
|
||||
prcopr(); //Process Operator
|
||||
}
|
||||
if (trmntr)
|
||||
expect(trmntr);
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
|
3
expr.h
3
expr.h
@ -3,11 +3,12 @@
|
||||
**********************************/
|
||||
|
||||
char term[255]; /*Term parsed from equation*/
|
||||
int trmtxt; /*Term Type*/
|
||||
|
||||
char fnstck[MAXFNS][VARLEN+1]; //Function Call Stack
|
||||
int fnscnt; //Number of Functions in Stack
|
||||
|
||||
int chkpst; //Check for Post-Operator
|
||||
|
||||
void prsidx(); //Parse Array Index
|
||||
void prstrm(); //Parse Term in Expression
|
||||
void prsxpr(char trmntr); //Parse Expression
|
||||
|
80
include.c
80
include.c
@ -55,14 +55,68 @@ void incasm() {
|
||||
clsinc();
|
||||
}
|
||||
|
||||
/* Process define directive */
|
||||
void pdefin()
|
||||
{
|
||||
getwrd(); //get defined identifier
|
||||
DEBUG("Defining '%s'\n", word);
|
||||
strncpy(defnam[defcnt], word, VARLEN);
|
||||
setlbl(word); //Set label Assembler Line
|
||||
expect('=');
|
||||
defval[defcnt++] = prsbyt(); //Get Value
|
||||
asmlin(EQUOP, value); //Write Definition
|
||||
DEBUG("Defined as '%s'\n", value);
|
||||
}
|
||||
|
||||
/* Parse Origin Subdirective */
|
||||
void porign()
|
||||
{
|
||||
prsnum(0xFFFF); //Get Origin Address
|
||||
asmlin(ORGOP, value); //Emit Origin Instruction
|
||||
DEBUG("Set origin to %s\n", value);
|
||||
}
|
||||
|
||||
/* Parse Origin Subdirective */
|
||||
void prszpg()
|
||||
{
|
||||
zpaddr = prsnum(0xFF); //Set Zero Page Address to Constant
|
||||
DEBUG("Set zero page address to %d\n", zpaddr);
|
||||
}
|
||||
|
||||
/* Process Vartable Subdirective */
|
||||
void pvrtbl()
|
||||
{
|
||||
if (vrwrtn) {
|
||||
ERROR("Variable table already written", 0, EXIT_FAILURE);
|
||||
}
|
||||
vartbl(); //Write Variable Table
|
||||
}
|
||||
|
||||
/* Parse Pragma Directive */
|
||||
void pprgma()
|
||||
{
|
||||
getwrd(); //Get Pragma Subdirective
|
||||
DEBUG("Parsing pragma directive '%s'\n", word);
|
||||
if (wordis("ORIGIN"))
|
||||
porign(); //Parse Origin
|
||||
else if (wordis("VARTABLE"))
|
||||
pvrtbl(); //Parse Vartable
|
||||
else if (wordis("ZEROPAGE"))
|
||||
prszpg(); //Parse Origin
|
||||
else
|
||||
ERROR("Illegal pragma subdirective '%s'\n", word, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Process Include File Directive */
|
||||
void pincdr()
|
||||
{
|
||||
skpchr(); //skip '#'
|
||||
getwrd(); //read directive into word
|
||||
DEBUG("Processing include file directive '%s'\n", word);
|
||||
if (wordis("define"))
|
||||
prsdef();
|
||||
if (wordis("DEFINE"))
|
||||
pdefin();
|
||||
if (wordis("PRAGMA"))
|
||||
pprgma();
|
||||
else {
|
||||
printf("Unrecognized directive '%s'\n", word);
|
||||
exterr(EXIT_FAILURE);
|
||||
@ -72,11 +126,7 @@ void pincdr()
|
||||
/* Parse Header Word */
|
||||
void phdwrd() {
|
||||
getwrd();
|
||||
if (wordis("void"))
|
||||
pdecl(VTVOID);
|
||||
else if (wordis("char"))
|
||||
pdecl(VTCHAR);
|
||||
else {
|
||||
if (!ptype(MTNONE)) {
|
||||
printf("Unexpected word '%s' in header\n", word);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
@ -151,13 +201,15 @@ void pincfl()
|
||||
printf("Invalid include file name '%sn", incnam);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
if (strcmp(dot, ".a02") == 0)
|
||||
incasm();
|
||||
if (strcmp(dot, ".asm") == 0)
|
||||
incasm();
|
||||
else if (strcmp(dot, ".h") == 0)
|
||||
include_hfil();
|
||||
else if (strcmp(dot, ".h02") == 0) {
|
||||
inchdr(); //Process Header File
|
||||
strcpy(dot, ".asm");
|
||||
strcpy(dot, ".a02");
|
||||
incasm(); //Process Assembly File with Same Name
|
||||
}
|
||||
else {
|
||||
@ -166,3 +218,15 @@ void pincfl()
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Definition Table to Log File */
|
||||
void logdef()
|
||||
{
|
||||
int i;
|
||||
fprintf(logfil, "\n%-31s %5s\n", "Definition", "Value");
|
||||
for (i=0; i<defcnt; i++)
|
||||
{
|
||||
fprintf(logfil, "%-31s %5d\n", defnam[i], defval[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,6 @@
|
||||
* C02 Include File Parsing Routines *
|
||||
*************************************/
|
||||
|
||||
char line[255]; /*Entire line parsed from include file*/
|
||||
char line[255]; /*Entire line parsed from include file*/
|
||||
|
||||
|
||||
|
46
label.c
46
label.c
@ -13,17 +13,21 @@
|
||||
#include "parse.h"
|
||||
#include "label.h"
|
||||
|
||||
/* Find Last Label of Specified Type *
|
||||
* Args: lbtype: Label type *
|
||||
* Sets: tmplbl - Label name *
|
||||
* Returns: Index into label table *
|
||||
* (-1 if not found) */
|
||||
int lstlbl(int lbtype)
|
||||
/* 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 i;
|
||||
DEBUG("Searching for label type %d\n", lbtype);
|
||||
for (i = lblcnt - 1; i>-1; i--)
|
||||
if (lbltyp[i] == lbtype) break;
|
||||
DEBUG("Searching for label type %d ", lbtyp1);
|
||||
DEBUG("and label type %d\n",lbtyp2);
|
||||
for (i = lblcnt - 1; i>-1; i--) {
|
||||
if (lbltyp[i] == lbtyp1) break;
|
||||
if (lbltyp[i] == lbtyp2) break;
|
||||
}
|
||||
DEBUG("Search produced label index %d\n", i);
|
||||
if (i>=0)
|
||||
strcpy(tmplbl, lblnam[i]);
|
||||
@ -42,8 +46,10 @@ void setblk(int blkflg)
|
||||
void setlbl(char *lblset)
|
||||
{
|
||||
DEBUG("Setting Label '%s'\n", lblset);
|
||||
if (strlen(lblasm) > 0)
|
||||
if (strlen(lblasm) > 0) {
|
||||
DEBUG("Emitting Label '%s'\n'", lblasm);
|
||||
asmlin("",""); //Emit Block End Label on it's own line
|
||||
}
|
||||
if (strlen(lblset) > LABLEN)
|
||||
ERROR("Label '%s' exceeds maximum size\n", word, EXIT_FAILURE);
|
||||
strcpy(lblasm, lblset);
|
||||
@ -53,6 +59,7 @@ void setlbl(char *lblset)
|
||||
void prslbl()
|
||||
{
|
||||
DEBUG("Parsing Label '%s''\n", word);
|
||||
CCMNT(nxtchr);
|
||||
skpchr(); //skip ':'
|
||||
setlbl(word);
|
||||
}
|
||||
@ -64,6 +71,22 @@ void newlbl(char* lbname)
|
||||
DEBUG("Generated new label '%s'\n", lbname);
|
||||
}
|
||||
|
||||
/* require label *
|
||||
* if label is already set, returns that label *
|
||||
* else generates new label and sets it */
|
||||
void reqlbl(char* lbname)
|
||||
{
|
||||
if (lblasm[0])
|
||||
strcpy(lbname, lblasm);
|
||||
else {
|
||||
newlbl(lbname);
|
||||
setlbl(lbname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Pop Label from Stack and Emit on Next Line */
|
||||
int poplbl()
|
||||
{
|
||||
@ -76,6 +99,9 @@ int poplbl()
|
||||
}
|
||||
else if (lbtype == LTDO)
|
||||
strcpy(loplbl, lblnam[lblcnt]);
|
||||
else if (lbtype == LTDWHL)
|
||||
strcpy(endlbl, lblnam[lblcnt]);
|
||||
//strcpy(cndlbl, lblnam[lblcnt]);
|
||||
else
|
||||
setlbl(lblnam[lblcnt]);
|
||||
inblck = lblblk[lblcnt-1];
|
||||
|
3
label.h
3
label.h
@ -18,9 +18,8 @@ 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 {LTIF, LTLOOP, LTEND, LTDO, LTCASE, LTFUNC}; //Label Types
|
||||
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTFUNC}; //Label Types
|
||||
|
||||
int lstlbl(int lbtype); //Find Last Label of Specified Type
|
||||
void prslbl(); //Parse Label From Code
|
||||
void newlbl(char* lbname); //Generate New Block Label
|
||||
int poplbl(); //Pull Last Label and Emit on Next Line
|
||||
|
198
parse.c
198
parse.c
@ -12,8 +12,6 @@
|
||||
#include "files.h"
|
||||
#include "parse.h"
|
||||
|
||||
char opstr[2]; //Operator as a String
|
||||
|
||||
/* Various tests against nxtchr */
|
||||
int match(char c) {return TF(nxtchr == c);}
|
||||
int inbtwn(char mn, char mx) {return TF(nxtchr >= mn && nxtchr <= mx);}
|
||||
@ -27,10 +25,13 @@ int isnl() {return TF(match('\n') || match('\r'));}
|
||||
int isspc() {return isspace(nxtchr);}
|
||||
int isnpre() {return TF(isdec() || match('$') || match('%'));}
|
||||
int isapos() {return match('\'');}
|
||||
int iscpre() {return TF(isnpre() || isapos());}
|
||||
int isbpre() {return TF(isnpre() || isapos());}
|
||||
int ishash() {return match('#');}
|
||||
int iscpre() {return TF(isbpre() || ishash());}
|
||||
int isvpre() {return TF(isalph() || iscpre());}
|
||||
int isoper() {return TF(strchr("+-&|^", nxtchr));}
|
||||
int ispopr() {return TF(strchr("+-<>", nxtchr));}
|
||||
int isxpre() {return TF(isvpre() || match('-'));}
|
||||
|
||||
/* if Word is s then return TRUE else return FALSE*/
|
||||
int wordis(char *s)
|
||||
@ -61,6 +62,7 @@ char getnxt()
|
||||
void skpspc()
|
||||
{
|
||||
//DEBUG("Skipping Spaces\n", 0);
|
||||
if (isspc()) CCMNT(' ');
|
||||
while (isspc())
|
||||
getnxt();
|
||||
}
|
||||
@ -84,8 +86,8 @@ int look(char c)
|
||||
/* if next printable character is c then skip, else generate error */
|
||||
void expect(char c)
|
||||
{
|
||||
if (look(c))
|
||||
return;
|
||||
if (c == 0) return;
|
||||
if (look(c)) return;
|
||||
else {
|
||||
printf("Expected Character '%c', but found '%c'\n", c, nxtchr);
|
||||
exterr(EXIT_FAILURE);
|
||||
@ -131,55 +133,11 @@ void getwrd()
|
||||
if (!isalph()) expctd("Alphabetic Character");
|
||||
while (isanum())
|
||||
{
|
||||
word[wrdlen++] = getnxt();
|
||||
word[wrdlen++] = toupper(getnxt());
|
||||
}
|
||||
word[wrdlen] = 0;
|
||||
}
|
||||
|
||||
/* Get Definition Text */
|
||||
void getdef()
|
||||
{
|
||||
int wrdlen = 0;
|
||||
skpspc();
|
||||
while (isprnt()) {
|
||||
word[wrdlen++] = getnxt();
|
||||
}
|
||||
word[wrdlen] = 0;
|
||||
}
|
||||
|
||||
/* Process define directive */
|
||||
void prsdef()
|
||||
{
|
||||
getwrd(); //get defined identifier
|
||||
DEBUG("Defining '%s'\n", word);
|
||||
strncpy(defnam[defcnt], word, VARLEN);
|
||||
getdef();
|
||||
DEBUG("Defined as '%s'\n", word);
|
||||
strncat(deftxt[defcnt], word, DEFLEN);
|
||||
defcnt++;
|
||||
}
|
||||
|
||||
/* Check for and Expand DEFINE *
|
||||
* Sets: nxtwrd, nxtchr, nxtupr *
|
||||
* if match is found */
|
||||
void expdef()
|
||||
{
|
||||
int i;
|
||||
if (!isalph()) return;
|
||||
DEBUG("Checking for definition '%s'\n", word);
|
||||
nxtptr = 0;
|
||||
for (i=0; i<defcnt; i++) {
|
||||
if (strcmp(word, defnam[i]) == 0) {
|
||||
strcpy(nxtwrd, deftxt[i]);
|
||||
nxtchr = nxtwrd[0];
|
||||
nxtupc = toupper(nxtchr);
|
||||
DEBUG("Expanded to '%s'\n", word);
|
||||
return;
|
||||
}
|
||||
}
|
||||
strcpy(nxtwrd, word);
|
||||
}
|
||||
|
||||
char escape(char c)
|
||||
{
|
||||
DEBUG("Escaping character '%c'\n", c);
|
||||
@ -318,7 +276,7 @@ int prsnum(int maxval)
|
||||
{
|
||||
int number;
|
||||
skpspc();
|
||||
if (!iscpre()) expctd("constant value");
|
||||
if (!isbpre()) expctd("constant value");
|
||||
switch(nxtchr) {
|
||||
case '%':
|
||||
number = prsbin();
|
||||
@ -345,22 +303,51 @@ int prsnum(int maxval)
|
||||
return number;
|
||||
}
|
||||
|
||||
/* Parse numeric constant *
|
||||
* Args: maxval - maximum allowed value *
|
||||
* Sets: value - the constant (as a string) *
|
||||
* valtyp - value type (CONSTANT) */
|
||||
void prscon(int maxval)
|
||||
int prsbyt()
|
||||
{
|
||||
cnstnt = prsnum(maxval);
|
||||
valtyp = CONSTANT;
|
||||
if (maxval > 255)
|
||||
sprintf(value, "#$%04X", cnstnt);
|
||||
else
|
||||
sprintf(value, "#$%02X", cnstnt);
|
||||
DEBUG("Generated constant '%s'\n", value);
|
||||
ACMNT(word);
|
||||
return prsnum(0xFF);
|
||||
}
|
||||
|
||||
void fnddef(char *name)
|
||||
{
|
||||
DEBUG("Looking up defined constant '%s'\n", word);
|
||||
for (defidx=0; defidx<defcnt; defidx++) {
|
||||
if (strcmp(defnam[defidx], name) == 0)
|
||||
return;
|
||||
}
|
||||
defidx = -1;
|
||||
}
|
||||
|
||||
int prsdef()
|
||||
{
|
||||
expect('#');
|
||||
getwrd(); //Get Constant Name
|
||||
fnddef(word);
|
||||
if (defidx < 0) {
|
||||
ERROR("Undefined constant '%s'\n", word, EXIT_FAILURE);
|
||||
}
|
||||
strcpy(value, word);
|
||||
return defval[defidx];
|
||||
}
|
||||
|
||||
/* Parse numeric constant *
|
||||
* Args: maxval - maximum allowed value *
|
||||
* Sets: cnstnt - the constant (as an integer) *
|
||||
* value - the constant (as a string) *
|
||||
* valtyp - value type (CONSTANT) */
|
||||
void prscon()
|
||||
{
|
||||
skpspc();
|
||||
if (ishash())
|
||||
cnstnt = prsdef();
|
||||
else
|
||||
cnstnt = prsbyt();
|
||||
valtyp = CONSTANT;
|
||||
ACMNT(word);
|
||||
strcpy(value, "#");
|
||||
strcat(value, word);
|
||||
DEBUG("Generated constant '%s'\n", value);
|
||||
}
|
||||
|
||||
/* Get Value Type */
|
||||
int gettyp()
|
||||
@ -371,13 +358,14 @@ int gettyp()
|
||||
}
|
||||
|
||||
/* Parse next word as variable or function name *
|
||||
* Sets: value - Identifier Name *
|
||||
* valtyp - Identifier Type */
|
||||
void prsvar()
|
||||
* Args: alwreg - Allow Register Names *
|
||||
* Sets: value - Identifier Name *
|
||||
* valtyp - Identifier Type */
|
||||
void prsvar(int alwreg)
|
||||
{
|
||||
getwrd();
|
||||
valtyp = gettyp();
|
||||
if (valtyp != FUNCTION) chksym(word);
|
||||
if (valtyp != FUNCTION) chksym(alwreg, word);
|
||||
strcpy(value, word);
|
||||
DEBUG("Parsed variable '%s'\n", value);
|
||||
ACMNT(word);
|
||||
@ -390,9 +378,77 @@ void prsopr()
|
||||
expctd("Arithmetic or bitwise operator");
|
||||
oper = getnxt();
|
||||
DEBUG("Parsed operator '%c'\n", oper);
|
||||
opstr[0] = oper;
|
||||
opstr[1] = 0;
|
||||
ACMNT(opstr);
|
||||
CCMNT(oper);
|
||||
skpspc();
|
||||
}
|
||||
|
||||
void prcpst(char* name)
|
||||
{
|
||||
DEBUG("Processing post operation '%c'\n", oper);
|
||||
switch(oper)
|
||||
{
|
||||
case '+':
|
||||
if (strcmp(name, "X")==0)
|
||||
asmlin("INX", "");
|
||||
else if (strcmp(name, "Y")==0)
|
||||
asmlin("INY", "");
|
||||
else if (strcmp(name, "A")==0)
|
||||
poperr(); //65C02 supports implicit INC, 6502 does not
|
||||
else
|
||||
asmlin("INC", name);
|
||||
break;
|
||||
case '-':
|
||||
if (strcmp(name, "X")==0)
|
||||
asmlin("DEX", "");
|
||||
else if (strcmp(name, "Y")==0)
|
||||
asmlin("DEY", "");
|
||||
else if (strcmp(name, "A")==0)
|
||||
poperr(); //65C02 supports implicit DEC, 6502 does not
|
||||
else
|
||||
asmlin("DEC", name);
|
||||
break;
|
||||
case '<':
|
||||
if (strcmp(name, "X")==0)
|
||||
poperr(); //Index Register Shift not Supported
|
||||
else if (strcmp(name, "Y")==0)
|
||||
poperr(); //Index Register Shift not Supported
|
||||
else if (strcmp(name, "A")==0)
|
||||
asmlin("ASL", "");
|
||||
else
|
||||
asmlin("ASL", name);
|
||||
break;
|
||||
case '>':
|
||||
if (strcmp(name, "X")==0)
|
||||
poperr(); //Index Register Shift not Supported
|
||||
else if (strcmp(name, "Y")==0)
|
||||
poperr(); //Index Register Shift not Supported
|
||||
else if (strcmp(name, "A")==0)
|
||||
asmlin("LSR", "");
|
||||
else
|
||||
asmlin("LSR", name);
|
||||
break;
|
||||
default:
|
||||
printf("Unrecognized post operator '%c'\n", oper);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Post Operator */
|
||||
int prspst(char trmntr, char* name) {
|
||||
oper = getnxt();
|
||||
CCMNT(oper);
|
||||
DEBUG("Checking for post operation '%c'\n", oper);
|
||||
if (nxtchr == oper) {
|
||||
skpchr();
|
||||
CCMNT(oper);
|
||||
expect(trmntr);
|
||||
prcpst(name); //Process Post-Op
|
||||
oper = 0;
|
||||
}
|
||||
else {
|
||||
DEBUG("Not a post operation\n", 0);
|
||||
}
|
||||
return oper;
|
||||
}
|
||||
|
||||
|
||||
|
17
parse.h
17
parse.h
@ -4,20 +4,22 @@
|
||||
|
||||
#define TF(x) (x) ? TRUE : FALSE;
|
||||
|
||||
enum trmtxts {CONSTANT, VARIABLE, ARRAY, FUNCTION};
|
||||
enum etypes {ETDEF, ETMAC}; //Definition Types
|
||||
enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types
|
||||
enum etypes {ETDEF, ETMAC}; //Definition Types
|
||||
|
||||
char word[LINELEN]; //Word parsed from source file
|
||||
char uword[LINELEN]; //Word converted too uppercase
|
||||
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)
|
||||
int nxtptr; //Pointer to next character in nxtwrd
|
||||
char value[LINELEN]; //Term parsed from equation
|
||||
int valtyp; //Value Type
|
||||
char oper; //Arithmetic or Bitwise Operator
|
||||
int cnstnt; //Value of Parsed Constant
|
||||
int cnstnt; //Value of Parsed Constant
|
||||
|
||||
char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table
|
||||
char deftxt[MAXDEF+1][DEFLEN+1]; //Definition Text Table
|
||||
int defval[MAXDEF+1]; //Definition Value Table
|
||||
int defcnt; //Number of Definitions Defined
|
||||
int defidx; //Index into Definition Tables
|
||||
|
||||
int match(char c); //Does Next Character match c
|
||||
int inbtwn(char mn, char mx); //Is Next Character in Range ()mn - mx)
|
||||
@ -48,10 +50,9 @@ void skpcmt(); //Skip to End of Comment
|
||||
|
||||
void getwrd(); //Get Next Word
|
||||
|
||||
void expdef(); //Check for and Expand Definition
|
||||
|
||||
int prsdec(); //Get Decimal Number
|
||||
|
||||
void prscon(int maxval); //Parse a Constant
|
||||
void prscon(); //Parse a Constant
|
||||
void prsopr(); //Parse Arithmetic Operator
|
||||
void prsvar(); //Parse Variable
|
||||
void prsvar(int alwreg); //Parse Variable
|
||||
|
||||
|
336
stmnt.c
336
stmnt.c
@ -15,80 +15,97 @@
|
||||
#include "expr.h"
|
||||
#include "stmnt.h"
|
||||
|
||||
/* Parse Shortcut If */
|
||||
void prssif(char trmntr) {
|
||||
newlbl(cndlbl); //Create Label for "if FALSE" expression
|
||||
prscnd(')', FALSE); //Parse Condition
|
||||
expect('?');
|
||||
prsxpr(':'); //Parse "if TRUE" expression
|
||||
newlbl(tmplbl); //Create End of Expression Label
|
||||
asmlin("JMP", tmplbl); //Jump over "if FALSE" expression
|
||||
setlbl(cndlbl); //Emit "if FALSE" label
|
||||
prsxpr(trmntr); //Parse "if FALSE" expression
|
||||
setlbl(tmplbl); //Emit End of Expression Label
|
||||
}
|
||||
|
||||
|
||||
/* Process Assignment */
|
||||
void prcasn(char trmntr)
|
||||
{
|
||||
DEBUG("Processing assignment of variable '%s'\n", asnvar);
|
||||
expect('=');
|
||||
if (look('(')) { //Parse Shortcut If
|
||||
newlbl(cndlbl); //Create Label for "if FALSE" expression
|
||||
prscnd(')', FALSE); //Parse Condition
|
||||
expect('?');
|
||||
prsxpr(':'); //Parse "if TRUE" expression
|
||||
newlbl(tmplbl); //Create End of Expression Label
|
||||
asmlin("JMP", tmplbl); //Jump over "if FALSE" expression
|
||||
setlbl(cndlbl); //Emit "if FALSE" label
|
||||
prsxpr(trmntr); //Parse "if FALSE" expression
|
||||
setlbl(tmplbl); //Emit End of Expression Label
|
||||
}
|
||||
else
|
||||
prsxpr(trmntr);
|
||||
if (strlen(asnidx)) {
|
||||
asmlin("LDX", asnidx);
|
||||
strcat(asnvar,",X");
|
||||
}
|
||||
asmlin("STA", asnvar);
|
||||
}
|
||||
|
||||
void prcpop() {
|
||||
DEBUG("Processing post operation '%c'\n", oper);
|
||||
switch(oper)
|
||||
{
|
||||
case '+':
|
||||
asmlin("INC", asnvar);
|
||||
break;
|
||||
case '-':
|
||||
asmlin("DEC", asnvar);
|
||||
break;
|
||||
case '<':
|
||||
asmlin("ASL", asnvar);
|
||||
break;
|
||||
case '>':
|
||||
asmlin("LSR", asnvar);
|
||||
break;
|
||||
default:
|
||||
printf("Unrecognized post operator '%c'\n", oper);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Post Operator */
|
||||
void prspop(char trmntr) {
|
||||
oper = getnxt();
|
||||
CCMNT(oper); CCMNT(oper);
|
||||
DEBUG("Checking for post operation '%c'\n", oper);
|
||||
if (nxtchr == oper) {
|
||||
skpchr();
|
||||
prcpop(); //Process Post-Op
|
||||
if (strlen(asnvar) == 1 && strchr("XY", asnvar[0])) {
|
||||
DEBUG("Processing assignment of register '%s'\n", asnvar);
|
||||
prsval(TRUE); //Get value to assign
|
||||
expect(trmntr);
|
||||
if (strlen(value) == 1 && strchr("XY", value[0])) {
|
||||
ERROR("Illegal Reference to Register %s\n", value, EXIT_FAILURE);
|
||||
}
|
||||
if (asnvar[0] == 'X') {
|
||||
if (strcmp(value, "A") == 0)
|
||||
asmlin("TAX", "");
|
||||
else
|
||||
asmlin("LDX", value);
|
||||
}
|
||||
else {
|
||||
if (strcmp(value, "A") == 0)
|
||||
asmlin("TAY", "");
|
||||
else
|
||||
asmlin("LDY", value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
DEBUG("Processing assignment of variable '%s'\n", asnvar);
|
||||
if (look('('))
|
||||
prssif(trmntr); //Parse Shortcut If
|
||||
else
|
||||
expctd("post operator");
|
||||
prsxpr(trmntr); //Parse Expression
|
||||
/* if (strcmp(asnvar, "X")==0)
|
||||
asmlin("TAX", "");
|
||||
else if (strcmp(asnvar, "Y")==0)
|
||||
asmlin("TAY", "");
|
||||
else */
|
||||
if ((strcmp(asnvar, "A")!=0))
|
||||
{
|
||||
if (strlen(asnidx)) {
|
||||
if (asnivt == CONSTANT) {
|
||||
strcat(asnvar, "+");
|
||||
strcat(asnvar, asnidx);
|
||||
}
|
||||
else {
|
||||
asmlin("LDX", asnidx);
|
||||
strcat(asnvar,",X");
|
||||
}
|
||||
}
|
||||
asmlin("STA", asnvar);
|
||||
}
|
||||
}
|
||||
|
||||
void poperr()
|
||||
{
|
||||
printf("Illegal post-operation %c%c on register %s\n", oper, oper, asnvar);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Process Variable at Beginning of Statement */
|
||||
void prcvar(char trmntr)
|
||||
{
|
||||
chksym(word);
|
||||
chksym(TRUE, word);
|
||||
strcpy(asnvar, word); //sav variable to assign to
|
||||
if (valtyp == VARIABLE && look(';')) {
|
||||
asmlin("STA", asnvar);
|
||||
return;
|
||||
}
|
||||
if (valtyp == ARRAY) {
|
||||
prsidx(); //Parse Array Index
|
||||
asnivt = valtyp;
|
||||
strncpy(asnidx, value, VARLEN);
|
||||
}
|
||||
else
|
||||
asnidx[0] = 0;
|
||||
if (ispopr(nxtchr))
|
||||
prspop(trmntr); //Parse Post Operator
|
||||
if (ispopr()) {
|
||||
if (prspst(trmntr, asnvar)) //Parse Post Operator
|
||||
expctd("post operator");
|
||||
}
|
||||
else
|
||||
prcasn(trmntr);
|
||||
}
|
||||
@ -107,6 +124,31 @@ void bgnblk(int blkflg)
|
||||
setblk(inblck);
|
||||
}
|
||||
|
||||
/* Parse 'asm' String Parameter */
|
||||
void pasmst(char trmntr)
|
||||
{
|
||||
skpspc(); //Skip Spaces
|
||||
if (!match('"'))
|
||||
expctd("string");
|
||||
getstr();
|
||||
skpspc();
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
/* Parse and Compile 'asm' statement */
|
||||
void pasm()
|
||||
{
|
||||
char opcode[LINELEN];
|
||||
expect('(');
|
||||
pasmst(',');
|
||||
if (strlen(word)) setlbl(word);
|
||||
pasmst(',');
|
||||
strcpy(opcode, word);
|
||||
pasmst(')');
|
||||
expect(';');
|
||||
asmlin(opcode, word);
|
||||
}
|
||||
|
||||
/* Parse and Compile and Assignment */
|
||||
void prsasn(char trmntr)
|
||||
{
|
||||
@ -116,9 +158,10 @@ void prsasn(char trmntr)
|
||||
}
|
||||
|
||||
/* parse and compile 'break'/'continue' statement */
|
||||
void pbrcnt(int lbtype) {
|
||||
void pbrcnt(int lbtyp1, int lbtyp2)
|
||||
{
|
||||
DEBUG("Parsing BREAK/CONTINUE statement\n", 0);
|
||||
if (lstlbl(lbtype) < 0)
|
||||
if (lstlbl(lbtyp1, lbtyp2) < 0)
|
||||
ERROR("Break/continue statement outside of loop\n", 0, EXIT_FAILURE);
|
||||
DEBUG("Found Label '%s'\n", tmplbl);
|
||||
asmlin("JMP", tmplbl);
|
||||
@ -126,11 +169,15 @@ void pbrcnt(int lbtype) {
|
||||
}
|
||||
|
||||
/* parse and compile 'do' statement */
|
||||
void pdo() {
|
||||
void pdo()
|
||||
{
|
||||
DEBUG("Parsing DO statement '%c'\n", nxtchr);
|
||||
newlbl(loplbl); //Create Do Loop Label
|
||||
newlbl(endlbl); //Create End Label
|
||||
pshlbl(LTDWHL, endlbl); //and Push onto Stack
|
||||
reqlbl(loplbl); //Get or Create/Set Loop Label
|
||||
//newlbl(loplbl); //Create Do Loop Label
|
||||
//setlbl(loplbl); //Set Label to Emit on Next Line
|
||||
pshlbl(LTDO, loplbl); //Push onto Stack
|
||||
setlbl(loplbl); //Set Label to Emit on Next Line
|
||||
bgnblk(FALSE); //Check For and Begin Block
|
||||
}
|
||||
|
||||
@ -139,14 +186,17 @@ void pdowhl() {
|
||||
DEBUG("Parsing WHILE after DO '%c'\n", nxtchr);
|
||||
getwrd(); //Check for While
|
||||
ACMNT(word);
|
||||
if (!wordis("while"))
|
||||
if (!wordis("WHILE"))
|
||||
expctd("while statement");
|
||||
expect('(');
|
||||
newlbl(cndlbl); //Create Skip Label
|
||||
prscnd(')', FALSE); //Parse Conditional Expession
|
||||
asmlin("JMP", loplbl); //Emit Jump to Beginning of Loop
|
||||
setlbl(cndlbl); //and Set Label to Emit on Next Line
|
||||
expect(';'); //Check for End of Statement
|
||||
//poplbl(); //Pop While Conditional Label
|
||||
strcpy(cndlbl, loplbl); //Set Conditional Label to Loop Label
|
||||
prscnd(')', TRUE); //Parse Conditional Expession
|
||||
//asmlin("JMP", loplbl); //Emit Jump to Beginning of Loop
|
||||
//setlbl(cndlbl); //and Set Label to Emit on Next Line
|
||||
poplbl(); //Pop While Conditional Label
|
||||
setlbl(endlbl); //and Set Label to Emit on Next Line
|
||||
expect(';'); //Check for End of Statement
|
||||
}
|
||||
|
||||
|
||||
@ -198,8 +248,72 @@ void pgoto() {
|
||||
DEBUG("Parsing GOTO statement\n", 0);
|
||||
getwrd();
|
||||
ACMNT(word);
|
||||
asmlin("JMP", word);
|
||||
expect(';');
|
||||
asmlin("JMP", word);
|
||||
}
|
||||
|
||||
/* parse and compile inline statement */
|
||||
void pinlne()
|
||||
{
|
||||
DEBUG("Parsing INLINE statement\n", 0);
|
||||
do {
|
||||
DEBUG("Parsing inline parameter\n", 0);
|
||||
if (look('&')) {
|
||||
reqvar(FALSE); //Get Variable Name
|
||||
strcpy(word, "<");
|
||||
strcat(word, value);
|
||||
strcat(word, ", >");
|
||||
strcat(word, value);
|
||||
asmlin(BYTEOP, word);
|
||||
}
|
||||
else if (look('"')) {
|
||||
value[0] = 0;
|
||||
while (!match('"')) {
|
||||
CCMNT(nxtchr);
|
||||
sprintf(word, "$%hhX,", getnxt());
|
||||
strcat(value, word);
|
||||
}
|
||||
strcat(value,"0");
|
||||
CCMNT(nxtchr);
|
||||
skpchr(); //Skip Terminating Quote
|
||||
asmlin(BYTEOP, value);
|
||||
}
|
||||
else {
|
||||
prscon(0xFF);
|
||||
sprintf(word, "$%hhX", cnstnt); //not needed?
|
||||
asmlin(BYTEOP, value);
|
||||
}
|
||||
} while (look(','));
|
||||
expect(';');
|
||||
}
|
||||
|
||||
/* parse and compile pop statement */
|
||||
void ppop()
|
||||
{
|
||||
DEBUG("Parsing POP statement\n", 0);
|
||||
do {
|
||||
asmlin("PLA", ""); //Pop Value off Stack
|
||||
if (!look('*')) {
|
||||
reqvar(TRUE);
|
||||
strcpy(term, value);
|
||||
chkidx();
|
||||
asmlin("STA", term);
|
||||
}
|
||||
} while (look(','));
|
||||
expect(';');
|
||||
}
|
||||
|
||||
/* parse and compile push statement */
|
||||
void ppush()
|
||||
{
|
||||
DEBUG("Parsing PUSH statement\n", 0);
|
||||
do {
|
||||
if (!chkadr(1)) {
|
||||
prsxpr(0); //Parse Expression
|
||||
asmlin("PHA",""); //Push Result on Stack
|
||||
}
|
||||
} while (look(','));
|
||||
expect(';');
|
||||
}
|
||||
|
||||
/* parse and compile return statement */
|
||||
@ -211,50 +325,22 @@ void pretrn() {
|
||||
lsrtrn = TRUE; //Set RETURN flag
|
||||
}
|
||||
|
||||
/* parse and compile switch statement */
|
||||
void pswtch() {
|
||||
DEBUG("Parsing SWITCH statement\n", 0);
|
||||
expect('(');
|
||||
prsxpr(')');
|
||||
newlbl(endlbl);
|
||||
pshlbl(LTEND, endlbl);
|
||||
bgnblk(TRUE);
|
||||
strcpy(xstmnt,"case");
|
||||
}
|
||||
|
||||
/* parse and compile case statement */
|
||||
void pcase() {
|
||||
DEBUG("Parsing CASE statement\n", 0);
|
||||
prscon(0xff); //Parse Constant
|
||||
asmlin("CMP", value);
|
||||
newlbl(skplbl);
|
||||
pshlbl(LTCASE, skplbl);
|
||||
asmlin("BNE", skplbl);
|
||||
expect(':');
|
||||
}
|
||||
|
||||
void pdeflt() {
|
||||
DEBUG("Parsing DEFAULT statement\n", 0);
|
||||
expect(':');
|
||||
if (poplbl() != LTCASE)
|
||||
ERROR("Encountered default without case\n", 0, EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* parse and compile while statement */
|
||||
void pwhile() {
|
||||
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
|
||||
expect('(');
|
||||
newlbl(endlbl); //Create End Label
|
||||
pshlbl(LTEND, endlbl); //and Push onto Stack
|
||||
newlbl(loplbl); //create Loop Label
|
||||
setlbl(loplbl); //Set to Emit on Next Line
|
||||
reqlbl(loplbl); //Get or Create/Set Loop Label
|
||||
//newlbl(loplbl); //create Loop Label
|
||||
//setlbl(loplbl); //Set to Emit on Next Line
|
||||
pshlbl(LTLOOP, loplbl); //Push onto Stack
|
||||
newlbl(cndlbl); //Create Conditional Skip Label
|
||||
prscnd(')', TRUE); //Parse Conditional Expession
|
||||
asmlin("JMP", endlbl); //Emit Jump to End of Loop
|
||||
setlbl(cndlbl); //and Set Label to Emit on Next Line
|
||||
if (!look(')')) {
|
||||
newlbl(cndlbl); //Create Conditional Skip Label
|
||||
prscnd(')', TRUE); //Parse Conditional Expession
|
||||
asmlin("JMP", endlbl); //Emit Jump to End of Loop
|
||||
setlbl(cndlbl); //and Set Label to Emit on Next Line
|
||||
}
|
||||
bgnblk(FALSE); //Check For and Begin Block
|
||||
}
|
||||
|
||||
@ -263,13 +349,11 @@ void punimp() {
|
||||
ERROR("Unimplemented statement '%s' encountered\n", word, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/* Parse Function Call as Statement */
|
||||
void prsfns()
|
||||
{
|
||||
strcpy(term, word); //Copy Function Name
|
||||
prsfnc(); //Parse Function Call
|
||||
expect(';');
|
||||
prsfnc(';'); //Parse Function Call
|
||||
return;
|
||||
}
|
||||
|
||||
@ -295,8 +379,6 @@ void endblk(int blkflg)
|
||||
if (inblck != blkflg)
|
||||
ERROR("Encountered '}' without matching '{'\n", 0, EXIT_FAILURE);
|
||||
lbtype = poplbl();
|
||||
if (lbtype == LTCASE)
|
||||
ERROR("Ended switch without default\n", 0, EXIT_FAILURE);
|
||||
if (lbtype == LTDO)
|
||||
pdowhl(); //Parse While at End of Do Loop
|
||||
}
|
||||
@ -305,35 +387,35 @@ void endblk(int blkflg)
|
||||
void pstmnt()
|
||||
{
|
||||
DEBUG("Parsing statement '%s'\n", word);
|
||||
if (wordis("do")) {
|
||||
if (wordis("DO")) {
|
||||
pdo();
|
||||
return;
|
||||
}
|
||||
if (wordis("else")) {
|
||||
if (wordis("ELSE")) {
|
||||
pelse();
|
||||
return;
|
||||
}
|
||||
if (wordis("for")) {
|
||||
if (wordis("FOR")) {
|
||||
pfor();
|
||||
return;
|
||||
}
|
||||
if (wordis("if")) {
|
||||
if (wordis("IF")) {
|
||||
pif();
|
||||
return;
|
||||
}
|
||||
if (wordis("switch")) {
|
||||
if (wordis("SWITCH")) {
|
||||
punimp();
|
||||
return;
|
||||
}
|
||||
if (wordis("case")) {
|
||||
if (wordis("CASE")) {
|
||||
punimp();
|
||||
return;
|
||||
}
|
||||
if (wordis("default")) {
|
||||
if (wordis("DEFAULT")) {
|
||||
punimp();
|
||||
return;
|
||||
}
|
||||
if (wordis("while")) {
|
||||
if (wordis("WHILE")) {
|
||||
pwhile();
|
||||
return;
|
||||
}
|
||||
@ -341,13 +423,21 @@ void pstmnt()
|
||||
prslbl(); //Parse Label
|
||||
return;
|
||||
}
|
||||
if (wordis("break"))
|
||||
pbrcnt(LTEND);
|
||||
else if (wordis("continue"))
|
||||
pbrcnt(LTLOOP);
|
||||
else if (wordis("goto"))
|
||||
if (wordis("ASM"))
|
||||
pasm();
|
||||
else if (wordis("BREAK"))
|
||||
pbrcnt(LTEND, LTDWHL);
|
||||
else if (wordis("CONTINUE"))
|
||||
pbrcnt(LTLOOP, LTDO);
|
||||
else if (wordis("GOTO"))
|
||||
pgoto();
|
||||
else if (wordis("return"))
|
||||
else if (wordis("INLINE"))
|
||||
pinlne();
|
||||
else if (wordis("POP"))
|
||||
ppop();
|
||||
else if (wordis("PUSH"))
|
||||
ppush();
|
||||
else if (wordis("RETURN"))
|
||||
pretrn();
|
||||
else
|
||||
prssym();
|
||||
|
1
stmnt.h
1
stmnt.h
@ -4,6 +4,7 @@
|
||||
|
||||
char asnvar[VARLEN+1]; //Assigned Variable Name
|
||||
char asnidx[VARLEN+1] ; //Assigned Variable Index
|
||||
int asnivt; //Assigned Index Variable Type
|
||||
|
||||
char xstmnt[LINELEN]; //Required Statement
|
||||
|
||||
|
125
vars.c
125
vars.c
@ -18,7 +18,7 @@
|
||||
/* Lookup variable name in variable table *
|
||||
* Returns index into varnam array *
|
||||
* FALSE if variable was not found */
|
||||
int lookup(char *name)
|
||||
int fndvar(char *name)
|
||||
{
|
||||
int i;
|
||||
DEBUG("Looking up variable '%s'\n", word);
|
||||
@ -32,28 +32,36 @@ int lookup(char *name)
|
||||
/* Check if variable has been defined */
|
||||
int symdef(char *name)
|
||||
{
|
||||
if (lookup(name) < 0)
|
||||
return FALSE;
|
||||
else
|
||||
if (fndvar(name) > -1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check for variable *
|
||||
* Generates error if variable is undefined */
|
||||
void chksym(char *name)
|
||||
* Generates error if variable is undefined *
|
||||
* Args: alwreg - allow register name *
|
||||
* name - variable name */
|
||||
void chksym(int alwreg, char *name)
|
||||
{
|
||||
if (strlen(name) == 1 && strchr("AXY", name[0])) {
|
||||
if (alwreg) return;
|
||||
else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE);
|
||||
}
|
||||
if (!symdef(name))
|
||||
ERROR("Undeclared variable '%s' encountered\n", word, EXIT_FAILURE);
|
||||
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/* Parse Variable Name *
|
||||
* Generates error if not a simple variable */
|
||||
void reqvar()
|
||||
/* Parse Variable Name *
|
||||
* Parameters: alwary - Allow Array Reference *
|
||||
* Sets: vrname - operand for LDA/STA/LDY/STY */
|
||||
void reqvar(int alwary)
|
||||
{
|
||||
prsvar();
|
||||
if (valtyp != VARIABLE)
|
||||
expctd("Variable");
|
||||
prsvar(FALSE);
|
||||
if (!alwary)
|
||||
if (valtyp != VARIABLE)
|
||||
expctd("Variable");
|
||||
}
|
||||
|
||||
/* Check for Array specifier and get size *
|
||||
@ -67,7 +75,7 @@ void pvarsz()
|
||||
skpchr();
|
||||
if (alcvar) {
|
||||
DEBUG("Parsing array size\n", 0);
|
||||
prsnum(0xFF);
|
||||
sprintf(value, "%d", prsnum(0xFF) + 1);
|
||||
}
|
||||
expect(']');
|
||||
}
|
||||
@ -79,7 +87,22 @@ void pvarsz()
|
||||
void prsdtc()
|
||||
{
|
||||
dtype = DTBYTE;
|
||||
prscon(0xff);
|
||||
prscon();
|
||||
}
|
||||
|
||||
/* Parse Data Array */
|
||||
void prsdta()
|
||||
{
|
||||
dtype = DTARRY;
|
||||
expect('{');
|
||||
dlen = 0;
|
||||
while (TRUE) {
|
||||
prscon();
|
||||
dattmp[dlen++] = cnstnt;
|
||||
if (!look(','))
|
||||
break;
|
||||
}
|
||||
expect('}');
|
||||
}
|
||||
|
||||
/* Parse Data String */
|
||||
@ -103,6 +126,11 @@ void setdat()
|
||||
dlen = 1;
|
||||
datvar[dsize++] = cnstnt;
|
||||
}
|
||||
else if (dtype == DTARRY) {
|
||||
DEBUG("Setting variable data to array of length %d\n", dlen);
|
||||
for (i=0; i<dlen; i++)
|
||||
datvar[dsize++] = dattmp[i];
|
||||
}
|
||||
else {
|
||||
DEBUG("Setting variable data to '%s'\n", value);
|
||||
dlen = strlen(value);
|
||||
@ -122,10 +150,12 @@ void prsdat()
|
||||
return;
|
||||
}
|
||||
skpspc();
|
||||
if (isnpre())
|
||||
prsdtc(0xff); //Parse Data Constant
|
||||
if (iscpre())
|
||||
prsdtc(); //Parse Data Constant
|
||||
else if (match('"'))
|
||||
prsdts(); //Parse Data String
|
||||
else if (match('{'))
|
||||
prsdta(); //Parse Data Array
|
||||
else
|
||||
expctd("numeric or string constant");
|
||||
setdat(); //Store Data Value
|
||||
@ -145,35 +175,45 @@ void setvar(int t)
|
||||
|
||||
/* Parse and Compile Variable Declaration *
|
||||
* Uses: word - variable name */
|
||||
void addvar(int t)
|
||||
void addvar(int m, int t)
|
||||
{
|
||||
strcpy(vrname, word); //Save Variable Name
|
||||
if (symdef(vrname))
|
||||
ERROR("Duplicate declaration of variable '%s\n", word,EXIT_FAILURE);
|
||||
if (t == VTVOID)
|
||||
ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
|
||||
pvarsz(); //Check for Array Declaration and Get Size
|
||||
if (m == MTZP) {
|
||||
setlbl(vrname);
|
||||
sprintf(word, "$%hhX", zpaddr++);
|
||||
asmlin(EQUOP, word);
|
||||
strcpy(value, "*"); //Set Variable Type to Zero Page
|
||||
}
|
||||
else
|
||||
pvarsz(); //Check for Array Declaration and Get Size
|
||||
setvar(t); //Add to Variable Table
|
||||
prsdat(); //Parse Variable Data
|
||||
if (m != MTZP)
|
||||
prsdat(); //Parse Variable Data
|
||||
varcnt++; //Increment Variable Counter
|
||||
}
|
||||
|
||||
/* Add Function Definition */
|
||||
void addfnc()
|
||||
{
|
||||
ACMNT(word);
|
||||
expect('(');
|
||||
strcpy(fncnam, word); //Save Function Name
|
||||
prmcnt = 0; //Set Number of Parameters
|
||||
skpspc(); //Skip Spaces
|
||||
if (isalph()) { //Parse Parameters
|
||||
reqvar(); //Get First Parameter
|
||||
reqvar(FALSE); //Get First Parameter
|
||||
strcpy(prmtra, value);
|
||||
prmcnt++;
|
||||
if (look(',')) {
|
||||
reqvar(); //Get Second Parameter
|
||||
reqvar(FALSE); //Get Second Parameter
|
||||
strcpy(prmtry, value);
|
||||
prmcnt++;
|
||||
if (look(',')) {
|
||||
reqvar(); //Third Parameter
|
||||
reqvar(FALSE); //Third Parameter
|
||||
strcpy(prmtrx, value);
|
||||
prmcnt++;
|
||||
}
|
||||
@ -195,22 +235,52 @@ void addfnc()
|
||||
}
|
||||
|
||||
/* (Check For and) Parse Variable Declaration*/
|
||||
void pdecl(int t)
|
||||
void pdecl(int m, int t)
|
||||
{
|
||||
DEBUG("Processing variable declarations(s) of type %d\n", t);
|
||||
while(TRUE) {
|
||||
getwrd();
|
||||
if (look('(')) {
|
||||
if (match('(')) {
|
||||
if (m != MTNONE) {
|
||||
ERROR("Illegal Modifier %d in Function Definion", m, EXIT_FAILURE);
|
||||
}
|
||||
addfnc(); //Add Function Call
|
||||
return;
|
||||
}
|
||||
addvar(t);
|
||||
addvar(m, t);
|
||||
if (!look(','))
|
||||
break;
|
||||
}
|
||||
expect(';');
|
||||
}
|
||||
|
||||
/* Check for and Parse Type Keyword */
|
||||
int ptype(int m)
|
||||
{
|
||||
int result = TRUE;
|
||||
if (wordis("VOID"))
|
||||
pdecl(m, VTVOID); //Parse 'void' declaration
|
||||
else if (wordis("CHAR"))
|
||||
pdecl(m, VTCHAR); //Parse 'char' declaration
|
||||
else
|
||||
result = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Check for and Parse Modifier */
|
||||
int pmodfr()
|
||||
{
|
||||
DEBUG("Parsing modifier '%s'\n", word);
|
||||
int result = TRUE;
|
||||
if (wordis("ZEROPAGE")) {
|
||||
getwrd();
|
||||
ptype(MTZP);
|
||||
}
|
||||
else
|
||||
result = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Write Variable Data */
|
||||
void vardat(int i)
|
||||
{
|
||||
@ -238,7 +308,7 @@ void vartbl()
|
||||
DEBUG("Set Label to '%s'\n", lblasm);
|
||||
if (strcmp(varsiz[i], "*") == 0)
|
||||
continue;
|
||||
else if (datlen[i])
|
||||
if (datlen[i])
|
||||
vardat(i); //Write Variable Data
|
||||
else if (strlen(varsiz[i]) > 0) {
|
||||
DEBUG("Allocating array '%s'\n", varnam[i]);
|
||||
@ -249,6 +319,7 @@ void vartbl()
|
||||
asmlin(BYTEOP, "0");
|
||||
}
|
||||
}
|
||||
vrwrtn = TRUE;
|
||||
}
|
||||
|
||||
/* Print Variable Table to Log File */
|
||||
|
11
vars.h
11
vars.h
@ -8,6 +8,7 @@ char vartyp[MAXVAR+1]; //Variable Type
|
||||
char varsiz[MAXVAR+1][4]; //Variable Array
|
||||
int varcnt; //Number of Variables in Table
|
||||
char vrname[MAXVAR+1]; //Variable Name
|
||||
int vrwrtn; //Variables Written Flag
|
||||
|
||||
/*
|
||||
int varidx; //Index into Variable Table
|
||||
@ -18,13 +19,17 @@ enum vtypes {VTVOID, VTCHAR}; //Variable Types
|
||||
char datvar[DATASPC+1]; //Variable Data Storage
|
||||
char datlen[MAXVAR+1]; //Variable Data Length
|
||||
char dattyp[MAXVAR+1]; //Variable Data Type
|
||||
char dattmp[256]; //Variable Temporary Data
|
||||
int dtype; //Data Type
|
||||
int dlen; //Length of Variable Data
|
||||
int dsize; //Total Data Length
|
||||
|
||||
enum dtypes {DTBYTE, DTSTR}; //Variable Data Types
|
||||
enum dtypes {DTBYTE, DTSTR, DTARRY}; //Variable Data Types
|
||||
|
||||
enum mtypes {MTNONE, MTZP}; //Variable Modifier Types
|
||||
|
||||
int symdef(char *name); //Is Variable defined (TRUE or FALSE)
|
||||
int zpaddr; //Current Zero-Page Address
|
||||
|
||||
char fncnam[VARLEN+1]; //Function Name
|
||||
char prmtra[VARLEN+1]; //Function Parameter A
|
||||
@ -32,11 +37,11 @@ char prmtrx[VARLEN+1]; //Function Parameter X
|
||||
char prmtry[VARLEN+1]; //Function Parameter Y
|
||||
int prmcnt; //Number of Parameters
|
||||
|
||||
void chksym(char *name); //Error if Variable not defined
|
||||
void chksym(int alwreg, char *name); //Error if Variable not defined
|
||||
void prsdts(); //Parse Data String
|
||||
void setdat(); //Set Variable Data
|
||||
void setvar(int t); //Set Variable Name and Size
|
||||
void pdecl(int t); //Parse Variable Declaration
|
||||
void pdecl(int m, int t); //Parse Variable Declaration
|
||||
|
||||
void vartbl(); //Create Variable Table
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user