element = value->next_;
_assert(value->value_ != NULL);
- CYString *string(dynamic_cast<CYString *>(value->value_));
+ CYString *string(value->value_->String(context));
if (string == NULL)
CYThrow("string was actually %s", typeid(*value->value_).name());
static std::ostream *out_;
-static void Output(CYUTF8String json, std::ostream *out, bool expand = false, bool reparse = false) {
+static void Output(CYUTF8String json, std::ostream *out, bool reparse = false) {
CYPool pool;
if (reparse) do {
if (data == NULL || out == NULL)
return;
- if (!expand ||
- data[0] != '@' && data[0] != '"' && data[0] != '\'' ||
- data[0] == '@' && data[1] != '"' && data[1] != '\''
- )
- CYLexerHighlight(data, size, *out);
- else for (size_t i(0); i != size; ++i)
- if (data[i] != '\\')
- *out << data[i];
- else switch(data[++i]) {
- case '\0': goto done;
- case '\\': *out << '\\'; break;
- case '\'': *out << '\''; break;
- case '"': *out << '"'; break;
- case 'b': *out << '\b'; break;
- case 'f': *out << '\f'; break;
- case 'n': *out << '\n'; break;
- case 'r': *out << '\r'; break;
- case 't': *out << '\t'; break;
- case 'v': *out << '\v'; break;
- default: *out << '\\'; --i; break;
- }
-
- done:
+ CYLexerHighlight(data, size, *out);
*out << std::endl;
}
CYConsoleRemapKeys(vi_movement_keymap);
}
-static void CYOutputRun(const std::string &code, bool expand = false, bool reparse = false) {
+static void CYOutputRun(const std::string &code, bool reparse = false) {
CYPool pool;
- Output(Run(pool, client_, code), &std::cout, expand, reparse);
+ Output(Run(pool, client_, code), &std::cout, reparse);
}
static void Console(CYOptions &options) {
bool bypass(false);
bool debug(false);
- bool expand(false);
bool lower(true);
bool reparse(false);
*out_ << "done." << std::endl;
} else if (data == "exit") {
return;
- } else if (data == "expand") {
- expand = !expand;
- *out_ << "expand == " << (expand ? "true" : "false") << std::endl;
} else if (data == "lower") {
lower = !lower;
*out_ << "lower == " << (lower ? "true" : "false") << std::endl;
std::cout << std::endl;
}
- CYOutputRun(code, expand, reparse);
+ CYOutputRun(code, reparse);
}
}
case kJSTypeString: {
std::ostringstream str;
CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, value)));
- CYStringify(str, string.data, string.size);
+ CYStringify(str, string.data, string.size, CYStringifyModeCycript);
std::string value(str.str());
return pool.strmemdup(value.c_str(), value.size());
} break;
if (CYIsKey(string))
str << string.data;
else
- CYStringify(str, string.data, string.size);
+ CYStringify(str, string.data, string.size, CYStringifyModeLegacy);
str << ':';
std::ostringstream str;
CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, _this)));
- CYStringify(str, string.data, string.size);
+ CYStringify(str, string.data, string.size, CYStringifyModeCycript);
std::string value(str.str());
return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
str << "NULL";
else {
str << "&";
- CYStringify(str, string, strlen(string), true);
+ CYStringify(str, string, strlen(string), CYStringifyModeNative);
}
std::string value(str.str());
return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
if (!objective)
str << '@';
CYUTF8String string(CYCastUTF8String(self));
- CYStringify(str, string.data, string.size, true);
+ CYStringify(str, string.data, string.size, CYStringifyModeNative);
std::string value(str.str());
return CYCastNSString(NULL, CYUTF8String(value.c_str(), value.size()));
}
#include "Syntax.hpp"
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) {
- bool single;
- if (c)
- single = false;
+enum CYStringType {
+ CYStringTypeSingle,
+ CYStringTypeDouble,
+ CYStringTypeTemplate,
+};
+
+void CYStringify(std::ostringstream &str, const char *data, size_t size, CYStringifyMode mode) {
+ if (size == 0) {
+ str << "\"\"";
+ return;
+ }
+
+ unsigned quot(0), apos(0), tick(0), line(0);
+ for (const char *value(data), *end(data + size); value != end; ++value)
+ switch (*value) {
+ case '"': ++quot; break;
+ case '\'': ++apos; break;
+ case '`': ++tick; break;
+ case '$': ++tick; break;
+ case '\n': ++line; break;
+ }
+
+ bool split;
+ if (mode != CYStringifyModeCycript)
+ split = false;
else {
- unsigned quot(0), apos(0);
- for (const char *value(data), *end(data + size); value != end; ++value)
- if (*value == '"')
- ++quot;
- else if (*value == '\'')
- ++apos;
-
- single = quot > apos;
+ double ratio(double(line) / size);
+ split = size > 10 && line > 2 && ratio > 0.005 && ratio < 0.10;
+ }
+
+ CYStringType type;
+ if (mode == CYStringifyModeNative)
+ type = CYStringTypeDouble;
+ else if (split)
+ type = CYStringTypeTemplate;
+ else if (quot > apos)
+ type = CYStringTypeSingle;
+ else
+ type = CYStringTypeDouble;
+
+ bool parens(split && mode != CYStringifyModeNative && type != CYStringTypeTemplate);
+ if (parens)
+ str << '(';
+
+ char border;
+ switch (type) {
+ case CYStringTypeSingle: border = '\''; break;
+ case CYStringTypeDouble: border = '"'; break;
+ case CYStringTypeTemplate: border = '`'; break;
}
- str << (single ? '\'' : '"');
+ str << border;
+
+ bool space(false);
for (const char *value(data), *end(data + size); value != end; ++value)
- switch (uint8_t next = *value) {
+ if (*value == ' ') {
+ space = true;
+ str << ' ';
+ } else { switch (uint8_t next = *value) {
case '\\': str << "\\\\"; break;
case '\b': str << "\\b"; break;
case '\f': str << "\\f"; break;
- case '\n': str << "\\n"; break;
case '\r': str << "\\r"; break;
case '\t': str << "\\t"; break;
case '\v': str << "\\v"; break;
+ case '\n':
+ if (!split)
+ str << "\\n";
+ /*else if (mode == CYStringifyModeNative)
+ str << border << "\\\n" << border;*/
+ else if (type != CYStringTypeTemplate)
+ str << border << '+' << border;
+ else if (!space)
+ str << '\n';
+ else
+ str << "\\n\\\n";
+ break;
+
+ case '$':
+ if (type == CYStringTypeTemplate)
+ str << "\\$";
+ else goto simple;
+ break;
+
+ case '`':
+ if (type == CYStringTypeTemplate)
+ str << "\\`";
+ else goto simple;
+ break;
+
case '"':
- if (!single)
+ if (type == CYStringTypeDouble)
str << "\\\"";
else goto simple;
break;
case '\'':
- if (single)
+ if (type == CYStringTypeSingle)
str << "\\'";
else goto simple;
break;
str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
}
}
- }
+ } space = false; }
+
+ str << border;
- str << (single ? '\'' : '"');
+ if (parens)
+ str << ')';
}
void CYNumerify(std::ostringstream &str, double value) {
void CYString::Output(CYOutput &out, CYFlags flags) const {
std::ostringstream str;
- CYStringify(str, value_, size_);
+ CYStringify(str, value_, size_, CYStringifyModeLegacy);
out << str.str().c_str();
}
return $C2($M($M($M($V("String"), $S("prototype")), $S("concat")), $S("apply")), $S(""), $ CYArray($ CYElementValue(string_, spans_->Replace(context))));
}
+CYString *CYTemplate::String(CYContext &context) {
+ // XXX: implement this over local concat
+ if (spans_ != NULL)
+ return NULL;
+ return string_;
+}
+
CYTarget *CYThis::Replace(CYContext &context) {
if (context.this_ != NULL)
return $V(context.this_->Identifier(context));
"$" R CYLexBufferUnit('$');
{PlateCharacter}+ R CYLexBufferUnits(yytext, yyleng);
- {PlateCharacter}*{LineTerminatorSequence} R E("invalid newline");
{PlateCharacter}*{UnicodeScrap} R E("invalid character");
+
+ {PlateCharacter}*{LineTerminatorSequence} yylloc->end.Lines(); CYLexBufferUnits(yytext, yyleng);
+ \\{LineTerminatorSequence} yylloc->end.Lines();
}
/* }}} */
/* Escapes {{{ */
double CYCastDouble(CYUTF8String value);
void CYNumerify(std::ostringstream &str, double value);
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c = false);
+
+enum CYStringifyMode {
+ CYStringifyModeLegacy,
+ CYStringifyModeCycript,
+ CYStringifyModeNative,
+};
+
+void CYStringify(std::ostringstream &str, const char *data, size_t size, CYStringifyMode mode);
// XXX: this really should not be here ... :/
void *CYPoolFile(CYPool &pool, const char *path, size_t *psize);
CYPrecedence(0)
+ virtual CYString *String(CYContext &context);
+
virtual CYTarget *Replace(CYContext &context);
virtual void Output(CYOutput &out, CYFlags flags) const;
};
char **CYComplete(const char *word, const std::string &line, CYUTF8String (*run)(CYPool &pool, const std::string &));
-void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c);
-
const char *CYPoolLibraryPath(CYPool &pool);
#endif/*CYCRIPT_HPP*/