2017-04-22 18:39:52 +00:00
|
|
|
/***********************************
|
|
|
|
* C02 Expression Parsing Routines *
|
|
|
|
***********************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "common.h"
|
|
|
|
#include "asm.h"
|
|
|
|
#include "parse.h"
|
|
|
|
#include "vars.h"
|
2017-05-01 01:17:50 +00:00
|
|
|
#include "label.h"
|
2017-04-22 18:39:52 +00:00
|
|
|
#include "expr.h"
|
|
|
|
|
|
|
|
/* Parse value (constant or identifier) *
|
|
|
|
* Sets: value - the value (as a string) *
|
|
|
|
* valtyp - value type */
|
2017-06-27 00:16:23 +00:00
|
|
|
void prsval(int alwreg)
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
|
|
|
DEBUG("Parsing value\n", 0);
|
2017-06-27 00:16:23 +00:00
|
|
|
skpspc();
|
2017-04-22 18:39:52 +00:00
|
|
|
if (iscpre())
|
2017-06-27 00:16:23 +00:00
|
|
|
prscon(); //Parse Constant
|
2017-05-01 01:17:50 +00:00
|
|
|
else if (isalph()) {
|
2017-06-27 00:16:23 +00:00
|
|
|
prsvar(alwreg); //Parse Variable
|
2017-05-01 01:17:50 +00:00
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
else
|
|
|
|
expctd("constant or variable");
|
2017-06-27 00:16:23 +00:00
|
|
|
DEBUG("Parsed value of type %d\n", valtyp);
|
2017-04-22 18:39:52 +00:00
|
|
|
skpspc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse array index *
|
|
|
|
* Sets: value - array index or *
|
|
|
|
* "" if no index defined */
|
|
|
|
void prsidx()
|
|
|
|
{
|
|
|
|
expect('[');
|
2017-06-27 00:16:23 +00:00
|
|
|
prsval(TRUE);
|
2017-04-22 18:39:52 +00:00
|
|
|
DEBUG("Parsed array index '%s'\n", value);
|
|
|
|
expect(']');
|
|
|
|
}
|
|
|
|
|
2017-06-27 00:16:23 +00:00
|
|
|
/* 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, "+");
|
2018-01-28 18:27:33 +00:00
|
|
|
strcat(term, word);
|
2017-06-27 00:16:23 +00:00
|
|
|
}
|
|
|
|
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) */
|
2017-04-22 18:39:52 +00:00
|
|
|
void prstrm()
|
|
|
|
{
|
|
|
|
DEBUG("Parsing term\n", 0);
|
2017-06-27 00:16:23 +00:00
|
|
|
prsval(FALSE);
|
2017-04-22 18:39:52 +00:00
|
|
|
if (valtyp == FUNCTION) {
|
|
|
|
ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
strcpy(term, value);
|
|
|
|
DEBUG("Parsed term %s\n", term);
|
2017-06-27 00:16:23 +00:00
|
|
|
chkidx(); //Check for Array Index
|
|
|
|
//chkpst = ispopr(); //Check for Post-Op
|
2017-04-22 18:39:52 +00:00
|
|
|
skpspc();
|
|
|
|
}
|
|
|
|
|
2017-05-01 01:17:50 +00:00
|
|
|
/* Compile Address Reference */
|
2017-06-27 00:16:23 +00:00
|
|
|
void prcadr(int adract, char* symbol)
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
2017-06-27 00:16:23 +00:00
|
|
|
DEBUG("Processing address '%s'\n", word);
|
|
|
|
strcpy(word,"#>");
|
|
|
|
strcat(word,symbol);
|
|
|
|
if (adract == 1) {
|
|
|
|
asmlin("LDA", word);
|
|
|
|
asmlin("PHA", "");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
asmlin("LDY", word);
|
2017-04-22 18:39:52 +00:00
|
|
|
strcpy(word,"#<");
|
2017-05-01 01:17:50 +00:00
|
|
|
strcat(word,symbol);
|
2017-06-27 00:16:23 +00:00
|
|
|
if (adract == 1) {
|
|
|
|
asmlin("LDA", word);
|
|
|
|
asmlin("PHA", "");
|
|
|
|
}
|
|
|
|
else
|
2017-04-22 18:39:52 +00:00
|
|
|
asmlin("LDX", word);
|
2017-05-01 01:17:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse and Compile Address of Operator */
|
2017-06-27 00:16:23 +00:00
|
|
|
void prsadr(int adract)
|
2017-05-01 01:17:50 +00:00
|
|
|
{
|
2017-06-27 00:16:23 +00:00
|
|
|
DEBUG("Parsing address\n", 0);
|
|
|
|
if (isnpre())
|
|
|
|
prsnum(0xFFFF);
|
|
|
|
else
|
|
|
|
prsvar(FALSE);
|
|
|
|
prcadr(adract, value); //Compile Address Reference
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 01:17:50 +00:00
|
|
|
/* Parse and Create Anonymous String */
|
2017-06-27 00:16:23 +00:00
|
|
|
void prsstr(adract)
|
2017-05-01 01:17:50 +00:00
|
|
|
{
|
|
|
|
DEBUG("Parsing anonymous string\n", 0);
|
2017-06-27 00:16:23 +00:00
|
|
|
newlbl(vrname); //Generate Variable Name
|
|
|
|
value[0] = 0; //Use Variable Size 0
|
2018-01-28 18:27:33 +00:00
|
|
|
setvar(MTNONE, VTCHAR); //Set Variable Name, Type, and Size
|
2017-06-27 00:16:23 +00:00
|
|
|
prsdts(); //Parse Data String
|
|
|
|
setdat(); //Set Variable Data
|
|
|
|
varcnt++; //Increment Variable Counter
|
|
|
|
prcadr(adract, vrname); //Compile Address Reference
|
2017-05-01 01:17:50 +00:00
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
|
2017-06-27 00:16:23 +00:00
|
|
|
/* Check for and Process Address or String */
|
|
|
|
int chkadr(adract)
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
2017-06-27 00:16:23 +00:00
|
|
|
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;
|
2017-05-01 01:17:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse function call */
|
2017-06-27 00:16:23 +00:00
|
|
|
void prsfnc(char trmntr)
|
2017-05-01 01:17:50 +00:00
|
|
|
{
|
|
|
|
DEBUG("Processing Function Call '%s'...\n", term);
|
|
|
|
if (fnscnt >= MAXFNS)
|
|
|
|
ERROR("Maximum Function Call Depth Exceeded", 0, EXIT_FAILURE);
|
|
|
|
strcpy(fnstck[fnscnt++], term);
|
2017-04-22 18:39:52 +00:00
|
|
|
skpchr(); //skip open paren
|
|
|
|
CCMNT('(');
|
2017-06-27 00:16:23 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
expect(')');
|
2017-06-27 00:16:23 +00:00
|
|
|
expect(trmntr);
|
2017-05-01 01:17:50 +00:00
|
|
|
asmlin("JSR", fnstck[--fnscnt]);
|
2017-04-22 18:39:52 +00:00
|
|
|
skpspc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse first term of expession *
|
|
|
|
* First term can include function calls */
|
|
|
|
void prsftm()
|
|
|
|
{
|
2017-06-27 00:16:23 +00:00
|
|
|
prsval(TRUE);
|
2017-04-22 18:39:52 +00:00
|
|
|
DEBUG("Processing first term '%s'...\n", value);
|
|
|
|
strcpy(term, value);
|
2017-06-27 00:16:23 +00:00
|
|
|
if (valtyp == FUNCTION) {
|
|
|
|
prsfnc(0); //Parse Expression Function
|
2017-04-22 18:39:52 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-06-27 00:16:23 +00:00
|
|
|
if (wordis("A"))
|
|
|
|
return;
|
|
|
|
if (wordis("X"))
|
|
|
|
asmlin("TXA", "");
|
|
|
|
else if (wordis("Y"))
|
|
|
|
asmlin("TYA", "");
|
|
|
|
else {
|
|
|
|
chkidx(); //Check for Array Index
|
|
|
|
asmlin("LDA", term);
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process Arithmetic or Bitwise Operator *
|
|
|
|
* and the term that follows it */
|
|
|
|
void prcopr()
|
|
|
|
{
|
|
|
|
DEBUG("Processing operator '%c'\n", oper);
|
|
|
|
switch(oper)
|
|
|
|
{
|
|
|
|
case '+':
|
|
|
|
asmlin("CLC", "");
|
|
|
|
asmlin("ADC", term);
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
asmlin("SEC", "");
|
|
|
|
asmlin("SBC", term);
|
|
|
|
break;
|
|
|
|
case '&':
|
|
|
|
asmlin("AND", term);
|
|
|
|
break;
|
|
|
|
case '|':
|
2017-05-16 00:25:11 +00:00
|
|
|
case '!': //For systems that don't have pipe in character set
|
2017-04-22 18:39:52 +00:00
|
|
|
asmlin("ORA", term);
|
|
|
|
break;
|
2017-05-16 00:25:11 +00:00
|
|
|
case '^': //Looks like an up-arrow in some character sets
|
2017-04-22 18:39:52 +00:00
|
|
|
asmlin("EOR", term);
|
|
|
|
break;
|
|
|
|
default:
|
2018-02-09 04:21:46 +00:00
|
|
|
fprintf(stderr, "Unrecognized operator '%c'\n", oper);
|
2017-04-22 18:39:52 +00:00
|
|
|
exterr(EXIT_FAILURE);
|
|
|
|
}
|
2017-06-27 00:16:23 +00:00
|
|
|
oper = 0;
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse and compile expression */
|
|
|
|
void prsxpr(char trmntr)
|
|
|
|
{
|
|
|
|
DEBUG("Parsing expression\n", 0);
|
|
|
|
skpspc();
|
2017-05-01 01:17:50 +00:00
|
|
|
if (match('-')) {
|
|
|
|
DEBUG("Processing unary minus", 0);
|
2017-06-27 00:16:23 +00:00
|
|
|
asmlin("LDA", "#$00"); //Handle Unary Minus
|
2017-05-01 01:17:50 +00:00
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
else
|
|
|
|
prsftm(); //Parse First Term
|
2017-06-27 00:16:23 +00:00
|
|
|
skpspc();
|
2017-04-22 18:39:52 +00:00
|
|
|
while (isoper())
|
|
|
|
{
|
|
|
|
prsopr(); //Parse Operator
|
|
|
|
prstrm(); //Parse Term
|
|
|
|
prcopr(); //Process Operator
|
|
|
|
}
|
2017-06-27 00:16:23 +00:00
|
|
|
expect(trmntr);
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
|