summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer/parser.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-04-26 16:59:41 -0700
committerGitHub <noreply@github.com>2019-04-26 16:59:41 -0700
commitdb9124f1de0478dcac525009b6f1589b44a7edd8 (patch)
treefa26395a0f6cca53cf5cb6e10189f989c5bfa847 /src/emscripten-optimizer/parser.h
parent87636dccd404a340d75acb1d96301581343f29ca (diff)
downloadbinaryen-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.h607
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) {