diff options
author | Alon Zakai <azakai@google.com> | 2019-04-26 16:59:41 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-26 16:59:41 -0700 |
commit | db9124f1de0478dcac525009b6f1589b44a7edd8 (patch) | |
tree | fa26395a0f6cca53cf5cb6e10189f989c5bfa847 /src/emscripten-optimizer/parser.h | |
parent | 87636dccd404a340d75acb1d96301581343f29ca (diff) | |
download | binaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.tar.gz binaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.tar.bz2 binaryen-db9124f1de0478dcac525009b6f1589b44a7edd8.zip |
Apply format changes from #2048 (#2059)
Mass change to apply clang-format to everything. We are applying this in a PR by me so the (git) blame is all mine ;) but @aheejin did all the work to get clang-format set up and all the manual work to tidy up some things to make the output nicer in #2048
Diffstat (limited to 'src/emscripten-optimizer/parser.h')
-rw-r--r-- | src/emscripten-optimizer/parser.h | 607 |
1 files changed, 370 insertions, 237 deletions
diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index 78ed27933..d180ea12c 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -14,10 +14,12 @@ * limitations under the License. */ -// Pure parsing. Calls methods on a Builder (template argument) to actually construct the AST +// Pure parsing. Calls methods on a Builder (template argument) to actually +// construct the AST // -// XXX All parsing methods assume they take ownership of the input string. This lets them reuse -// parts of it. You will segfault if the input string cannot be reused and written to. +// XXX All parsing methods assume they take ownership of the input string. This +// lets them reuse parts of it. You will segfault if the input string cannot +// be reused and written to. #ifndef wasm_parser_h #define wasm_parser_h @@ -35,89 +37,89 @@ namespace cashew { // common strings -extern IString TOPLEVEL, - DEFUN, - BLOCK, - VAR, - CONST, - CONDITIONAL, - BINARY, - RETURN, - IF, - ELSE, - WHILE, - DO, - FOR, - SEQ, - SUB, - CALL, - LABEL, - BREAK, - CONTINUE, - SWITCH, - STRING, - TRY, - INF, - NaN, - LLVM_CTTZ_I32, - UDIVMODDI4, - UNARY_PREFIX, - UNARY_POSTFIX, - MATH_FROUND, - MATH_CLZ32, - INT64, - INT64_CONST, - SIMD_FLOAT32X4, - SIMD_FLOAT64X2, - SIMD_INT8X16, - SIMD_INT16X8, - SIMD_INT32X4, - PLUS, - MINUS, - OR, - AND, - XOR, - L_NOT, - B_NOT, - LT, - GE, - LE, - GT, - EQ, - NE, - DIV, - MOD, - MUL, - RSHIFT, - LSHIFT, - TRSHIFT, - HEAP8, - HEAP16, - HEAP32, - HEAPF32, - HEAPU8, - HEAPU16, - HEAPU32, - HEAPF64, - F0, - EMPTY, - FUNCTION, - OPEN_PAREN, - OPEN_BRACE, - OPEN_CURLY, - CLOSE_CURLY, - COMMA, - QUESTION, - COLON, - CASE, - DEFAULT, - DOT, - PERIOD, - NEW, - ARRAY, - OBJECT, - THROW, - SET; +extern IString TOPLEVEL; +extern IString DEFUN; +extern IString BLOCK; +extern IString VAR; +extern IString CONST; +extern IString CONDITIONAL; +extern IString BINARY; +extern IString RETURN; +extern IString IF; +extern IString ELSE; +extern IString WHILE; +extern IString DO; +extern IString FOR; +extern IString SEQ; +extern IString SUB; +extern IString CALL; +extern IString LABEL; +extern IString BREAK; +extern IString CONTINUE; +extern IString SWITCH; +extern IString STRING; +extern IString TRY; +extern IString INF; +extern IString NaN; +extern IString LLVM_CTTZ_I32; +extern IString UDIVMODDI4; +extern IString UNARY_PREFIX; +extern IString UNARY_POSTFIX; +extern IString MATH_FROUND; +extern IString MATH_CLZ32; +extern IString INT64; +extern IString INT64_CONST; +extern IString SIMD_FLOAT32X4; +extern IString SIMD_FLOAT64X2; +extern IString SIMD_INT8X16; +extern IString SIMD_INT16X8; +extern IString SIMD_INT32X4; +extern IString PLUS; +extern IString MINUS; +extern IString OR; +extern IString AND; +extern IString XOR; +extern IString L_NOT; +extern IString B_NOT; +extern IString LT; +extern IString GE; +extern IString LE; +extern IString GT; +extern IString EQ; +extern IString NE; +extern IString DIV; +extern IString MOD; +extern IString MUL; +extern IString RSHIFT; +extern IString LSHIFT; +extern IString TRSHIFT; +extern IString HEAP8; +extern IString HEAP16; +extern IString HEAP32; +extern IString HEAPF32; +extern IString HEAPU8; +extern IString HEAPU16; +extern IString HEAPU32; +extern IString HEAPF64; +extern IString F0; +extern IString EMPTY; +extern IString FUNCTION; +extern IString OPEN_PAREN; +extern IString OPEN_BRACE; +extern IString OPEN_CURLY; +extern IString CLOSE_CURLY; +extern IString COMMA; +extern IString QUESTION; +extern IString COLON; +extern IString CASE; +extern IString DEFAULT; +extern IString DOT; +extern IString PERIOD; +extern IString NEW; +extern IString ARRAY; +extern IString OBJECT; +extern IString THROW; +extern IString SET; extern IStringSet keywords; @@ -126,12 +128,7 @@ extern const char *OPERATOR_INITS, *SEPARATORS; extern int MAX_OPERATOR_SIZE, LOWEST_PREC; struct OperatorClass { - enum Type { - Binary = 0, - Prefix = 1, - Postfix = 2, - Tertiary = 3 - }; + enum Type { Binary = 0, Prefix = 1, Postfix = 2, Tertiary = 3 }; IStringSet ops; bool rtl; @@ -150,10 +147,11 @@ extern bool isIdentPart(char x); // parser -template<class NodeRef, class Builder> -class Parser { +template<class NodeRef, class Builder> class Parser { - static bool isSpace(char x) { return x == 32 || x == 9 || x == 10 || x == 13; } /* space, tab, linefeed/newline, or return */ + static bool isSpace(char x) { + return x == 32 || x == 9 || x == 10 || x == 13; + } /* space, tab, linefeed/newline, or return */ static void skipSpace(char*& curr) { while (*curr) { if (isSpace(*curr)) { @@ -162,13 +160,16 @@ class Parser { } if (curr[0] == '/' && curr[1] == '/') { curr += 2; - while (*curr && *curr != '\n') curr++; - if (*curr) curr++; + while (*curr && *curr != '\n') + curr++; + if (*curr) + curr++; continue; } if (curr[0] == '/' && curr[1] == '*') { curr += 2; - while (*curr && (curr[0] != '*' || curr[1] != '/')) curr++; + while (*curr && (curr[0] != '*' || curr[1] != '/')) + curr++; curr += 2; continue; } @@ -178,7 +179,12 @@ class Parser { static bool isDigit(char x) { return x >= '0' && x <= '9'; } - static bool hasChar(const char* list, char x) { while (*list) if (*list++ == x) return true; return false; } + static bool hasChar(const char* list, char x) { + while (*list) + if (*list++ == x) + return true; + return false; + } // An atomic fragment of something. Stops at a natural boundary. enum FragType { @@ -192,7 +198,9 @@ class Parser { }; struct Frag { -#ifndef _MSC_VER // MSVC does not allow unrestricted unions: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + // MSVC does not allow unrestricted unions: + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf +#ifndef _MSC_VER union { #endif IString str; @@ -203,12 +211,10 @@ class Parser { int size; FragType type; - bool isNumber() const { - return type == INT || type == DOUBLE; - } + bool isNumber() const { return type == INT || type == DOUBLE; } explicit Frag(char* src) { - char *start = src; + char* start = src; if (isIdentInit(*src)) { // read an identifier or a keyword src++; @@ -227,15 +233,22 @@ class Parser { } else if (isDigit(*src) || (src[0] == '.' && isDigit(src[1]))) { if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) { // Explicitly parse hex numbers of form "0x...", because strtod - // supports hex number strings only in C++11, and Visual Studio 2013 does - // not yet support that functionality. + // supports hex number strings only in C++11, and Visual Studio 2013 + // does not yet support that functionality. src += 2; num = 0; while (1) { - if (*src >= '0' && *src <= '9') { num *= 16; num += *src - '0'; } - else if (*src >= 'a' && *src <= 'f') { num *= 16; num += *src - 'a' + 10; } - else if (*src >= 'A' && *src <= 'F') { num *= 16; num += *src - 'A' + 10; } - else break; + if (*src >= '0' && *src <= '9') { + num *= 16; + num += *src - '0'; + } else if (*src >= 'a' && *src <= 'f') { + num *= 16; + num += *src - 'a' + 10; + } else if (*src >= 'A' && *src <= 'F') { + num *= 16; + num += *src - 'A' + 10; + } else + break; src++; } } else { @@ -244,33 +257,69 @@ class Parser { // asm.js must have a '.' for double values. however, we also tolerate // uglify's tendency to emit without a '.' (and fix it later with a +). // for valid asm.js input, the '.' should be enough, and for uglify - // in the emscripten optimizer pipeline, we use simple_ast where INT/DOUBLE - // is quite the same at this point anyhow + // in the emscripten optimizer pipeline, we use simple_ast where + // INT/DOUBLE is quite the same at this point anyhow type = (std::find(start, src, '.') == src && (wasm::isSInteger32(num) || wasm::isUInteger32(num))) - ? INT - : DOUBLE; + ? INT + : DOUBLE; assert(src > start); } else if (hasChar(OPERATOR_INITS, *src)) { switch (*src) { - case '!': str = src[1] == '=' ? NE : L_NOT; break; - case '%': str = MOD; break; - case '&': str = AND; break; - case '*': str = MUL; break; - case '+': str = PLUS; break; - case ',': str = COMMA; break; - case '-': str = MINUS; break; - case '.': str = PERIOD; break; - case '/': str = DIV; break; - case ':': str = COLON; break; - case '<': str = src[1] == '<' ? LSHIFT : (src[1] == '=' ? LE : LT); break; - case '=': str = src[1] == '=' ? EQ : SET; break; - case '>': str = src[1] == '>' ? (src[2] == '>' ? TRSHIFT : RSHIFT) : (src[1] == '=' ? GE : GT); break; - case '?': str = QUESTION; break; - case '^': str = XOR; break; - case '|': str = OR; break; - case '~': str = B_NOT; break; - default: abort(); + case '!': + str = src[1] == '=' ? NE : L_NOT; + break; + case '%': + str = MOD; + break; + case '&': + str = AND; + break; + case '*': + str = MUL; + break; + case '+': + str = PLUS; + break; + case ',': + str = COMMA; + break; + case '-': + str = MINUS; + break; + case '.': + str = PERIOD; + break; + case '/': + str = DIV; + break; + case ':': + str = COLON; + break; + case '<': + str = src[1] == '<' ? LSHIFT : (src[1] == '=' ? LE : LT); + break; + case '=': + str = src[1] == '=' ? EQ : SET; + break; + case '>': + str = src[1] == '>' ? (src[2] == '>' ? TRSHIFT : RSHIFT) + : (src[1] == '=' ? GE : GT); + break; + case '?': + str = QUESTION; + break; + case '^': + str = XOR; + break; + case '|': + str = OR; + break; + case '~': + str = B_NOT; + break; + default: + abort(); } size = strlen(str.str); #ifndef NDEBUG @@ -289,10 +338,10 @@ class Parser { src[1] = temp; src++; } else if (*src == '"' || *src == '\'') { - char *end = strchr(src+1, *src); + char* end = strchr(src + 1, *src); *end = 0; - str.set(src+1); - src = end+1; + str.set(src + 1); + src = end + 1; type = STRING; } else { dump("frag parsing", src); @@ -304,7 +353,9 @@ class Parser { struct ExpressionElement { bool isNode; -#ifndef _MSC_VER // MSVC does not allow unrestricted unions: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + // MSVC does not allow unrestricted unions: + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf +#ifndef _MSC_VER union { #endif NodeRef node; @@ -326,13 +377,15 @@ class Parser { }; // This is a list of the current stack of node-operator-node-operator-etc. - // this works by each parseExpression call appending to the vector; then recursing out, and the toplevel sorts it all + // this works by each parseExpression call appending to the vector; then + // recursing out, and the toplevel sorts it all typedef std::vector<ExpressionElement> ExpressionParts; std::vector<ExpressionParts> expressionPartsStack; - // Parses an element in a list of such elements, e.g. list of statements in a block, or list of parameters in a call - NodeRef parseElement(char*& src, const char* seps=";") { - //dump("parseElement", src); + // Parses an element in a list of such elements, e.g. list of statements in a + // block, or list of parameters in a call + NodeRef parseElement(char*& src, const char* seps = ";") { + // dump("parseElement", src); skipSpace(src); Frag frag(src); src += frag.size; @@ -349,44 +402,67 @@ class Parser { return parseExpression(parseFrag(frag), src, seps); } case SEPARATOR: { - if (frag.str == OPEN_PAREN) return parseExpression(parseAfterParen(src), src, seps); - if (frag.str == OPEN_BRACE) return parseExpression(parseAfterBrace(src), src, seps); - if (frag.str == OPEN_CURLY) return parseExpression(parseAfterCurly(src), src, seps); + if (frag.str == OPEN_PAREN) + return parseExpression(parseAfterParen(src), src, seps); + if (frag.str == OPEN_BRACE) + return parseExpression(parseAfterBrace(src), src, seps); + if (frag.str == OPEN_CURLY) + return parseExpression(parseAfterCurly(src), src, seps); abort(); } case OPERATOR: { return parseExpression(frag.str, src, seps); } - default: /* dump("parseElement", src); printf("bad frag type: %d\n", frag.type); */ abort(); + default: + /* dump("parseElement", src); printf("bad frag type: %d\n",frag.type); + */ + abort(); } return nullptr; } NodeRef parseFrag(Frag& frag) { switch (frag.type) { - case IDENT: return Builder::makeName(frag.str); - case STRING: return Builder::makeString(frag.str); - case INT: return Builder::makeInt(uint32_t(frag.num)); - case DOUBLE: return Builder::makeDouble(frag.num); - default: abort(); + case IDENT: + return Builder::makeName(frag.str); + case STRING: + return Builder::makeString(frag.str); + case INT: + return Builder::makeInt(uint32_t(frag.num)); + case DOUBLE: + return Builder::makeDouble(frag.num); + default: + abort(); } return nullptr; } NodeRef parseAfterKeyword(Frag& frag, char*& src, const char* seps) { skipSpace(src); - if (frag.str == FUNCTION) return parseFunction(src, seps); - else if (frag.str == VAR) return parseVar(src, seps, false); - else if (frag.str == CONST) return parseVar(src, seps, true); - else if (frag.str == RETURN) return parseReturn(src, seps); - else if (frag.str == IF) return parseIf(src, seps); - else if (frag.str == DO) return parseDo(src, seps); - else if (frag.str == WHILE) return parseWhile(src, seps); - else if (frag.str == BREAK) return parseBreak(src, seps); - else if (frag.str == CONTINUE) return parseContinue(src, seps); - else if (frag.str == SWITCH) return parseSwitch(src, seps); - else if (frag.str == NEW) return parseNew(src, seps); - else if (frag.str == FOR) return parseFor(src, seps); + if (frag.str == FUNCTION) + return parseFunction(src, seps); + else if (frag.str == VAR) + return parseVar(src, seps, false); + else if (frag.str == CONST) + return parseVar(src, seps, true); + else if (frag.str == RETURN) + return parseReturn(src, seps); + else if (frag.str == IF) + return parseIf(src, seps); + else if (frag.str == DO) + return parseDo(src, seps); + else if (frag.str == WHILE) + return parseWhile(src, seps); + else if (frag.str == BREAK) + return parseBreak(src, seps); + else if (frag.str == CONTINUE) + return parseContinue(src, seps); + else if (frag.str == SWITCH) + return parseSwitch(src, seps); + else if (frag.str == NEW) + return parseNew(src, seps); + else if (frag.str == FOR) + return parseFor(src, seps); dump(frag.str.str, src); abort(); return nullptr; @@ -406,13 +482,15 @@ class Parser { src++; while (1) { skipSpace(src); - if (*src == ')') break; + if (*src == ')') + break; Frag arg(src); assert(arg.type == IDENT); src += arg.size; Builder::appendArgumentToFunction(ret, arg.str); skipSpace(src); - if (*src == ')') break; + if (*src == ')') + break; if (*src == ',') { src++; continue; @@ -429,7 +507,8 @@ class Parser { NodeRef ret = Builder::makeVar(is_const); while (1) { skipSpace(src); - if (*src == ';') break; + if (*src == ';') + break; Frag name(src); assert(name.type == IDENT); NodeRef value; @@ -442,7 +521,8 @@ class Parser { } Builder::appendToVar(ret, name.str, value); skipSpace(src); - if (*src == ';') break; + if (*src == ';') + break; if (*src == ',') { src++; continue; @@ -458,7 +538,8 @@ class Parser { NodeRef value = !hasChar(seps, *src) ? parseElement(src, seps) : nullptr; skipSpace(src); assert(hasChar(seps, *src)); - if (*src == ';') src++; + if (*src == ';') + src++; return Builder::makeReturn(value); } @@ -516,14 +597,16 @@ class Parser { NodeRef parseBreak(char*& src, const char* seps) { skipSpace(src); Frag next(src); - if (next.type == IDENT) src += next.size; + if (next.type == IDENT) + src += next.size; return Builder::makeBreak(next.type == IDENT ? next.str : IString()); } NodeRef parseContinue(char*& src, const char* seps) { skipSpace(src); Frag next(src); - if (next.type == IDENT) src += next.size; + if (next.type == IDENT) + src += next.size; return Builder::makeContinue(next.type == IDENT ? next.str : IString()); } @@ -535,7 +618,8 @@ class Parser { while (1) { // find all cases and possibly a default skipSpace(src); - if (*src == '}') break; + if (*src == '}') + break; Frag next(src); if (next.type == KEYWORD) { if (next.str == CASE) { @@ -575,12 +659,14 @@ class Parser { src++; continue; } - // otherwise, may be some keyword that happens to start a block (e.g. case 1: _return_ 5) + // otherwise, may be some keyword that happens to start a block (e.g. + // case 1: _return_ 5) } // not case X: or default: or }, so must be some code skipSpace(src); bool explicitBlock = *src == '{'; - NodeRef subBlock = explicitBlock ? parseBracketedBlock(src) : parseBlock(src, ";}", CASE, DEFAULT); + NodeRef subBlock = explicitBlock ? parseBracketedBlock(src) + : parseBlock(src, ";}", CASE, DEFAULT); Builder::appendCodeToSwitch(ret, subBlock, explicitBlock); } skipSpace(src); @@ -595,34 +681,40 @@ class Parser { NodeRef parseAfterIdent(Frag& frag, char*& src, const char* seps) { skipSpace(src); - if (*src == '(') return parseExpression(parseCall(parseFrag(frag), src), src, seps); - if (*src == '[') return parseExpression(parseIndexing(parseFrag(frag), src), src, seps); + if (*src == '(') + return parseExpression(parseCall(parseFrag(frag), src), src, seps); + if (*src == '[') + return parseExpression(parseIndexing(parseFrag(frag), src), src, seps); if (*src == ':' && expressionPartsStack.back().size() == 0) { src++; skipSpace(src); NodeRef inner; - if (*src == '{') { // context lets us know this is not an object, but a block + if (*src == '{') { + // context lets us know this is not an object, but a block inner = parseBracketedBlock(src); } else { inner = parseElement(src, seps); } return Builder::makeLabel(frag.str, inner); } - if (*src == '.') return parseExpression(parseDotting(parseFrag(frag), src), src, seps); + if (*src == '.') + return parseExpression(parseDotting(parseFrag(frag), src), src, seps); return parseExpression(parseFrag(frag), src, seps); } NodeRef parseCall(NodeRef target, char*& src) { - expressionPartsStack.resize(expressionPartsStack.size()+1); + expressionPartsStack.resize(expressionPartsStack.size() + 1); assert(*src == '('); src++; NodeRef ret = Builder::makeCall(target); while (1) { skipSpace(src); - if (*src == ')') break; + if (*src == ')') + break; Builder::appendToCall(ret, parseElement(src, ",)")); skipSpace(src); - if (*src == ')') break; + if (*src == ')') + break; if (*src == ',') { src++; continue; @@ -636,7 +728,7 @@ class Parser { } NodeRef parseIndexing(NodeRef target, char*& src) { - expressionPartsStack.resize(expressionPartsStack.size()+1); + expressionPartsStack.resize(expressionPartsStack.size() + 1); assert(*src == '['); src++; NodeRef ret = Builder::makeIndexing(target, parseElement(src, "]")); @@ -658,7 +750,7 @@ class Parser { } NodeRef parseAfterParen(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size()+1); + expressionPartsStack.resize(expressionPartsStack.size() + 1); skipSpace(src); NodeRef ret = parseElement(src, ")"); skipSpace(src); @@ -670,16 +762,18 @@ class Parser { } NodeRef parseAfterBrace(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size()+1); + expressionPartsStack.resize(expressionPartsStack.size() + 1); NodeRef ret = Builder::makeArray(); while (1) { skipSpace(src); assert(*src); - if (*src == ']') break; + if (*src == ']') + break; NodeRef element = parseElement(src, ",]"); Builder::appendToArray(ret, element); skipSpace(src); - if (*src == ']') break; + if (*src == ']') + break; if (*src == ',') { src++; continue; @@ -691,12 +785,13 @@ class Parser { } NodeRef parseAfterCurly(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size()+1); + expressionPartsStack.resize(expressionPartsStack.size() + 1); NodeRef ret = Builder::makeObject(); while (1) { skipSpace(src); assert(*src); - if (*src == '}') break; + if (*src == '}') + break; Frag key(src); assert(key.type == IDENT || key.type == STRING); src += key.size; @@ -706,7 +801,8 @@ class Parser { NodeRef value = parseElement(src, ",}"); Builder::appendToObject(ret, key.str, value); skipSpace(src); - if (*src == '}') break; + if (*src == '}') + break; if (*src == ',') { src++; continue; @@ -735,12 +831,13 @@ class Parser { if (op == PERIOD) { return Builder::makeDot(left, right); } else { - return Builder::makeBinary(left, op ,right); + return Builder::makeBinary(left, op, right); } } - NodeRef parseExpression(ExpressionElement initial, char*&src, const char* seps) { - //dump("parseExpression", src); + NodeRef + parseExpression(ExpressionElement initial, char*& src, const char* seps) { + // dump("parseExpression", src); ExpressionParts& parts = expressionPartsStack.back(); skipSpace(src); if (*src == 0 || hasChar(seps, *src)) { @@ -771,55 +868,77 @@ class Parser { parts.push_back(initial); } NodeRef last = parseElement(src, seps); - if (!top) return last; + if (!top) + return last; { - ExpressionParts& parts = expressionPartsStack.back(); // |parts| may have been invalidated by that call + // |parts| may have been invalidated by that call + ExpressionParts& parts = expressionPartsStack.back(); // we are the toplevel. sort it all out // collapse right to left, highest priority first - //dumpParts(parts, 0); + // dumpParts(parts, 0); for (auto& ops : operatorClasses) { if (ops.rtl) { // right to left - for (int i = parts.size()-1; i >= 0; i--) { - if (parts[i].isNode) continue; + for (int i = parts.size() - 1; i >= 0; i--) { + if (parts[i].isNode) + continue; IString op = parts[i].getOp(); - if (!ops.ops.has(op)) continue; - if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) { - parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); + if (!ops.ops.has(op)) + continue; + if (ops.type == OperatorClass::Binary && i > 0 && + i < (int)parts.size() - 1) { + parts[i] = + makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); parts.erase(parts.begin() + i - 1); - } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size()-1) { - if (i > 0 && parts[i-1].isNode) continue; // cannot apply prefix operator if it would join two nodes - parts[i] = Builder::makePrefix(op, parts[i+1].getNode()); + } else if (ops.type == OperatorClass::Prefix && + i < (int)parts.size() - 1) { + if (i > 0 && parts[i - 1].isNode) + // cannot apply prefix operator if it would join two nodes + continue; + parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); } else if (ops.type == OperatorClass::Tertiary) { // we must be at X ? Y : Z // ^ - //dumpParts(parts, i); - if (op != COLON) continue; - assert(i < (int)parts.size()-1 && i >= 3); - if (parts[i-2].getOp() != QUESTION) continue; // e.g. x ? y ? 1 : 0 : 2 - parts[i-3] = Builder::makeConditional(parts[i-3].getNode(), parts[i-1].getNode(), parts[i+1].getNode()); + // dumpParts(parts, i); + if (op != COLON) + continue; + assert(i < (int)parts.size() - 1 && i >= 3); + if (parts[i - 2].getOp() != QUESTION) + continue; // e.g. x ? y ? 1 : 0 : 2 + parts[i - 3] = Builder::makeConditional(parts[i - 3].getNode(), + parts[i - 1].getNode(), + parts[i + 1].getNode()); parts.erase(parts.begin() + i - 2, parts.begin() + i + 2); - i = parts.size(); // basically a reset, due to things like x ? y ? 1 : 0 : 2 + // basically a reset, due to things like x ? y ? 1 : 0 : 2 + i = parts.size(); } // TODO: postfix } } else { // left to right for (int i = 0; i < (int)parts.size(); i++) { - if (parts[i].isNode) continue; + if (parts[i].isNode) + continue; IString op = parts[i].getOp(); - if (!ops.ops.has(op)) continue; - if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size()-1) { - parts[i] = makeBinary(parts[i-1].getNode(), op, parts[i+1].getNode()); + if (!ops.ops.has(op)) + continue; + if (ops.type == OperatorClass::Binary && i > 0 && + i < (int)parts.size() - 1) { + parts[i] = + makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); parts.erase(parts.begin() + i - 1); i--; - } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size()-1) { - if (i > 0 && parts[i-1].isNode) continue; // cannot apply prefix operator if it would join two nodes - parts[i] = Builder::makePrefix(op, parts[i+1].getNode()); + } else if (ops.type == OperatorClass::Prefix && + i < (int)parts.size() - 1) { + if (i > 0 && parts[i - 1].isNode) + // cannot apply prefix operator if it would join two nodes + continue; + parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); - i = std::max(i-2, 0); // allow a previous prefix operator to cascade + // allow a previous prefix operator to cascade + i = std::max(i - 2, 0); } // TODO: tertiary, postfix } } @@ -831,25 +950,33 @@ class Parser { } } - // Parses a block of code (e.g. a bunch of statements inside {,}, or the top level of o file) - NodeRef parseBlock(char*& src, const char* seps=";", IString keywordSep1=IString(), IString keywordSep2=IString()) { + // Parses a block of code (e.g. a bunch of statements inside {,}, or the top + // level of o file) + NodeRef parseBlock(char*& src, + const char* seps = ";", + IString keywordSep1 = IString(), + IString keywordSep2 = IString()) { NodeRef block = Builder::makeBlock(); - //dump("parseBlock", src); + // dump("parseBlock", src); while (1) { skipSpace(src); - if (*src == 0) break; + if (*src == 0) + break; if (*src == ';') { src++; // skip a statement in this block continue; } - if (hasChar(seps, *src)) break; + if (hasChar(seps, *src)) + break; if (!!keywordSep1) { Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep1) break; + if (next.type == KEYWORD && next.str == keywordSep1) + break; } if (!!keywordSep2) { Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep2) break; + if (next.type == KEYWORD && next.str == keywordSep2) + break; } NodeRef element = parseElementOrStatement(src, seps); Builder::appendToBlock(block, element); @@ -861,25 +988,29 @@ class Parser { skipSpace(src); assert(*src == '{'); src++; - NodeRef block = parseBlock(src, ";}"); // the two are not symmetrical, ; is just internally separating, } is the final one - parseBlock knows all this + // the two are not symmetrical, ; is just internally separating, } is the + // final one - parseBlock knows all this + NodeRef block = parseBlock(src, ";}"); assert(*src == '}'); src++; return block; } - NodeRef parseElementOrStatement(char*& src, const char *seps) { + NodeRef parseElementOrStatement(char*& src, const char* seps) { skipSpace(src); if (*src == ';') { src++; - return Builder::makeBlock(); // we don't need the brackets here, but oh well + // we don't need the brackets here, but oh well + return Builder::makeBlock(); } if (*src == '{') { // detect a trivial {} in a statement context - char *before = src; + char* before = src; src++; skipSpace(src); if (*src == '}') { src++; - return Builder::makeBlock(); // we don't need the brackets here, but oh well + // we don't need the brackets here, but oh well + return Builder::makeBlock(); } src = before; } @@ -892,9 +1023,10 @@ class Parser { return ret; } - NodeRef parseMaybeBracketed(char*& src, const char *seps) { + NodeRef parseMaybeBracketed(char*& src, const char* seps) { skipSpace(src); - return *src == '{' ? parseBracketedBlock(src) : parseElementOrStatement(src, seps); + return *src == '{' ? parseBracketedBlock(src) + : parseElementOrStatement(src, seps); } NodeRef parseParenned(char*& src) { @@ -910,13 +1042,15 @@ class Parser { // Debugging - char *allSource = nullptr; + char* allSource = nullptr; int allSize = 0; - static void dump(const char *where, char* curr) { + static void dump(const char* where, char* curr) { /* printf("%s:\n=============\n", where); - for (int i = 0; i < allSize; i++) printf("%c", allSource[i] ? allSource[i] : '?'); + for (int i = 0; i < allSize; i++) + printf("%c", allSource[i] ? allSource[i] : + '?'); printf("\n"); for (int i = 0; i < (curr - allSource); i++) printf(" "); printf("^\n=============\n"); @@ -927,20 +1061,19 @@ class Parser { while (*curr) { if (*curr == '\n') { newlinesLeft--; - if (newlinesLeft == 0) break; + if (newlinesLeft == 0) + break; } charsLeft--; - if (charsLeft == 0) break; + if (charsLeft == 0) + break; fprintf(stderr, "%c", *curr++); } fprintf(stderr, "\n\n"); } public: - - Parser() { - expressionPartsStack.resize(1); - } + Parser() { expressionPartsStack.resize(1); } // Highest-level parsing, as of a JavaScript script file. NodeRef parseToplevel(char* src) { |