233 lines
5.6 KiB
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;
|
|
}
|
|
|
|
|