171 lines
6.6 KiB
C
171 lines
6.6 KiB
C
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
#include "base.c"
|
|
|
|
int main() {
|
|
typedef struct {
|
|
char *name;
|
|
char *serialized_operator;
|
|
bool keyword;
|
|
} Task;
|
|
Task kinds[] = {
|
|
{"EOF"},
|
|
{"ERROR"},
|
|
{"IDENT"},
|
|
{"INT"},
|
|
{"FLOAT"},
|
|
{"CHAR"},
|
|
{"STRING"},
|
|
|
|
{"LPAREN", .serialized_operator = "("},
|
|
{"RPAREN", .serialized_operator = ")"},
|
|
{"LBRACKET", .serialized_operator = "["},
|
|
{"RBRACKET", .serialized_operator = "]"},
|
|
{"LBRACE", .serialized_operator = "{"},
|
|
{"RBRACE", .serialized_operator = "}"},
|
|
{"COMMA", .serialized_operator = ","},
|
|
{"DOT", .serialized_operator = "."},
|
|
{"ARROW", .serialized_operator = "->"},
|
|
{"ELLIPSIS", .serialized_operator = "..."},
|
|
{"COLON", .serialized_operator = ":"},
|
|
{"SEMICOLON", .serialized_operator = ";"},
|
|
{"QUESTION", .serialized_operator = "?"},
|
|
{"HASH", .serialized_operator = "#"},
|
|
{"HASHHASH", .serialized_operator = "##"},
|
|
{"PLUS", .serialized_operator = "+"},
|
|
{"MINUS", .serialized_operator = "-"},
|
|
{"STAR", .serialized_operator = "*"},
|
|
{"SLASH", .serialized_operator = "/"},
|
|
{"PERCENT", .serialized_operator = "%"},
|
|
{"INC", .serialized_operator = "++"},
|
|
{"DEC", .serialized_operator = "--"},
|
|
{"ASSIGN", .serialized_operator = "="},
|
|
{"PLUS_ASSIGN", .serialized_operator = "+="},
|
|
{"MINUS_ASSIGN", .serialized_operator = "-="},
|
|
{"MUL_ASSIGN", .serialized_operator = "*="},
|
|
{"DIV_ASSIGN", .serialized_operator = "/="},
|
|
{"MOD_ASSIGN", .serialized_operator = "%="},
|
|
{"LSHIFT_ASSIGN", .serialized_operator = "<<="},
|
|
{"RSHIFT_ASSIGN", .serialized_operator = ">>="},
|
|
{"AND_ASSIGN", .serialized_operator = "&="},
|
|
{"XOR_ASSIGN", .serialized_operator = "^="},
|
|
{"OR_ASSIGN", .serialized_operator = "|="},
|
|
{"EQ", .serialized_operator = "=="},
|
|
{"NEQ", .serialized_operator = "!="},
|
|
{"LT", .serialized_operator = "<"},
|
|
{"LEQ", .serialized_operator = "<="},
|
|
{"GT", .serialized_operator = ">"},
|
|
{"GEQ", .serialized_operator = ">="},
|
|
{"NOT", .serialized_operator = "!"},
|
|
{"BITNOT", .serialized_operator = "~"},
|
|
{"BITAND", .serialized_operator = "&"},
|
|
{"BITOR", .serialized_operator = "|"},
|
|
{"BITXOR", .serialized_operator = "^"},
|
|
{"AND", .serialized_operator = "&&"},
|
|
{"OR", .serialized_operator = "||"},
|
|
{"LSHIFT", .serialized_operator = "<<"},
|
|
{"RSHIFT", .serialized_operator = ">>"},
|
|
|
|
{"auto", .keyword = true},
|
|
{"break", .keyword = true},
|
|
{"case", .keyword = true},
|
|
{"char", .keyword = true},
|
|
{"const", .keyword = true},
|
|
{"continue", .keyword = true},
|
|
{"default", .keyword = true},
|
|
{"do", .keyword = true},
|
|
{"double", .keyword = true},
|
|
{"else", .keyword = true},
|
|
{"enum", .keyword = true},
|
|
{"extern", .keyword = true},
|
|
{"float", .keyword = true},
|
|
{"for", .keyword = true},
|
|
{"goto", .keyword = true},
|
|
{"if", .keyword = true},
|
|
{"inline", .keyword = true},
|
|
{"int", .keyword = true},
|
|
{"long", .keyword = true},
|
|
{"register", .keyword = true},
|
|
{"restrict", .keyword = true},
|
|
{"return", .keyword = true},
|
|
{"short", .keyword = true},
|
|
{"signed", .keyword = true},
|
|
{"sizeof", .keyword = true},
|
|
{"static", .keyword = true},
|
|
{"struct", .keyword = true},
|
|
{"switch", .keyword = true},
|
|
{"typedef", .keyword = true},
|
|
{"union", .keyword = true},
|
|
{"unsigned", .keyword = true},
|
|
{"void", .keyword = true},
|
|
{"volatile", .keyword = true},
|
|
{"while", .keyword = true},
|
|
};
|
|
|
|
printf("// auto generated by meta.c\n");
|
|
|
|
printf("typedef enum {\n");
|
|
for (int i = 0; i < ilen(kinds); i += 1) {
|
|
printf(" TOK_%s,\n", kinds[i].name);
|
|
}
|
|
printf("} Token_Kind;\n");
|
|
|
|
printf("char *token_to_op(Token_Kind kind) {\n");
|
|
printf(" switch (kind) {\n");
|
|
for (int i = 0; i < ilen(kinds); i += 1) {
|
|
if (kinds[i].serialized_operator) {
|
|
printf(" case TOK_%s: return \"%s\";\n", kinds[i].name, kinds[i].serialized_operator);
|
|
}
|
|
}
|
|
printf(" default: return 0;\n");
|
|
printf(" }\n");
|
|
printf("}\n");
|
|
|
|
printf("char *token_to_name(Token_Kind kind) {\n");
|
|
printf(" switch (kind) {\n");
|
|
for (int i = 0; i < ilen(kinds); i += 1) {
|
|
if (kinds[i].name) {
|
|
printf(" case TOK_%s: return \"%s\";\n", kinds[i].name, kinds[i].name);
|
|
}
|
|
}
|
|
printf(" default: return \"<invalid-token-kind>\";\n");
|
|
printf(" }\n");
|
|
printf("}\n");
|
|
|
|
{
|
|
printf("// \n");
|
|
printf("// KEYWORDS\n");
|
|
printf("// \n");
|
|
|
|
for (int i = 0; i < ilen(kinds); i += 1) {
|
|
if (kinds[i].keyword) {
|
|
printf("char *keyword_%s;\n", kinds[i].name);
|
|
}
|
|
}
|
|
|
|
Task *first = NULL;
|
|
Task *last = NULL;
|
|
printf("char *lex_first_keyword = NULL;\n");
|
|
printf("char *lex_last_keyword = NULL;\n");
|
|
printf("char *make_intern(char *string, int len);\n");
|
|
printf("#define lex_add_keyword(x) make_intern(x, ilen(x) - 1)\n");
|
|
printf("void lex_init_keywords(void) {\n");
|
|
for (int i = 0; i < ilen(kinds); i += 1) {
|
|
if (kinds[i].keyword) {
|
|
if (!first) first = kinds + i;
|
|
last = kinds + i;
|
|
printf(" keyword_%s = lex_add_keyword(\"%s\");\n", kinds[i].name, kinds[i].name);
|
|
}
|
|
}
|
|
printf("#define TOK_FIRST_KEYWORD TOK_%s\n", first->name);
|
|
printf("#define TOK_LAST_KEYWORD TOK_%s\n", last->name);
|
|
printf(" lex_first_keyword = keyword_%s;\n", first->name);
|
|
printf(" lex_last_keyword = keyword_%s;\n", last->name);
|
|
printf("}\n");
|
|
}
|
|
}
|