txlyre hace 1 día
padre
commit
cd7873a0c8
Se han modificado 1 ficheros con 89 adiciones y 3 borrados
  1. 89 3
      qic.c

+ 89 - 3
qic.c

@@ -320,6 +320,8 @@ typedef struct {
     T_STARASSIGN,
     T_SLASHSLASHASSIGN,
     T_PERCENTASSIGN,
+    T_STARSTARASSIGN,
+    T_BARASSIGN,
     T_BARBAR,
     T_ANDAND,
     T_STARSTAR,
@@ -515,6 +517,21 @@ token_t *next_token(char *source, size_t *pos) {
     (*pos)++;
 
     return token(T_STRING, buffer_read(text));
+  } else if (source[*pos] == '0' && (source[(*pos)+1] == 'x' || source[(*pos)+1] == 'b' || source[(*pos)+1] == 'o')) {
+    buffer_t *number = buffer_new();
+    buffer_append(number, source[(*pos)++]);
+
+    char b = source[(*pos)++];
+
+    buffer_append(number, b);
+
+    while (source[*pos] && strchr(b == 'x' ? "0123456789abcdefABCDEF": b == 'b' ? "01": "01234567", source[*pos]) != NULL)
+      buffer_append(number, source[(*pos)++]);
+
+    if (number->size < 3)
+      LEX_ERROR("illegal number literal (trailing base)");
+
+    return token(T_NUMBER, buffer_read(number));
   } else if ((source[*pos] == '.' && isdigit(source[(*pos)+1])) || isdigit(source[*pos])) {
     buffer_t *number = buffer_new();
     int dot = 0;
@@ -631,6 +648,10 @@ token_t *next_token(char *source, size_t *pos) {
     return TK(SLASHSLASHASSIGN);
   else if (strncmp(&source[*pos], "%=", 2) == 0 && ++(*pos) && ++(*pos))
     return TK(PERCENTASSIGN);
+  else if (strncmp(&source[*pos], "**=", 3) == 0 && ++(*pos) && ++(*pos) && ++(*pos))
+    return TK(STARSTARASSIGN);
+  else if (strncmp(&source[*pos], "|=", 2) == 0 && ++(*pos) && ++(*pos))
+    return TK(BARASSIGN);
   else if (strncmp(&source[*pos], "||", 2) == 0 && ++(*pos) && ++(*pos))
     return TK(BARBAR);
   else if (strncmp(&source[*pos], "&&", 2) == 0 && ++(*pos) && ++(*pos))
@@ -768,6 +789,7 @@ struct _node_t {
     N_ASSIGN_IDIV,
     N_ASSIGN_MOD,
     N_ASSIGN_POW,
+    N_ASSIGN_BOR,
 
     N_EQUALS,
     N_NOTEQUALS,
@@ -1472,6 +1494,14 @@ node_t *parse_assignment(list_t *tokens, size_t *pos) {
     node_t *b = parse_assignment(tokens, pos);
 
     return NODE2(ASSIGN_MOD, a, b);
+  } else if (MATCH(STARSTARASSIGN)) {
+    node_t *b = parse_assignment(tokens, pos);
+
+    return NODE2(ASSIGN_POW, a, b);
+  } else if (MATCH(BARASSIGN)) {
+    node_t *b = parse_assignment(tokens, pos);
+
+    return NODE2(ASSIGN_BOR, a, b);
   }
 
   return a;
@@ -2320,6 +2350,7 @@ const char *STD[][2] = {
     "set_pseudomethod(\"string.slice\", slice)\n"
     "set_pseudomethod(\"bytes.slice\", slice)\n"
     "func Object(t, p=nil): return p !is nil? set_meta_table(p, get_meta_table(p) + t): set_meta_table({}, t)\n"
+    "func is_object(o): return has_meta_table(o)\n"
     "func __class_wrapper(n, p, t, mt): return Object({\n"
     "    t: t,\n"
     "    mt: mt,\n"
@@ -2348,6 +2379,40 @@ const char *STD[][2] = {
     "inline `srand(time(NULL))`\n"
   },
 
+  {"utf8",
+    "func utf8_chrlen(s) {\n"
+    "  s = bytes(s)\n"
+    "  var z = len(s)\n"
+    "  if z < 2\n"
+    "    return z\n"
+    "  var l = 1\n"
+    "  for var i = 1; i < z && (s[i] & 0xc0) == 0x80; i++\n"
+    "    l++\n"
+    "  return l\n"
+    "}\n"
+    "func utf8_decode(s) {\n"
+    "  s = bytes(s)\n"
+    "  var l = utf8_chrlen(s)\n"
+    "  if !l\n"
+    "    throw \"malformed sequence\"\n"
+    "  var c = (s[0] & ((1 << (8 - l)) - 1)) << (l - 1) * 6\n"
+    "  for var i = 1; i < l; i++\n"
+    "    c |= (s[i] & 0x3f) << (l - i - 1) * 6\n"
+    "  return (c, l)\n"
+    "}\n"
+    "func utf8_encode(c) {\n"
+    "  if c <= 0x7f\n"
+    "    return bytes([c & 0xFF])\n"
+    "  elif c >= 0x80 && c <= 0x7ff\n"
+    "    return bytes([0xC0 | ((c >> 6) & 0x1f), 0x80 | (c & 0x3f)])\n"
+    "  elif c >= 0x800 && c <= 0xfff\n"
+    "    return bytes([0xe0 | ((c >> 12) & 0xf), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)])\n"
+    "  elif c >= 0x10000 && c <= 0x10ffff\n"
+    "    return bytes([0xf0 | ((c >> 18) & 0x7), 0x80 | ((c >> 12) & 0x3f), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)])\n"
+    "  throw \"malformed codepoint\"\n"
+    "}\n"
+  },
+
   {"str",
     "let STR_LETTERS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n"
     "let STR_ASCII_LC = \"abcdefghijklmnopqrstuvwxyz\"\n"
@@ -2461,9 +2526,29 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
 
     case N_LITERAL:
       switch (node->t->tag) {
-        case T_NUMBER:
-          EMIT("qi_make_number(state, %s)", node->t->text);
-          break;
+        case T_NUMBER: {
+          char *number = node->t->text;
+          
+          if (strncmp(number, "0o", 2) == 0 || strncmp(number, "0b", 2) == 0) {
+            buffer_t *buf = buffer_new();
+
+            if (number[1] == 'o')
+              buffer_fmt(buf, "0%s", number + 2);
+            else
+              buffer_fmt(buf, "%d", strtol(number + 2, NULL, 2));
+
+            number = buffer_read(buf);
+          } else if (number[0] == '0' && number[1] && isdigit(number[1])) {
+            size_t i;
+            for (i = 0; i < strlen(number); i++)
+              if (number[i] != '0' || number[i+1] == '.')
+                break;
+
+            number += i;
+          }
+
+          EMIT("qi_make_number(state, %s)", number);
+          } break;
 
         case T_STRING:
           if (!*(node->t->text)) {
@@ -2539,6 +2624,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
     case N_ASSIGN_IDIV: COMPASSIGN(node->a, "idiv", compile_node(gbuf, buf, ctx, lstk, lbl, node->b)); break;
     case N_ASSIGN_MOD: COMPASSIGN(node->a, "mod", compile_node(gbuf, buf, ctx, lstk, lbl, node->b)); break;
     case N_ASSIGN_POW: COMPASSIGN(node->a, "pow", compile_node(gbuf, buf, ctx, lstk, lbl, node->b)); break;
+    case N_ASSIGN_BOR: COMPASSIGN(node->a, "bor", compile_node(gbuf, buf, ctx, lstk, lbl, node->b)); break;
 
     case N_INC: 
       COMPASSIGN(node->a, "add", EMIT("state->one"));