update cashew
This commit is contained in:
Родитель
6ead9d7601
Коммит
956f2d9967
|
@ -71,6 +71,7 @@ IString TOPLEVEL("toplevel"),
|
|||
OPEN_PAREN("("),
|
||||
OPEN_BRACE("["),
|
||||
OPEN_CURLY("{"),
|
||||
CLOSE_CURLY("}"),
|
||||
COMMA(","),
|
||||
QUESTION("?"),
|
||||
COLON(":"),
|
||||
|
@ -87,7 +88,7 @@ IStringSet keywords("var function if else do while for break continue return swi
|
|||
allOperators(". ! ~ - + * / % + - << >> >>> < <= > >= == != & ^ | ? : = ,");
|
||||
|
||||
const char *OPERATOR_INITS = "+-*/%<>&^|~=!,?:.",
|
||||
*SEPARATORS = "([;{";
|
||||
*SEPARATORS = "([;{}";
|
||||
|
||||
int MAX_OPERATOR_SIZE = 3;
|
||||
|
||||
|
@ -131,5 +132,8 @@ bool OperatorClass::getRtl(int prec) {
|
|||
return operatorClasses[prec].rtl;
|
||||
}
|
||||
|
||||
bool isIdentInit(char x) { return (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_' || x == '$'; }
|
||||
bool isIdentPart(char x) { return isIdentInit(x) || (x >= '0' && x <= '9'); }
|
||||
|
||||
} // namespace cashew
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ extern IString TOPLEVEL,
|
|||
OPEN_PAREN,
|
||||
OPEN_BRACE,
|
||||
OPEN_CURLY,
|
||||
CLOSE_CURLY,
|
||||
COMMA,
|
||||
QUESTION,
|
||||
COLON,
|
||||
|
@ -118,6 +119,8 @@ struct OperatorClass {
|
|||
|
||||
extern std::vector<OperatorClass> operatorClasses;
|
||||
|
||||
extern bool isIdentInit(char x);
|
||||
extern bool isIdentPart(char x);
|
||||
|
||||
// parser
|
||||
|
||||
|
@ -148,9 +151,6 @@ class Parser {
|
|||
return curr;
|
||||
}
|
||||
|
||||
static bool isIdentInit(char x) { return (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || x == '_' || x == '$'; }
|
||||
static bool isIdentPart(char x) { return isIdentInit(x) || (x >= '0' && x <= '9'); }
|
||||
|
||||
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; }
|
||||
|
@ -362,10 +362,10 @@ class Parser {
|
|||
|
||||
NodeRef parseReturn(Frag& frag, char*& src, const char* seps) {
|
||||
src = skipSpace(src);
|
||||
NodeRef value = *src != ';' ? parseElement(src, ";") : nullptr;
|
||||
NodeRef value = !hasChar(seps, *src) ? parseElement(src, seps) : nullptr;
|
||||
src = skipSpace(src);
|
||||
assert(*src == ';');
|
||||
src++;
|
||||
assert(hasChar(seps, *src));
|
||||
if (*src == ';') src++;
|
||||
return Builder::makeReturn(value);
|
||||
}
|
||||
|
||||
|
@ -734,12 +734,7 @@ class Parser {
|
|||
Frag next(src);
|
||||
if (next.type == KEYWORD && next.str == keywordSep) break;
|
||||
}
|
||||
NodeRef element = parseElement(src, seps);
|
||||
src = skipSpace(src);
|
||||
if (*src && *src == ';') {
|
||||
element = Builder::makeStatement(element);
|
||||
src++;
|
||||
}
|
||||
NodeRef element = parseElementOrStatement(src, seps);
|
||||
Builder::appendToBlock(block, element);
|
||||
}
|
||||
return block;
|
||||
|
@ -756,9 +751,19 @@ class Parser {
|
|||
return block;
|
||||
}
|
||||
|
||||
NodeRef parseElementOrStatement(char*& src, const char *seps) {
|
||||
NodeRef ret = parseElement(src, seps);
|
||||
src = skipSpace(src);
|
||||
if (*src == ';') {
|
||||
ret = Builder::makeStatement(ret);
|
||||
src++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
NodeRef parseMaybeBracketed(char*& src, const char *seps) {
|
||||
src = skipSpace(src);
|
||||
return *src == '{' ? parseBracketedBlock(src) : parseElement(src, seps);
|
||||
return *src == '{' ? parseBracketedBlock(src) : parseElementOrStatement(src, seps);
|
||||
}
|
||||
|
||||
NodeRef parseMaybeBracketedBlock(char*& src, const char *seps, IString keywordSep=IString()) {
|
||||
|
@ -792,11 +797,14 @@ class Parser {
|
|||
*/
|
||||
printf("%s:\n==========\n", where);
|
||||
int newlinesLeft = 2;
|
||||
int charsLeft = 200;
|
||||
while (*curr) {
|
||||
if (*curr == '\n') {
|
||||
newlinesLeft--;
|
||||
if (newlinesLeft == 0) break;
|
||||
}
|
||||
charsLeft--;
|
||||
if (charsLeft == 0) break;
|
||||
printf("%c", *curr++);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
|
|
@ -538,10 +538,11 @@ struct JSPrinter {
|
|||
int size, used;
|
||||
|
||||
int indent;
|
||||
bool possibleSpace; // add a space to separate identifiers
|
||||
|
||||
Ref ast;
|
||||
|
||||
JSPrinter(bool pretty_, bool finalize_, Ref ast_) : pretty(pretty_), finalize(finalize_), buffer(0), size(0), used(0), indent(0), ast(ast_) {}
|
||||
JSPrinter(bool pretty_, bool finalize_, Ref ast_) : pretty(pretty_), finalize(finalize_), buffer(0), size(0), used(0), indent(0), possibleSpace(false), ast(ast_) {}
|
||||
|
||||
void printAst() {
|
||||
print(ast);
|
||||
|
@ -562,12 +563,14 @@ struct JSPrinter {
|
|||
}
|
||||
|
||||
void emit(char c) {
|
||||
maybeSpace(c);
|
||||
if (!pretty && c == '}' && buffer[used-1] == ';') used--; // optimize ;} into }, the ; is not separating anything
|
||||
ensure(1);
|
||||
buffer[used++] = c;
|
||||
}
|
||||
|
||||
void emit(const char *s) {
|
||||
maybeSpace(*s);
|
||||
int len = strlen(s);
|
||||
ensure(len);
|
||||
strcpy(buffer + used, s);
|
||||
|
@ -584,6 +587,18 @@ struct JSPrinter {
|
|||
if (pretty) emit(' ');
|
||||
}
|
||||
|
||||
void safeSpace() {
|
||||
if (pretty) emit(' ');
|
||||
else possibleSpace = true;
|
||||
}
|
||||
|
||||
void maybeSpace(char s) {
|
||||
if (possibleSpace) {
|
||||
possibleSpace = false;
|
||||
if (isIdentPart(s)) emit(' ');
|
||||
}
|
||||
}
|
||||
|
||||
void print(Ref node) {
|
||||
ensure();
|
||||
IString type = node[0]->getIString();
|
||||
|
@ -759,6 +774,7 @@ struct JSPrinter {
|
|||
// try to emit the fewest necessary characters
|
||||
bool integer = fmod(d, 1) == 0;
|
||||
static char storage_f[50], storage_e[50]; // f is normal, e is scientific for float, x for integer
|
||||
double err_f, err_e;
|
||||
for (int e = 0; e <= 1; e++) {
|
||||
char *buffer = e ? storage_e : storage_f;
|
||||
double temp;
|
||||
|
@ -779,6 +795,7 @@ struct JSPrinter {
|
|||
}
|
||||
snprintf(buffer, 45, format, d);
|
||||
sscanf(buffer, "%lf", &temp);
|
||||
//errv("%.18f, %.18e => %s => %.18f, %.18e (%d), ", d, d, buffer, temp, temp, temp == d);
|
||||
if (temp == d) break;
|
||||
}
|
||||
} else {
|
||||
|
@ -794,7 +811,8 @@ struct JSPrinter {
|
|||
sscanf(buffer, "%lf", &temp);
|
||||
}
|
||||
}
|
||||
assert(temp == d);
|
||||
(e ? err_e : err_f) = fabs(temp - d);
|
||||
//assert(temp == d);
|
||||
char *dot = strchr(buffer, '.');
|
||||
if (dot) {
|
||||
// remove trailing zeros
|
||||
|
@ -808,6 +826,7 @@ struct JSPrinter {
|
|||
} while (*copy++ != 0);
|
||||
end--;
|
||||
}
|
||||
//errv("%.18f => %s", d, buffer);
|
||||
// remove preceding zeros
|
||||
while (*buffer == '0') {
|
||||
char *copy = buffer;
|
||||
|
@ -815,6 +834,7 @@ struct JSPrinter {
|
|||
copy[0] = copy[1];
|
||||
} while (*copy++ != 0);
|
||||
}
|
||||
//errv("%.18f ===> %s", d, buffer);
|
||||
} else if (!integer || !e) {
|
||||
// no dot. try to change 12345000 => 12345e3
|
||||
char *end = strchr(buffer, 0);
|
||||
|
@ -839,7 +859,11 @@ struct JSPrinter {
|
|||
}
|
||||
//fprintf(stderr, "options:\n%s\n%s\n", storage_e, storage_f);
|
||||
if (neg) emit('-');
|
||||
emit(strlen(storage_e) < strlen(storage_f) ? storage_e : storage_f);
|
||||
if (err_e == err_f) {
|
||||
emit(strlen(storage_e) < strlen(storage_f) ? storage_e : storage_f);
|
||||
} else {
|
||||
emit(err_e < err_f ? storage_e : storage_f);
|
||||
}
|
||||
}
|
||||
|
||||
void printString(Ref node) {
|
||||
|
@ -912,10 +936,6 @@ struct JSPrinter {
|
|||
}
|
||||
|
||||
void printUnaryPrefix(Ref node) {
|
||||
if ((buffer[used-1] == '-' && node[1] == MINUS) ||
|
||||
(buffer[used-1] == '+' && node[1] == PLUS && !finalize)) {
|
||||
emit(' '); // cannot join - and - to --, looks like the -- operator
|
||||
}
|
||||
if (finalize && node[1] == PLUS && (node[2][0] == NUM ||
|
||||
(node[2][0] == UNARY_PREFIX && node[2][1] == MINUS && node[2][2][0] == NUM))) {
|
||||
// emit a finalized number
|
||||
|
@ -939,6 +959,10 @@ struct JSPrinter {
|
|||
used += 2;
|
||||
return;
|
||||
}
|
||||
if ((buffer[used-1] == '-' && node[1] == MINUS) ||
|
||||
(buffer[used-1] == '+' && node[1] == PLUS)) {
|
||||
emit(' '); // cannot join - and - to --, looks like the -- operator
|
||||
}
|
||||
emit(node[1]->getCString());
|
||||
printChild(node[2], node, 1);
|
||||
}
|
||||
|
@ -998,13 +1022,17 @@ struct JSPrinter {
|
|||
print(c[0]);
|
||||
emit(':');
|
||||
}
|
||||
indent++;
|
||||
newline();
|
||||
int curr = used;
|
||||
printStats(c[1]);
|
||||
indent--;
|
||||
if (curr != used) newline();
|
||||
else used--; // avoid the extra indentation we added tentatively
|
||||
if (c[1]->size() > 0) {
|
||||
indent++;
|
||||
newline();
|
||||
int curr = used;
|
||||
printStats(c[1]);
|
||||
indent--;
|
||||
if (curr != used) newline();
|
||||
else used--; // avoid the extra indentation we added tentatively
|
||||
} else {
|
||||
newline();
|
||||
}
|
||||
}
|
||||
emit('}');
|
||||
}
|
||||
|
@ -1034,7 +1062,7 @@ struct JSPrinter {
|
|||
|
||||
void printIf(Ref node) {
|
||||
emit("if");
|
||||
space();
|
||||
safeSpace();
|
||||
emit('(');
|
||||
print(node[1]);
|
||||
emit(')');
|
||||
|
@ -1056,14 +1084,14 @@ struct JSPrinter {
|
|||
if (hasElse) {
|
||||
space();
|
||||
emit("else");
|
||||
space();
|
||||
safeSpace();
|
||||
print(node[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void printDo(Ref node) {
|
||||
emit("do");
|
||||
space();
|
||||
safeSpace();
|
||||
print(node[2]);
|
||||
space();
|
||||
emit("while");
|
||||
|
|
Загрузка…
Ссылка в новой задаче