First push after merge, split and enhance both zOS and zputa
This commit is contained in:
232
apps/tbasic/basic_expr.c
Normal file
232
apps/tbasic/basic_expr.c
Normal file
@@ -0,0 +1,232 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user