kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

literals.c (2789B)


      1 #include <string.h>
      2 
      3 #include "internal.h"
      4 
      5 void toy_emit_int_bytes(ToyParser* p, uint64_t v, uint8_t* buf, size_t n) {
      6   size_t i;
      7   (void)p;
      8   for (i = 0; i < n; ++i) buf[i] = (uint8_t)(v >> (i * 8u));
      9 }
     10 
     11 int toy_parse_number_arg(ToyParser* p, int64_t* out) {
     12   if (p->cur.kind != TOK_NUMBER || p->cur.is_float) {
     13     toy_error(p, p->cur.loc, "expected integer constant");
     14     return 0;
     15   }
     16   *out = p->cur.int_value;
     17   toy_parser_advance(p);
     18   return 1;
     19 }
     20 
     21 int toy_parse_string_sym(ToyParser* p, KitSym* out, size_t* len_out) {
     22   char buf[256];
     23   size_t len;
     24   if (p->cur.kind != TOK_STRING || p->cur.text_len < 2) {
     25     toy_error(p, p->cur.loc, "expected string literal");
     26     return 0;
     27   }
     28   len = p->cur.text_len - 2;
     29   if (len >= sizeof buf) {
     30     toy_error(p, p->cur.loc, "string literal too long");
     31     return 0;
     32   }
     33   memcpy(buf, p->cur.text + 1, len);
     34   buf[len] = '\0';
     35   *out = kit_sym_intern(p->c, (KitSlice){.s = buf, .len = len});
     36   if (len_out) *len_out = len;
     37   toy_parser_advance(p);
     38   return 1;
     39 }
     40 
     41 int toy_parse_string_bytes(ToyParser* p, uint8_t* out, size_t cap,
     42                            size_t* len_out) {
     43   const uint8_t* cur;
     44   const uint8_t* end;
     45   size_t n = 0;
     46   if (p->cur.kind != TOK_STRING || p->cur.text_len < 2) {
     47     toy_error(p, p->cur.loc, "expected string literal");
     48     return 0;
     49   }
     50   cur = p->cur.text + 1;
     51   end = p->cur.text + p->cur.text_len - 1;
     52   while (cur < end) {
     53     uint8_t c = *cur++;
     54     if (c == '\\' && cur < end) {
     55       uint8_t esc = *cur++;
     56       if (esc == '0')
     57         c = 0;
     58       else if (esc == 'n')
     59         c = '\n';
     60       else if (esc == 't')
     61         c = '\t';
     62       else if (esc == '"' || esc == '\\')
     63         c = esc;
     64       else if (esc == 'x' && cur + 1 < end) {
     65         uint8_t hi = *cur++;
     66         uint8_t lo = *cur++;
     67         uint8_t hv = (hi >= '0' && hi <= '9')   ? (uint8_t)(hi - '0')
     68                      : (hi >= 'a' && hi <= 'f') ? (uint8_t)(hi - 'a' + 10)
     69                      : (hi >= 'A' && hi <= 'F') ? (uint8_t)(hi - 'A' + 10)
     70                                                 : 255;
     71         uint8_t lv = (lo >= '0' && lo <= '9')   ? (uint8_t)(lo - '0')
     72                      : (lo >= 'a' && lo <= 'f') ? (uint8_t)(lo - 'a' + 10)
     73                      : (lo >= 'A' && lo <= 'F') ? (uint8_t)(lo - 'A' + 10)
     74                                                 : 255;
     75         if (hv == 255 || lv == 255) {
     76           toy_error(p, p->cur.loc, "invalid hex escape");
     77           return 0;
     78         }
     79         c = (uint8_t)((hv << 4) | lv);
     80       } else {
     81         toy_error(p, p->cur.loc, "unknown string escape");
     82         return 0;
     83       }
     84     }
     85     if (n >= cap) {
     86       toy_error(p, p->cur.loc, "string literal too long");
     87       return 0;
     88     }
     89     out[n++] = c;
     90   }
     91   *len_out = n;
     92   toy_parser_advance(p);
     93   return 1;
     94 }