bool isEndOfToken(const bool in_str, const string& s, size_t p) { return ( (in_str && isStringBoundary(s[p])) || (p == s.length() - 1 && (in_str && isStringBoundary(s[p]))) || (!in_str && (isParen(s[p]) || isParen(s[p+1]))) || (blank(in_str, s[p+1]))); }
ACCExpr *cleanupExpr(ACCExpr *expr, bool preserveParen) { if (!expr) return expr; static int level; level++; if (expr->operands.size() == 1 && expr->operands.front()->value != "," && (!preserveParen && expr->value == "(")) expr = expr->operands.front(); if (isParen(expr->value) && expr->operands.size() == 1 && expr->operands.front()->value == ",") expr->operands = expr->operands.front()->operands; ACCExpr *ret = allocExpr(expr->value); bool booleanCond = expr->value == "?"; for (auto item: expr->operands) { if (booleanCond) item = cleanupBool(item); ACCExpr *titem = cleanupExpr(item, isIdChar(expr->value[0])); booleanCond = false; if (titem->value != ret->value || ret->value == "?" || isParen(ret->value) || ( titem->value != "&" && titem->value != "|" && titem->value != "&&" && titem->value != "||" && titem->value != "+" && titem->value != "*")) ret->operands.push_back(titem); else { for (auto oitem: titem->operands) ret->operands.push_back(oitem); } } level--; return ret; }
std::string tree2str(ACCExpr *expr) { if (!expr) return ""; std::string ret, sep, op = expr->value; if (isParen(op)) { ret += op; if (expr->operands.size()) ret += " "; op = ","; } else if (isIdChar(op[0])) { ret += op; } else if (!expr->operands.size() || ((op == "-" || op == "!")/*unary*/ && expr->operands.size() == 1)) ret += op; bool topOp = checkOperand(expr->value) || expr->value == "," || expr->value == "[" || expr->value == PARAMETER_MARKER; for (auto item: expr->operands) { ret += sep; bool addParen = !topOp && !checkOperand(item->value) && item->value != ","; if (addParen) ret += "( "; ret += tree2str(item); if (addParen) ret += " )"; sep = " " + op + " "; if (op == "?") op = ":"; } ret += treePost(expr); return ret; }
/** * @brief Extracts paren characters from current line of input. * @param[in] s The line of input to be read. * @param[out] p The location for extracted parens to be placed. * @param[in] max The maximum size of the @a p char array. * */ void extract(char s[], char p[], int max) { int c, i; int len = strLen(s); for (i = 0; i < len; i++) { c = s[i]; evalStateAt(s, i); if ((state == code || state == include) && isParen(c)) add(p, c, max); } }
bool isStartOfToken(const bool in_str, const string& s, size_t p) { return !in_str && (isStringBoundary(s[p]) || isParen(s[p]) || (!blank(in_str, s[p]) && (p == 0 || blank(in_str, s[p-1]) || isParen(s[p-1])))); }
static ACCExpr *getExprList(ACCExpr *head, std::string terminator, bool repeatCurrentToken, bool preserveParen) { bool parseState = false; ACCExpr *currentOperand = nullptr; ACCExpr *tok; ACCExpr *exprStack[MAX_EXPR_DEPTH]; int exprStackIndex = 0; #define TOP exprStack[exprStackIndex] TOP = nullptr; if (trace_expr) printf("[%s:%d] head %s\n", __FUNCTION__, __LINE__, head ? head->value.c_str() : "(nil)"); if (head) { while ((tok = get1Token()) && tok->value != terminator) { if (trace_expr) printf("[%s:%d] parseState %d tok->value %s repeat %d\n", __FUNCTION__, __LINE__, parseState, tok->value.c_str(), repeatCurrentToken); if ((parseState = !parseState)) { /* Operand */ ACCExpr *unary = nullptr; ACCExpr *tnext = tok; if (repeatCurrentToken) tok = head; else tnext = get1Token(); repeatCurrentToken = false; if ((tok->value == "-" || tok->value == "!") && !tok->operands.size()) { // unary '-' unary = tok; tok = tnext; tnext = get1Token(); if (trace_expr) printf("[%s:%d] unary '-' unary %p tok %p tnext %p\n", __FUNCTION__, __LINE__, (void *)unary, (void *)tok, (void *)tnext); } if (!checkOperand(tok->value) && !checkOperator(tok->value)) { printf("[%s:%d] OPERAND CHECKFAILLLLLLLLLLLLLLL %s from %s\n", __FUNCTION__, __LINE__, tree2str(tok).c_str(), lexString.c_str()); exit(-1); } while (tnext && (isParen(tnext->value) || isIdChar(tnext->value[0]))) { assert(isIdChar(tok->value[0])); tok->operands.push_back(tnext); tnext = get1Token(); } repeatGet1Token = tnext; if (unary) { unary->operands.push_back(tok); tok = unary; } currentOperand = tok; } else { /* Operator */ std::string L = TOP ? TOP->value : "", R = tok->value; if (!checkOperator(R)) { printf("[%s:%d] OPERATOR CHECKFAILLLLLLLLLLLLLLL %s from %s\n", __FUNCTION__, __LINE__, R.c_str(), lexString.c_str()); exit(-1); } else if (!((L == R && L != "?") || (L == "?" && R == ":"))) { if (TOP) { int lprec = findPrec(L), rprec = findPrec(R); if (lprec < rprec) { exprStackIndex++; TOP = nullptr; } else { TOP->operands.push_back(currentOperand); currentOperand = TOP; while (exprStackIndex > 0 && lprec >= rprec) { exprStackIndex--; TOP->operands.push_back(currentOperand); currentOperand = TOP; L = TOP->value; lprec = findPrec(L); } } } TOP = tok; } TOP->operands.push_back(currentOperand); currentOperand = nullptr; } } while (exprStackIndex != 0) { TOP->operands.push_back(currentOperand); currentOperand = TOP; exprStackIndex--; } if (currentOperand) { if (TOP) TOP->operands.push_back(currentOperand); else TOP = currentOperand; } if (TOP) { if (terminator != "") head->operands.push_back(TOP); // the first item in a recursed list else head = TOP; } } head = cleanupExpr(head, preserveParen); return head; }
static bool isParen(char ch) { static char item[2]; item[0] = ch; return isParen(item); }
static ACCExpr *get1Token(void) { std::string lexToken; auto getNext = [&] (void) -> void { lexToken += lexChar; lexChar = lexString[lexIndex++]; }; ACCExpr *ret = repeatGet1Token; repeatGet1Token = nullptr; if (ret) return ret; while (lexChar == ' ' || lexChar == '\t') lexChar = lexString[lexIndex++]; if(lexIndex > lexString.length() || lexChar == 0) return nullptr; if (isIdChar(lexChar)) { do { getNext(); } while (isIdChar(lexChar) || isdigit(lexChar)); if (lexAllowRange && lexChar == '[') { do { getNext(); } while (lexChar != ']'); getNext(); } if (lexToken == "__defaultClock") lexToken = "CLK"; else if (lexToken == "__defaultnReset") lexToken = "nRST"; } else if (isdigit(lexChar)) do { getNext(); } while (isdigit(lexChar) || lexChar == '.' || lexChar == '\'' || lexChar == 'b' || lexChar == 'h' || lexChar == 'd' || lexChar == 'o'); else if (lexChar == '+' || lexChar == '-' || lexChar == '*' || lexChar == '&' || lexChar == '|') do { getNext(); } while (lexChar == lexToken[0]); else if (lexChar == '=' || lexChar == '<' || lexChar == '>' || lexChar == '!') do { getNext(); } while (lexChar == '=' || lexChar == '<' || lexChar == '>'); else if (isParen(lexChar) || lexChar == '/' || lexChar == '%' || lexChar == '.' || lexChar == ']' || lexChar == '}' || lexChar == ')' || lexChar == '^' || lexChar == ',' || lexChar == '?' || lexChar == ':' || lexChar == ';') getNext(); else if (lexChar == '@') { // special 'escape' character for internal SUBSCRIPT_MARKER/PARAMETER_MARKER sequences getNext(); getNext(); } else if (lexChar == '"') { do { if (lexChar == '\\') getNext(); getNext(); } while (lexChar != '"'); getNext(); } else { printf("[%s:%d] lexString '%s' unknown lexChar %c %x\n", __FUNCTION__, __LINE__, lexString.c_str(), lexChar, lexChar); exit(-1); } ret = allocExpr(lexToken); if (isParen(ret->value)) { std::string val = ret->value; if (trace_expr) printf("[%s:%d] before subparse of '%s'\n", __FUNCTION__, __LINE__, ret->value.c_str()); ret = getExprList(ret, treePost(ret).substr(1), false, true); if (ret->value != val) ret = allocExpr(val, ret); // over optimization of '(<singleItem>)' if (trace_expr) { printf("[%s:%d] after subparse of '%s'\n", __FUNCTION__, __LINE__, ret->value.c_str()); dumpExpr("SUBPAREN", ret); } } return ret; }