Files
zSoft/apps/tbasic/basic_expr.c

233 lines
5.6 KiB
C

#include "mystdlib.h"
#include "basic_tokens.h"
#include "basic_tokenint.h"
#include "basic_expr.h"
char parseExprUnary() {
char c = *getCurTokPos();
if (c != '-' && c != '!') {
return 0;
}
parseSymbol();
if (prevTok->body.symbol == '-') {
prevTok->body.symbol = '~';
}
return 1;
}
char parseExprVal(void) {
if (parseNumber()) {
if (*getCurTokPos() == '(') {
setTokenError(getCurTokPos(), 9);
return 'e';
}
return '+';
}
if (parseName(0)) {
if (*getCurTokPos() == '(') {
prevTok->type = TT_FUNCTION;
skipTokenInInput(1);
return 'f';
}
prevTok->type = TT_VARIABLE;
return '+';
}
if (*getCurTokPos() == '(') {
parseSymbol();
return '(';
}
if (parseExprUnary()) {
return '1';
}
setTokenError(getCurTokPos(), 9);
return 'e';
}
char parseExprBop(void) {
char c = *getCurTokPos();
if (c == 0 || c == ';') {
return 's';
}
if (c == ')') {
return ')';
}
if (c == ',') {
return ',';
}
if (c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%'
|| c == '<' || c == '>' || c == '=' || c == '&' || c == '|') {
parseSymbol();
return '1';
}
setTokenError(getCurTokPos(), 9);
return 'e';
}
char parseExprRbr(char brCount, char argCount) {
if (brCount < 1) {
setTokenError(getCurTokPos(), 9);
return 'e';
} else {
parseSymbol();
if (argCount > 0) {
prevTok->type = TT_FUNC_END;
prevTok->body.symbol = argCount;
}
return '+';
}
}
char parseExprComma(char inFunc) {
if (inFunc == 0) {
setTokenError(getCurTokPos(), 9);
return 'e';
} else {
parseSymbol();
return '1';
}
}
schar operatorPriority(char op) {
switch (op) {
case '&':
case '|':
return 5;
case '<':
case '>':
case '=':
case '#':
case '{':
case '}':
return 10;
case '+':
case '-':
return 15;
case '*':
case '/':
case '%':
return 20;
case '!':
case '~':
return 25;
case '(':
return 0;
}
return -1;
}
char isUnary(char op) {
return op == '!' || op == '~';
}
char convertRpnPop(char op) {
if (op == '(') {
return 0;
}
curTok->type = TT_SYMBOL;
curTok->body.symbol = op;
curTok = nextToken(curTok);
return 1;
}
void shuntingYard(token* next) {
char opstack[16];
schar sp = -1;
char prio;
char op;
char* start = (char*)(void*)next;
while (next->type != TT_ERROR) {
if (next->type == TT_VARIABLE || next->type == TT_NUMBER) {
copyToken(curTok, next);
curTok = nextToken(curTok);
} else if (next->type == TT_SYMBOL) {
op = next->body.symbol;
if (op == '(') {
opstack[++sp] = '(';
} else if (op == ')' || op == ',') {
while (convertRpnPop(opstack[sp--]));
if (op == ',') {
sp++;
}
} else {
prio = operatorPriority(op);
if (isUnary(op)) {
prio += 1;
}
while (sp >= 0 && operatorPriority(opstack[sp]) >= prio) {
convertRpnPop(opstack[sp--]);
}
opstack[++sp] = op;
}
} else if (next->type == TT_FUNCTION) {
opstack[++sp] = (char)(((char*)(void*)next) - start);
opstack[++sp] = '(';
} else if (next->type == TT_FUNC_END) {
while (convertRpnPop(opstack[sp--]));
copyToken(curTok, (token*)(void*)(start + opstack[sp--]));
if (curTok->body.str.len == 1) {
curTok->type = TT_ARRAY;
curTok->body.symbol = curTok->body.str.text[0];
}
curTok = nextToken(curTok);
}
next = nextToken(next);
}
while (sp >= 0) {
convertRpnPop(opstack[sp--]);
}
}
void convertToRpn(token* next) {
char buf[MAX_LINE_LEN * 2];
curTok->type = TT_ERROR;
memcpy(buf, next, ((char*)(void*)curTok) - ((char*)(void*)next) + 1);
curTok = next;
next = (token*)(void*) buf;
shuntingYard(next);
curTok->type = TT_ERROR;
prevTok = NULL;
}
char parseExpression(void) {
token* startTok = curTok;
char funcBrackets[16];
unsigned char iFuncBr = 0;
char state = '1';
funcBrackets[iFuncBr] = 0;
if (*getCurTokPos() == 0) {
setTokenError(getCurTokPos(), 10);
return 0;
}
while (state != 's') {
switch (state) {
case '1':
state = parseExprVal();
break;
case 'f':
funcBrackets[++iFuncBr] = 1;
state = '1';
break;
case '(':
funcBrackets[++iFuncBr] = 0;
state = '1';
break;
case '+':
state = parseExprBop();
break;
case ')':
state = parseExprRbr(iFuncBr, funcBrackets[iFuncBr]);
iFuncBr -= 1;
break;
case ',':
state = parseExprComma(funcBrackets[iFuncBr]++);
break;
case 'e':
return 0;
}
}
convertToRpn(startTok);
return 1;
}