Add `signed` keyword

This commit is contained in:
Rui Ueyama 2019-08-27 00:21:23 +09:00
parent d1e7d1e88d
commit 06d3190515
3 changed files with 47 additions and 10 deletions

32
parse.c
View File

@ -260,18 +260,20 @@ Program *program(void) {
// //
// Note that "typedef" and "static" can appear anywhere in a basetype. // Note that "typedef" and "static" can appear anywhere in a basetype.
// "int" can appear anywhere if type is short, long or long long. // "int" can appear anywhere if type is short, long or long long.
// "signed" can appear anywhere if type is short, int, long or long long.
static Type *basetype(StorageClass *sclass) { static Type *basetype(StorageClass *sclass) {
if (!is_typename()) if (!is_typename())
error_tok(token, "typename expected"); error_tok(token, "typename expected");
enum { enum {
VOID = 1 << 0, VOID = 1 << 0,
BOOL = 1 << 2, BOOL = 1 << 2,
CHAR = 1 << 4, CHAR = 1 << 4,
SHORT = 1 << 6, SHORT = 1 << 6,
INT = 1 << 8, INT = 1 << 8,
LONG = 1 << 10, LONG = 1 << 10,
OTHER = 1 << 12, OTHER = 1 << 12,
SIGNED = 1 << 13,
}; };
Type *ty = int_type; Type *ty = int_type;
@ -302,7 +304,8 @@ static Type *basetype(StorageClass *sclass) {
// Handle user-defined types. // Handle user-defined types.
if (!peek("void") && !peek("_Bool") && !peek("char") && if (!peek("void") && !peek("_Bool") && !peek("char") &&
!peek("short") && !peek("int") && !peek("long")) { !peek("short") && !peek("int") && !peek("long") &&
!peek("signed")) {
if (counter) if (counter)
break; break;
@ -333,6 +336,8 @@ static Type *basetype(StorageClass *sclass) {
counter += INT; counter += INT;
else if (consume("long")) else if (consume("long"))
counter += LONG; counter += LONG;
else if (consume("signed"))
counter |= SIGNED;
switch (counter) { switch (counter) {
case VOID: case VOID:
@ -342,19 +347,28 @@ static Type *basetype(StorageClass *sclass) {
ty = bool_type; ty = bool_type;
break; break;
case CHAR: case CHAR:
case SIGNED + CHAR:
ty = char_type; ty = char_type;
break; break;
case SHORT: case SHORT:
case SHORT + INT: case SHORT + INT:
case SIGNED + SHORT:
case SIGNED + SHORT + INT:
ty = short_type; ty = short_type;
break; break;
case INT: case INT:
case SIGNED:
case SIGNED + INT:
ty = int_type; ty = int_type;
break; break;
case LONG: case LONG:
case LONG + INT: case LONG + INT:
case LONG + LONG: case LONG + LONG:
case LONG + LONG + INT: case LONG + LONG + INT:
case SIGNED + LONG:
case SIGNED + LONG + INT:
case SIGNED + LONG + LONG:
case SIGNED + LONG + LONG + INT:
ty = long_type; ty = long_type;
break; break;
default: default:
@ -1118,7 +1132,7 @@ static bool is_typename(void) {
return peek("void") || peek("_Bool") || peek("char") || peek("short") || return peek("void") || peek("_Bool") || peek("char") || peek("short") ||
peek("int") || peek("long") || peek("enum") || peek("struct") || peek("int") || peek("long") || peek("enum") || peek("struct") ||
peek("typedef") || peek("static") || peek("extern") || peek("typedef") || peek("static") || peek("extern") ||
find_typedef(token); peek("signed") || find_typedef(token);
} }
static Node *stmt(void) { static Node *stmt(void) {

23
tests
View File

@ -709,6 +709,29 @@ int main() {
assert(6, add_all3(1,2,3,0), "add_all3(1,2,3,0)"); assert(6, add_all3(1,2,3,0), "add_all3(1,2,3,0)");
assert(5, add_all3(1,2,3,-1,0), "add_all3(1,2,3,-1,0)"); assert(5, add_all3(1,2,3,-1,0), "add_all3(1,2,3,-1,0)");
assert(1, sizeof(char), "sizeof(char)");
assert(1, sizeof(signed char), "sizeof(signed char)");
assert(1, sizeof(signed char signed), "sizeof(signed char signed)");
assert(2, sizeof(short), "sizeof(short)");
assert(2, sizeof(int short), "sizeof(int short)");
assert(2, sizeof(short int), "sizeof(short int)");
assert(2, sizeof(signed short), "sizeof(signed short)");
assert(2, sizeof(int short signed), "sizeof(int short signed)");
assert(4, sizeof(int), "sizeof(int)");
assert(4, sizeof(signed int), "sizeof(signed int)");
assert(4, sizeof(signed), "sizeof(signed)");
assert(4, sizeof(signed signed), "sizeof(signed signed)");
assert(8, sizeof(long), "sizeof(long)");
assert(8, sizeof(signed long), "sizeof(signed long)");
assert(8, sizeof(signed long int), "sizeof(signed long int)");
assert(8, sizeof(long long), "sizeof(long long)");
assert(8, sizeof(signed long long), "sizeof(signed long long)");
assert(8, sizeof(signed long long int), "sizeof(signed long long int)");
printf("OK\n"); printf("OK\n");
return 0; return 0;
} }

View File

@ -151,7 +151,7 @@ static char *starts_with_reserved(char *p) {
"char", "sizeof", "struct", "typedef", "short", "char", "sizeof", "struct", "typedef", "short",
"long", "void", "_Bool", "enum", "static", "break", "long", "void", "_Bool", "enum", "static", "break",
"continue", "goto", "switch", "case", "default", "continue", "goto", "switch", "case", "default",
"extern", "_Alignof", "do"}; "extern", "_Alignof", "do", "signed"};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) { for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) {
int len = strlen(kw[i]); int len = strlen(kw[i]);