Use a separate table for keywords.

This commit is contained in:
Jack Palevich 2009-06-11 14:29:47 -07:00
parent 0a280a0dde
commit 2db168f12f
2 changed files with 134 additions and 69 deletions

View File

@ -1204,8 +1204,8 @@ class Compiler : public ErrorSink {
*/
class FakeString : public String {
public:
FakeString(char* string, size_t length) :
String(string, length, true) {}
FakeString(const char* string, size_t length) :
String((char*) string, length, true) {}
~FakeString() {
orphan();
@ -1220,6 +1220,7 @@ class Compiler : public ErrorSink {
~StringTable() {
clear();
hashmapFree(mpMap);
}
void clear() {
@ -1278,6 +1279,71 @@ class Compiler : public ErrorSink {
MacroTable() : StringTable<String>(10) {}
};
class KeywordTable {
public:
KeywordTable(){
mpMap = hashmapCreate(40, hashFn, equalsFn);
put("int", TOK_INT);
put("char", TOK_CHAR);
put("void", TOK_VOID);
put("if", TOK_IF);
put("else", TOK_ELSE);
put("while", TOK_WHILE);
put("break", TOK_BREAK);
put("return", TOK_RETURN);
put("for", TOK_FOR);
put("pragma", TOK_PRAGMA);
}
~KeywordTable() {
hashmapFree(mpMap);
}
int get(char* key) {
return (int) hashmapGet(mpMap, key);
}
const char* lookupKeyFor(int value) {
FindValContext context;
context.key = 0;
hashmapForEach(mpMap, findKeyFn, &context);
return context.key;
}
private:
void put(const char* kw, int val) {
hashmapPut(mpMap, (void*) kw, (void*) val);
}
static int hashFn(void* pKey) {
char* pString = (char*) pKey;
return hashmapHash(pString, strlen(pString));
}
static bool equalsFn(void* keyA, void* keyB) {
const char* pStringA = (const char*) keyA;
const char* pStringB = (const char*) keyB;
return strcmp(pStringA, pStringB) == 0;
}
struct FindValContext {
char* key;
int value;
};
static bool findKeyFn(void* key, void* value, void* context) {
FindValContext* pContext = (FindValContext*) context;
if ((int) value == pContext->value) {
pContext->key = (char*) key;
return false;
}
return true;
}
Hashmap* mpMap;
};
template<class E> class Array {
public:
Array() {
@ -1346,6 +1412,11 @@ class Compiler : public ErrorSink {
int oldCh;
};
struct VariableInfo {
void* pA;
void* pB;
};
int ch; // Current input character, or EOF
intptr_t tok; // token
@ -1360,7 +1431,8 @@ class Compiler : public ErrorSink {
int dch; // Macro state: Saves old value of ch during a macro playback.
char* last_id;
char* pGlobalBase;
char* pVarsBase; // Value of variables
VariableInfo* pVarsBase; // Value of variables
KeywordTable mKeywords;
InputStream* file;
@ -1377,20 +1449,22 @@ class Compiler : public ErrorSink {
static const int ALLOC_SIZE = 99999;
// Indentifiers start at 0x100 and increase by # (chars + 1) * 8
static const int TOK_IDENT = 0x100;
static const int TOK_INT = 0x100;
static const int TOK_CHAR = TOK_INT + 4*8;
static const int TOK_VOID = TOK_CHAR + 5*8;
static const int TOK_IF = TOK_VOID + 5*8;
static const int TOK_ELSE = TOK_IF + 3*8;
static const int TOK_WHILE = TOK_ELSE + 5*8;
static const int TOK_BREAK = TOK_WHILE + 6*8;
static const int TOK_RETURN = TOK_BREAK + 6*8;
static const int TOK_FOR = TOK_RETURN + 7*8;
static const int TOK_PRAGMA = TOK_FOR + 4*8;
static const int TOK_DEFINE = TOK_PRAGMA + 7*8;
static const int TOK_MAIN = TOK_DEFINE + 7*8;
// Keywords start at 0x100 and increase by 1
static const int TOK_KEYWORD = 0x100;
static const int TOK_INT = TOK_KEYWORD + 0;
static const int TOK_CHAR = TOK_KEYWORD + 1;
static const int TOK_VOID = TOK_KEYWORD + 2;
static const int TOK_IF = TOK_KEYWORD + 3;
static const int TOK_ELSE = TOK_KEYWORD + 4;
static const int TOK_WHILE = TOK_KEYWORD + 5;
static const int TOK_BREAK = TOK_KEYWORD + 6;
static const int TOK_RETURN = TOK_KEYWORD + 7;
static const int TOK_FOR = TOK_KEYWORD + 8;
static const int TOK_PRAGMA = TOK_KEYWORD + 9;
static const int TOK_DEFINE = TOK_KEYWORD + 10;
// Symbols start at 0x200
static const int TOK_SYMBOL = 0x200;
static const int TOK_DUMMY = 1;
static const int TOK_NUM = 2;
@ -1514,18 +1588,20 @@ class Compiler : public ErrorSink {
inp();
next();
} else {
* dstk = TAG_TOK; /* no need to mark end of string (we
suppose data is initialized to zero by calloc) */
tok = (intptr_t) (strstr(sym_stk, (last_id - 1))
- sym_stk);
* dstk = 0; /* mark real end of ident for dlsym() */
tok = tok * 8 + TOK_IDENT;
if (tok > TOK_DEFINE) {
if (tok + 8 > ALLOC_SIZE) {
error("Variable Table overflow.");
}
tok = (intptr_t) (pVarsBase + tok);
/* printf("tok=%s %x\n", last_id, tok); */
// Is this a keyword?
* dstk = 0;
int kwtok = mKeywords.get(last_id);
if (kwtok) {
tok = kwtok;
// fprintf(stderr, "tok= keyword %s %x\n", last_id, tok);
} else {
* dstk = TAG_TOK; /* no need to mark end of string (we
suppose data is initialized to zero by calloc) */
tok = (intptr_t) (strstr(sym_stk, (last_id - 1))
- sym_stk);
* dstk = 0; /* mark real end of ident for dlsym() */
tok = (intptr_t) & (pVarsBase[tok]);
// fprintf(stderr, "tok= symbol %s %x\n", last_id, tok);
}
}
}
@ -1583,15 +1659,19 @@ class Compiler : public ErrorSink {
}
#if 0
{
char* p;
const char* p;
printf("tok=0x%x ", tok);
if (tok >= TOK_IDENT) {
if (tok >= TOK_KEYWORD) {
printf("'");
if (tok> TOK_DEFINE)
p = sym_stk + 1 + ((char*) tok - pVarsBase - TOK_IDENT) / 8;
else
p = sym_stk + 1 + (tok - TOK_IDENT) / 8;
if (tok>= TOK_SYMBOL)
p = sym_stk + 1 + ((char*) tok - (char*) pVarsBase) / 8;
else {
p = mKeywords.lookupKeyFor(tok);
if (!p) {
p = "unknown keyword";
}
}
while (*p != TAG_TOK && *p)
printf("%c", *p++);
printf("'\n");
@ -1979,7 +2059,7 @@ class Compiler : public ErrorSink {
}
void checkSymbol() {
if (tok <= TOK_DEFINE) {
if (tok < TOK_SYMBOL) {
error("Expected a symbol");
}
}
@ -2174,15 +2254,10 @@ public:
pGen->init(&codeBuf);
file = new TextInputStream(text, textLength);
sym_stk = (char*) calloc(1, ALLOC_SIZE);
static const char* predefinedSymbols =
" int char void"
" if else while break return for"
" pragma define main ";
dstk = strcpy(sym_stk, predefinedSymbols)
+ strlen(predefinedSymbols);
dstk = sym_stk;
pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
glo = pGlobalBase;
pVarsBase = (char*) calloc(1, ALLOC_SIZE);
pVarsBase = (VariableInfo*) calloc(1, ALLOC_SIZE);
inp();
next();
globalDeclarations();
@ -2195,16 +2270,6 @@ public:
return result;
}
int run(int argc, char** argv) {
typedef int (*mainPtr)(int argc, char** argv);
mainPtr aMain = (mainPtr) *(int*) (pVarsBase + TOK_MAIN);
if (!aMain) {
fprintf(stderr, "Could not find function \"main\".\n");
return -1;
}
return aMain(argc, argv);
}
int dump(FILE* out) {
fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
return 0;
@ -2233,13 +2298,9 @@ public:
if (memcmp(pSym, name, nameLen) == 0
&& pSym[nameLen] == TAG_TOK) {
int tok = pSym - 1 - sym_stk;
tok = tok * 8 + TOK_IDENT;
if (tok <= TOK_DEFINE) {
return 0;
} else {
tok = (intptr_t) (pVarsBase + tok);
return * (void**) tok;
}
tok = tok * sizeof(VariableInfo);
tok = (intptr_t) ((intptr_t) pVarsBase + tok);
return * (void**) tok;
}
}
}

View File

@ -109,16 +109,20 @@ int main(int argc, char** argv) {
}
}
accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
if (runResults) {
accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
result = accGetError(script);
if (result == ACC_NO_ERROR && runResults) {
fprintf(stderr, "Executing compiled code:\n");
int codeArgc = argc - i + 1;
char** codeArgv = argv + i - 1;
codeArgv[0] = (char*) (inFile ? inFile : "stdin");
result = run(mainPointer, codeArgc, codeArgv);
fprintf(stderr, "result: %d\n", result);
result = accGetError(script);
if (result != ACC_NO_ERROR) {
fprintf(stderr, "Could not find main: %d\n", result);
} else {
fprintf(stderr, "Executing compiled code:\n");
int codeArgc = argc - i + 1;
char** codeArgv = argv + i - 1;
codeArgv[0] = (char*) (inFile ? inFile : "stdin");
result = run(mainPointer, codeArgc, codeArgv);
fprintf(stderr, "result: %d\n", result);
}
}
exit: