Page MenuHomePhorge

emit.c
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None
#include <string.h>
#include "highlight/emit.h"
static inline void ob_putc(hl_outbuf *o, char c) {
if (o->pos + 1 < o->size) o->buf[o->pos++] = c;
else o->overflow = true;
}
static inline void ob_write(hl_outbuf *o, const char *s, size_t n) {
if (o->pos + n < o->size) {
memcpy(o->buf + o->pos, s, n);
o->pos += n;
} else o->overflow = true;
}
static inline void ob_puts(hl_outbuf *o, const char *s) {
ob_write(o, s, strlen(s));
}
static inline void ob_put_escaped(hl_outbuf *o, char c) {
switch (c) {
case '<': ob_write(o, "<<", 2); break;
case '>': ob_write(o, ">>", 2); break;
case '%': ob_write(o, "%%", 2); break;
default: ob_putc(o, c); break;
}
}
void hl_outbuf_write_escaped(hl_outbuf *o, const char *s, size_t n) {
for (size_t i = 0; i < n; i++) ob_put_escaped(o, s[i]);
}
static const char *class_to_crvar(hl_token_class cls) {
switch (cls) {
case HL_NUMBER: return "#E8CD7C";
case HL_NUMBER_PREFIX: return "#EADBAD";
case HL_BOOLEAN: return "#65B2FF";
case HL_LITERAL_NULL: return "#65B2FF";
case HL_STRING: return "#FF8A7F";
case HL_STRING_DELIMITER: return "#FF7265";
case HL_STRING_ESCAPE: return "#F4AAA3";
case HL_STRING_KEY: return "#CCA3F4";
case HL_STRING_TEMPLATE: return "#FFB265";
case HL_REGEX: return "#FFB265";
case HL_REGEX_ESCAPE: return "#FFCC99";
case HL_REGEX_DELIMITER: return "#FF9932";
case HL_REGEX_CDATA: return "#65B2FF";
case HL_KEYWORD: return "#65B2FF";
case HL_KEYWORD_DELETE: return "#F43D3D";
case HL_TYPE: return "#59D8F1";
case HL_TYPE_STRING: return "#30E8AA";
case HL_TYPE_BOOLEAN: return "#30E8AA";
case HL_COMMENT: return "#758CA3";
case HL_FUNCTION_NAME: return "#30E8AA";
case HL_FUNCTION: return "#30E8AA";
case HL_ARGUMENT: return "#CCA3F4";
case HL_PROPERTY: return "#CCA3F4";
case HL_OPERATOR: return "#8CB2D8";
case HL_OPTIONAL_CHAIN: return "#8CB2D8";
case HL_BRACKET: return "#8CB2D8";
case HL_SEMICOLON: return "#B2CCE5";
case HL_KEYWORD_ITALIC: return "italic+#65B2FF";
case HL_CLASS_NAME: return "bold+#F7B76D";
case HL_PARENT_CLASS: return "bold+#59D8F1";
case HL_KEYWORD_EXTENDS: return "italic+#59D8F1";
default: return NULL;
}
}
static inline void ob_write_with_class(hl_outbuf *o, hl_token_class cls, const char *s, size_t n) {
if (n == 0) return;
const char *var = class_to_crvar(cls);
if (var) {
ob_putc(o, '<');
ob_puts(o, var);
ob_putc(o, '>');
hl_outbuf_write_escaped(o, s, n);
ob_write(o, "</>", 3);
} else hl_outbuf_write_escaped(o, s, n);
}
static bool span_is_template_string(const char *s, size_t n) {
for (size_t i = 0; i < n; i++) {
if (s[i] == '`') return true;
if (s[i] == '$' && i + 1 < n && s[i + 1] == '{') return true;
}
return false;
}
static void emit_string_literal(hl_outbuf *o, const char *s, size_t n, hl_token_class body_cls) {
if (n == 0) return;
size_t i = 0;
size_t seg_start = 0;
while (i < n) {
unsigned char ch = (unsigned char)s[i];
if (ch == '\\') {
ob_write_with_class(o, body_cls, s + seg_start, i - seg_start);
size_t esc_len = (i + 1 < n) ? 2 : 1;
ob_write_with_class(o, HL_STRING_ESCAPE, s + i, esc_len);
i += esc_len;
seg_start = i;
continue;
}
if (ch == '"' || ch == '\'' || ch == '`') {
ob_write_with_class(o, body_cls, s + seg_start, i - seg_start);
ob_write_with_class(o, HL_STRING_DELIMITER, s + i, 1);
i++;
seg_start = i;
continue;
}
if (ch == '$' && i + 1 < n && s[i + 1] == '{') {
ob_write_with_class(o, body_cls, s + seg_start, i - seg_start);
ob_write_with_class(o, HL_BRACKET, s + i, 1);
ob_write_with_class(o, HL_BRACKET, s + i + 1, 1);
i += 2;
seg_start = i;
continue;
}
i++;
}
ob_write_with_class(o, body_cls, s + seg_start, n - seg_start);
}
static void emit_regex_literal(hl_outbuf *o, const char *s, size_t n) {
if (n == 0) return;
ob_write_with_class(o, HL_REGEX_DELIMITER, s, 1);
size_t i = 1;
size_t seg_start = i;
bool in_class = false;
while (i < n) {
unsigned char ch = (unsigned char)s[i];
if (!in_class && ch == '/') {
ob_write_with_class(o, HL_REGEX, s + seg_start, i - seg_start);
ob_write_with_class(o, HL_REGEX_DELIMITER, s + i, 1);
i++;
ob_write_with_class(o, HL_REGEX_DELIMITER, s + i, n - i);
return;
}
if (ch == '\\') {
ob_write_with_class(o, in_class ? HL_REGEX_CDATA : HL_REGEX, s + seg_start, i - seg_start);
size_t esc_len = (i + 1 < n) ? 2 : 1;
ob_write_with_class(o, HL_REGEX_ESCAPE, s + i, esc_len);
i += esc_len;
seg_start = i;
continue;
}
if (!in_class && ch == '[') {
ob_write_with_class(o, HL_REGEX, s + seg_start, i - seg_start);
in_class = true;
seg_start = i;
i++;
continue;
}
if (in_class && ch == ']') {
i++;
ob_write_with_class(o, HL_REGEX_CDATA, s + seg_start, i - seg_start);
in_class = false;
seg_start = i;
continue;
}
i++;
}
ob_write_with_class(o, in_class ? HL_REGEX_CDATA : HL_REGEX, s + seg_start, n - seg_start);
}
static void emit_number_literal(hl_outbuf *o, const char *s, size_t n) {
if (n >= 2 && s[0] == '0' &&
(s[1] == 'x' || s[1] == 'X' ||
s[1] == 'b' || s[1] == 'B' ||
s[1] == 'o' || s[1] == 'O')) {
ob_write_with_class(o, HL_NUMBER_PREFIX, s, 2);
ob_write_with_class(o, HL_NUMBER, s + 2, n - 2);
return;
}
ob_write_with_class(o, HL_NUMBER, s, n);
}
void hl_outbuf_init(hl_outbuf *o, char *buf, size_t size) {
o->buf = buf;
o->size = size;
o->pos = 0;
o->overflow = false;
}
void hl_outbuf_emit_span(hl_outbuf *o, hl_token_class cls, const char *s, size_t n) {
if (cls == HL_STRING) {
hl_token_class body_cls = span_is_template_string(s, n) ? HL_STRING_TEMPLATE : HL_STRING;
emit_string_literal(o, s, n, body_cls);
return;
}
if (cls == HL_REGEX) {
emit_regex_literal(o, s, n);
return;
}
if (cls == HL_NUMBER) {
emit_number_literal(o, s, n);
return;
}
ob_write_with_class(o, cls, s, n);
}

File Metadata

Mime Type
text/x-c
Expires
Sun, May 3, 7:58 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
540792
Default Alt Text
emit.c (6 KB)

Event Timeline