Skip to content

Commit

Permalink
Add U, L and LL suffixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Dec 7, 2020
1 parent 34ab83b commit aaf1045
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 4 deletions.
2 changes: 1 addition & 1 deletion chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct Token {
int64_t val; // If kind is TK_NUM, its value
char *loc; // Token location
int len; // Token length
Type *ty; // Used if TK_STR
Type *ty; // Used if TK_NUM or TK_STR
char *str; // String literal contents including terminating '\0'

int line_no; // Line number
Expand Down
1 change: 1 addition & 0 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,7 @@ static Node *primary(Token **rest, Token *tok) {

if (tok->kind == TK_NUM) {
Node *node = new_num(tok->val, tok);
node->ty = tok->ty;
*rest = tok->next;
return node;
}
Expand Down
61 changes: 61 additions & 0 deletions test/literal.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,67 @@ int main() {
ASSERT(47, 0b101111);
ASSERT(47, 0B101111);

ASSERT(4, sizeof(0));
ASSERT(8, sizeof(0L));
ASSERT(8, sizeof(0LU));
ASSERT(8, sizeof(0UL));
ASSERT(8, sizeof(0LL));
ASSERT(8, sizeof(0LLU));
ASSERT(8, sizeof(0Ull));
ASSERT(8, sizeof(0l));
ASSERT(8, sizeof(0ll));
ASSERT(8, sizeof(0x0L));
ASSERT(8, sizeof(0b0L));
ASSERT(4, sizeof(2147483647));
ASSERT(8, sizeof(2147483648));
ASSERT(-1, 0xffffffffffffffff);
ASSERT(8, sizeof(0xffffffffffffffff));
ASSERT(4, sizeof(4294967295U));
ASSERT(8, sizeof(4294967296U));

ASSERT(3, -1U>>30);
ASSERT(3, -1Ul>>62);
ASSERT(3, -1ull>>62);

ASSERT(1, 0xffffffffffffffffl>>63);
ASSERT(1, 0xffffffffffffffffll>>63);

ASSERT(-1, 18446744073709551615);
ASSERT(8, sizeof(18446744073709551615));
ASSERT(-1, 18446744073709551615>>63);

ASSERT(-1, 0xffffffffffffffff);
ASSERT(8, sizeof(0xffffffffffffffff));
ASSERT(1, 0xffffffffffffffff>>63);

ASSERT(-1, 01777777777777777777777);
ASSERT(8, sizeof(01777777777777777777777));
ASSERT(1, 01777777777777777777777>>63);

ASSERT(-1, 0b1111111111111111111111111111111111111111111111111111111111111111);
ASSERT(8, sizeof(0b1111111111111111111111111111111111111111111111111111111111111111));
ASSERT(1, 0b1111111111111111111111111111111111111111111111111111111111111111>>63);

ASSERT(8, sizeof(2147483648));
ASSERT(4, sizeof(2147483647));

ASSERT(8, sizeof(0x1ffffffff));
ASSERT(4, sizeof(0xffffffff));
ASSERT(1, 0xffffffff>>31);

ASSERT(8, sizeof(040000000000));
ASSERT(4, sizeof(037777777777));
ASSERT(1, 037777777777>>31);

ASSERT(8, sizeof(0b111111111111111111111111111111111));
ASSERT(4, sizeof(0b11111111111111111111111111111111));
ASSERT(1, 0b11111111111111111111111111111111>>31);

ASSERT(-1, 1 << 31 >> 31);
ASSERT(-1, 01 << 31 >> 31);
ASSERT(-1, 0x1 << 31 >> 31);
ASSERT(-1, 0b1 << 31 >> 31);

printf("OK\n");
return 0;
}
60 changes: 58 additions & 2 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,29 +243,85 @@ static Token *read_char_literal(char *start) {

Token *tok = new_token(TK_NUM, start, end + 1);
tok->val = c;
tok->ty = ty_int;
return tok;
}

static Token *read_int_literal(char *start) {
char *p = start;

// Read a binary, octal, decimal or hexadecimal number.
int base = 10;
if (!strncasecmp(p, "0x", 2) && isalnum(p[2])) {
if (!strncasecmp(p, "0x", 2) && isxdigit(p[2])) {
p += 2;
base = 16;
} else if (!strncasecmp(p, "0b", 2) && isalnum(p[2])) {
} else if (!strncasecmp(p, "0b", 2) && (p[2] == '0' || p[2] == '1')) {
p += 2;
base = 2;
} else if (*p == '0') {
base = 8;
}

int64_t val = strtoul(p, &p, base);

// Read U, L or LL suffixes.
bool l = false;
bool u = false;

if (startswith(p, "LLU") || startswith(p, "LLu") ||
startswith(p, "llU") || startswith(p, "llu") ||
startswith(p, "ULL") || startswith(p, "Ull") ||
startswith(p, "uLL") || startswith(p, "ull")) {
p += 3;
l = u = true;
} else if (!strncasecmp(p, "lu", 2) || !strncasecmp(p, "ul", 2)) {
p += 2;
l = u = true;
} else if (startswith(p, "LL") || startswith(p, "ll")) {
p += 2;
l = true;
} else if (*p == 'L' || *p == 'l') {
p++;
l = true;
} else if (*p == 'U' || *p == 'u') {
p++;
u = true;
}

if (isalnum(*p))
error_at(p, "invalid digit");

// Infer a type.
Type *ty;
if (base == 10) {
if (l && u)
ty = ty_ulong;
else if (l)
ty = ty_long;
else if (u)
ty = (val >> 32) ? ty_ulong : ty_uint;
else
ty = (val >> 31) ? ty_long : ty_int;
} else {
if (l && u)
ty = ty_ulong;
else if (l)
ty = (val >> 63) ? ty_ulong : ty_long;
else if (u)
ty = (val >> 32) ? ty_ulong : ty_uint;
else if (val >> 63)
ty = ty_ulong;
else if (val >> 32)
ty = ty_long;
else if (val >> 31)
ty = ty_uint;
else
ty = ty_int;
}

Token *tok = new_token(TK_NUM, start, p);
tok->val = val;
tok->ty = ty;
return tok;
}

Expand Down
2 changes: 1 addition & 1 deletion type.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void add_type(Node *node) {

switch (node->kind) {
case ND_NUM:
node->ty = (node->val == (int)node->val) ? ty_int : ty_long;
node->ty = ty_int;
return;
case ND_ADD:
case ND_SUB:
Expand Down

0 comments on commit aaf1045

Please sign in to comment.