cleaning up binding code
This commit is contained in:
parent
38e67f8287
commit
5337b65513
102
binding.c
102
binding.c
|
@ -3,28 +3,33 @@
|
|||
struct returnobject;
|
||||
struct scopeobject;
|
||||
|
||||
ValueObject *getArg(struct scopeobject *scope, char *name)
|
||||
{
|
||||
IdentifierNode *id = createIdentifierNode(IT_DIRECT, (void *)copyString(name), NULL, NULL, 0);
|
||||
ValueObject *val = getScopeValueLocal(scope, scope, id);
|
||||
deleteIdentifierNode(id);
|
||||
return val;
|
||||
}
|
||||
|
||||
struct returnobject *fopenWrapper(struct scopeobject *scope)
|
||||
{
|
||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("filename"), NULL, NULL, 0);
|
||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
||||
IdentifierNode *id2 = createIdentifierNode(IT_DIRECT, (void *)copyString("mode"), NULL, NULL, 0);
|
||||
ValueObject *val2 = getScopeValueLocal(scope, scope, id2);
|
||||
char *filename = getString(val1);
|
||||
char *mode = getString(val2);
|
||||
ValueObject *arg1 = getArg(scope, "filename");
|
||||
ValueObject *arg2 = getArg(scope, "mode");
|
||||
char *filename = getString(arg1);
|
||||
char *mode = getString(arg2);
|
||||
|
||||
FILE *f = fopen(filename, mode);
|
||||
|
||||
ValueObject *ret = createBlobValueObject(f);
|
||||
return createReturnObject(RT_RETURN, ret);
|
||||
}
|
||||
|
||||
struct returnobject *freadWrapper(struct scopeobject *scope)
|
||||
{
|
||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("file"), NULL, NULL, 0);
|
||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
||||
IdentifierNode *id2 = createIdentifierNode(IT_DIRECT, (void *)copyString("length"), NULL, NULL, 0);
|
||||
ValueObject *val2 = getScopeValueLocal(scope, scope, id2);
|
||||
FILE *file = (FILE *)getBlob(val1);
|
||||
int length = getInteger(val2);
|
||||
ValueObject *arg1 = getArg(scope, "file");
|
||||
ValueObject *arg2 = getArg(scope, "length");
|
||||
FILE *file = (FILE *)getBlob(arg1);
|
||||
int length = getInteger(arg2);
|
||||
|
||||
char *buf = malloc((sizeof(char) * length) + 1);
|
||||
fread(buf, 1, length, file);
|
||||
|
@ -36,46 +41,83 @@ struct returnobject *freadWrapper(struct scopeobject *scope)
|
|||
|
||||
struct returnobject *fcloseWrapper(struct scopeobject *scope)
|
||||
{
|
||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("file"), NULL, NULL, 0);
|
||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
||||
FILE *file = (FILE *)getBlob(val1);
|
||||
ValueObject *arg1 = getArg(scope, "file");
|
||||
FILE *file = (FILE *)getBlob(arg1);
|
||||
|
||||
fclose(file);
|
||||
deleteValueObject(arg1);
|
||||
|
||||
return createReturnObject(RT_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
void loadBinding(ScopeObject *scope)
|
||||
void loadLibrary(ScopeObject *scope, IdentifierNode *name)
|
||||
{
|
||||
/* TODO: make this select which library to load */
|
||||
|
||||
/* stdio */
|
||||
ScopeObject *lib = createScopeObject(scope);
|
||||
IdentifierNode* id = createIdentifierNode(IT_DIRECT, (void *)copyString("STDIO"), NULL, NULL, 0);
|
||||
createScopeValue(scope, scope, id);
|
||||
ValueObject *val = createArrayValueObject(lib);
|
||||
updateScopeValue(scope, scope, id, val);
|
||||
loadBinding(lib, "FOPENIN", "filename mode", &fopenWrapper);
|
||||
loadBinding(lib, "FREADIN", "file length", &freadWrapper);
|
||||
loadBinding(lib, "FCLOSIN", "file", &fcloseWrapper);
|
||||
}
|
||||
|
||||
void loadBinding(ScopeObject *scope, char *name, const char *args, struct returnobject *(*binding)(struct scopeobject *))
|
||||
{
|
||||
/* TODO: add error checking and handling */
|
||||
|
||||
/* stdio */
|
||||
ScopeObject *stdio = createScopeObject(scope);
|
||||
IdentifierNode* name_stdio = createIdentifierNode(IT_DIRECT, (void *)copyString("STDIO"), NULL, NULL, 0);
|
||||
createScopeValue(scope, scope, name_stdio);
|
||||
ValueObject *val_stdio = createArrayValueObject(stdio);
|
||||
updateScopeValue(scope, scope, name_stdio, val_stdio);
|
||||
IdentifierNode* id = createIdentifierNode(IT_DIRECT, (void *)copyString(name), NULL, NULL, 0);
|
||||
StmtNodeList *stmts = createStmtNodeList();
|
||||
BindingStmtNode *stmt = createBindingStmtNode(binding);
|
||||
StmtNode *wrapper = createStmtNode(ST_BINDING, stmt);
|
||||
addStmtNode(stmts, wrapper);
|
||||
BlockNode *body = createBlockNode(stmts);
|
||||
|
||||
IdentifierNodeList *ids = createIdentifierNodeList();
|
||||
const char *start = args;
|
||||
while (start != NULL) {
|
||||
char *end = strchr(start, ' ');
|
||||
char *temp = NULL;
|
||||
unsigned int len = 0;
|
||||
if (end != NULL) len = (end - start);
|
||||
else len = strlen(start);
|
||||
temp = malloc(sizeof(char) * (len + 1));
|
||||
strncpy(temp, start, len);
|
||||
temp[len] = '\0';
|
||||
if (end != NULL) start = (end + 1);
|
||||
else start = NULL;
|
||||
IdentifierNode *arg = createIdentifierNode(IT_DIRECT, (void *)temp, NULL, NULL, 0);
|
||||
addIdentifierNode(ids, arg);
|
||||
}
|
||||
|
||||
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, id, ids, body);
|
||||
ValueObject *val = createFunctionValueObject(interface);
|
||||
createScopeValue(scope, scope, id);
|
||||
updateScopeValue(scope, scope, id, val);
|
||||
return;
|
||||
|
||||
/* fopen */
|
||||
/*
|
||||
{
|
||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FOPENIN"), NULL, NULL, 0);
|
||||
IdentifierNodeList *args = createIdentifierNodeList();
|
||||
IdentifierNode *filename = createIdentifierNode(IT_DIRECT, (void *)copyString("filename"), NULL, NULL, 0);
|
||||
IdentifierNode *mode = createIdentifierNode(IT_DIRECT, (void *)copyString("mode"), NULL, NULL, 0);
|
||||
addIdentifierNode(args, filename);
|
||||
addIdentifierNode(args, mode);
|
||||
StmtNodeList *stmts = createStmtNodeList();
|
||||
BindingStmtNode *binding = createBindingStmtNode(&fopenWrapper);
|
||||
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
||||
addStmtNode(stmts, wrapper);
|
||||
BlockNode *body = createBlockNode(stmts);
|
||||
/* TODO: should this first parameter be NULL? */
|
||||
|
||||
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
||||
ValueObject *val = createFunctionValueObject(interface);
|
||||
createScopeValue(stdio, stdio, name);
|
||||
updateScopeValue(stdio, stdio, name, val);
|
||||
}
|
||||
*/
|
||||
|
||||
/* fread */
|
||||
/*
|
||||
{
|
||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FREADIN"), NULL, NULL, 0);
|
||||
IdentifierNodeList *args = createIdentifierNodeList();
|
||||
|
@ -88,14 +130,15 @@ void loadBinding(ScopeObject *scope)
|
|||
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
||||
addStmtNode(stmts, wrapper);
|
||||
BlockNode *body = createBlockNode(stmts);
|
||||
/* TODO: should this first parameter be NULL? */
|
||||
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
||||
ValueObject *val = createFunctionValueObject(interface);
|
||||
createScopeValue(stdio, stdio, name);
|
||||
updateScopeValue(stdio, stdio, name, val);
|
||||
}
|
||||
*/
|
||||
|
||||
/* fclose */
|
||||
/*
|
||||
{
|
||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FCLOSIN"), NULL, NULL, 0);
|
||||
IdentifierNodeList *args = createIdentifierNodeList();
|
||||
|
@ -111,6 +154,7 @@ void loadBinding(ScopeObject *scope)
|
|||
createScopeValue(stdio, stdio, name);
|
||||
updateScopeValue(stdio, stdio, name, val);
|
||||
}
|
||||
*/
|
||||
|
||||
return;
|
||||
|
||||
|
|
25
binding.h
25
binding.h
|
@ -23,27 +23,8 @@ typedef struct {
|
|||
FuncDefStmtNode *interface; /**< The interface that exports the binding. */
|
||||
} Binding;
|
||||
|
||||
void loadBinding(ScopeObject *); /* TODO: make this take an IdentifierNode library to load */
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* - At startup, check which bindings are imported (using "CAN HAS" syntax)
|
||||
* - Package those bindings as VT_FUNCs in BUKKITs
|
||||
* - Add those bindings to the top-level scope (maybe create a new,
|
||||
* higher-than-global scope for this)
|
||||
* - To implement a new binding, specify the interface, which will contain a
|
||||
* BlockNode that contains a StmtListNode with one statement: a
|
||||
* BindingStmtNode that implements a native function that modifies directly
|
||||
* the scope.
|
||||
* - Binding creation/deletion helper functions.
|
||||
|
||||
IdentifierNode *scope = ??? what goes here again?;
|
||||
IdentifierNode *name = createIdentifierNode("FileOpen");
|
||||
IdentifierNodeList *args = ... add these ...
|
||||
BlockNode *block = ... block with appropriate BindingStmtNode ...
|
||||
FuncDefStmtNode *def = createFuncDefStmtNode();
|
||||
Binding *binding = createBinding("STDIO", def);
|
||||
|
||||
*/
|
||||
ValueObject *getArg(struct scopeobject *, char *);
|
||||
void loadLibrary(ScopeObject *, IdentifierNode *);
|
||||
void loadBinding(ScopeObject *, char *, const char *, struct returnobject *(*)(struct scopeobject *));
|
||||
|
||||
#endif /* __BINDING_H__ */
|
||||
|
|
|
@ -3683,11 +3683,32 @@ ReturnObject *interpretBindingStmtNode(StmtNode *node,
|
|||
return (stmt->binding)(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets a library import statement.
|
||||
*
|
||||
* \param [in] node The statement to interpret.
|
||||
*
|
||||
* \param [in] scope The scope to evaluate \a node under.
|
||||
*
|
||||
* \pre \a node contains a statement created by createImportStmtNode().
|
||||
*
|
||||
* \return A pointer to a default return value.
|
||||
*
|
||||
* \retval NULL An error occurred during interpretation.
|
||||
*/
|
||||
ReturnObject *interpretImportStmtNode(StmtNode *node,
|
||||
ScopeObject *scope)
|
||||
{
|
||||
ImportStmtNode *stmt = (ImportStmtNode *)node->stmt;
|
||||
loadLibrary(scope, stmt->name);
|
||||
return createReturnObject(RT_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* A jump table for statements. The index of a function in the table is given
|
||||
* by its its index in the enumerated StmtType type.
|
||||
*/
|
||||
static ReturnObject *(*StmtJumpTable[15])(StmtNode *, ScopeObject *) = {
|
||||
static ReturnObject *(*StmtJumpTable[16])(StmtNode *, ScopeObject *) = {
|
||||
interpretCastStmtNode,
|
||||
interpretPrintStmtNode,
|
||||
interpretInputStmtNode,
|
||||
|
@ -3702,7 +3723,8 @@ static ReturnObject *(*StmtJumpTable[15])(StmtNode *, ScopeObject *) = {
|
|||
interpretFuncDefStmtNode,
|
||||
interpretExprStmtNode,
|
||||
interpretAltArrayDefStmtNode,
|
||||
interpretBindingStmtNode };
|
||||
interpretBindingStmtNode,
|
||||
interpretImportStmtNode };
|
||||
|
||||
/**
|
||||
* Interprets a statement.
|
||||
|
@ -3798,10 +3820,7 @@ int interpretMainNode(MainNode *main)
|
|||
{
|
||||
ReturnObject *ret = NULL;
|
||||
if (!main) return 1;
|
||||
ScopeObject *libs = createScopeObject(NULL);
|
||||
if (!libs) return 1;
|
||||
loadBinding(libs);
|
||||
ret = interpretBlockNode(main->block, libs);
|
||||
ret = interpretBlockNode(main->block, NULL);
|
||||
if (!ret) return 1;
|
||||
deleteReturnObject(ret);
|
||||
return 0;
|
||||
|
|
|
@ -260,6 +260,8 @@ ReturnObject *interpretDeallocationStmtNode(StmtNode *, ScopeObject *);
|
|||
ReturnObject *interpretFuncDefStmtNode(StmtNode *, ScopeObject *);
|
||||
ReturnObject *interpretExprStmtNode(StmtNode *, ScopeObject *);
|
||||
ReturnObject *interpretAltArrayDefStmtNode(StmtNode *, ScopeObject *);
|
||||
ReturnObject *interpretBindingStmtNode(StmtNode *, ScopeObject *);
|
||||
ReturnObject *interpretImportStmtNode(StmtNode *, ScopeObject *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
|
|
17
lexer.c
17
lexer.c
|
@ -198,6 +198,21 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
start += 2;
|
||||
continue;
|
||||
}
|
||||
/* Question mark (?) is its own lexeme */
|
||||
if (*start == '?') {
|
||||
Lexeme *lex = createLexeme("?", fname, line);
|
||||
if (!lex) {
|
||||
deleteLexemeList(list);
|
||||
return NULL;
|
||||
}
|
||||
if (!addLexeme(list, lex)) {
|
||||
deleteLexeme(lex);
|
||||
deleteLexemeList(list);
|
||||
return NULL;
|
||||
}
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
/* Skip over leading whitespace */
|
||||
while (isspace(*start)) {
|
||||
unsigned int newline = 0;
|
||||
|
@ -292,6 +307,7 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
if (start[len] && !isspace(start[len])
|
||||
&& *(start + len) != ','
|
||||
&& *(start + len) != '!'
|
||||
&& *(start + len) != '?'
|
||||
&& strncmp(start + len, "'Z", 2)
|
||||
&& strncmp(start + len, "...", 3)
|
||||
&& strncmp(start + len, "\xE2\x80\xA6", 3)) {
|
||||
|
@ -305,6 +321,7 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
while (start[len] && !isspace(start[len])
|
||||
&& *(start + len) != ','
|
||||
&& *(start + len) != '!'
|
||||
&& *(start + len) != '?'
|
||||
&& strncmp(start + len, "'Z", 2)
|
||||
&& strncmp(start + len, "...", 3)
|
||||
&& strncmp(start + len, "\xE2\x80\xA6", 3))
|
||||
|
|
118
parser.c
118
parser.c
|
@ -514,6 +514,16 @@ void deleteStmtNode(StmtNode *node)
|
|||
deleteAltArrayDefStmtNode(stmt);
|
||||
break;
|
||||
}
|
||||
case ST_BINDING: {
|
||||
BindingStmtNode *stmt = (BindingStmtNode *)node->stmt;
|
||||
deleteBindingStmtNode(stmt);
|
||||
break;
|
||||
}
|
||||
case ST_IMPORT: {
|
||||
ImportStmtNode *stmt = (ImportStmtNode *)node->stmt;
|
||||
deleteImportStmtNode(stmt);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error(PR_UNKNOWN_STATEMENT_TYPE);
|
||||
break;
|
||||
|
@ -1105,6 +1115,40 @@ void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *node)
|
|||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a library import statement.
|
||||
*
|
||||
* \param [in] name The name of the library to import.
|
||||
*
|
||||
* \return A pointer to a library import statement with the desired properties.
|
||||
*
|
||||
* \retval NULL Memory allocation failed.
|
||||
*/
|
||||
ImportStmtNode *createImportStmtNode(IdentifierNode *name)
|
||||
{
|
||||
ImportStmtNode *p = malloc(sizeof(ImportStmtNode));
|
||||
if (!p) {
|
||||
perror("malloc");
|
||||
return NULL;
|
||||
}
|
||||
p->name = name;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a library import statement.
|
||||
*
|
||||
* \param [in,out] node The library import statement to delete.
|
||||
*
|
||||
* \post The memory at \a node and all of its members will be freed.
|
||||
*/
|
||||
void deleteImportStmtNode(ImportStmtNode *node)
|
||||
{
|
||||
if (!node) return;
|
||||
deleteIdentifierNode(node->name);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a binding statement.
|
||||
*
|
||||
|
@ -3905,6 +3949,76 @@ parseAltArrayDefStmtNodeAbort: /* Exception handling */
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tokens into a library import statement.
|
||||
*
|
||||
* \param [in] tokenp The position in a token list to start parsing at.
|
||||
*
|
||||
* \post \a tokenp will point to the next unparsed token.
|
||||
*
|
||||
* \return A pointer to a return statement.
|
||||
*
|
||||
* \retval NULL Unable to parse.
|
||||
*/
|
||||
StmtNode *parseImportStmtNode(Token ***tokenp)
|
||||
{
|
||||
IdentifierNode *value = NULL;
|
||||
ImportStmtNode *stmt = NULL;
|
||||
StmtNode *ret = NULL;
|
||||
int status;
|
||||
|
||||
/* Work from a copy of the token stream in case something goes wrong */
|
||||
Token **tokens = *tokenp;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("ST_IMPORT");
|
||||
#endif
|
||||
|
||||
/* Remove the library import keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_CANHAS);
|
||||
if (!status) {
|
||||
parser_error_expected_token(TT_CANHAS, tokens);
|
||||
goto parseImportStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Parse the library name */
|
||||
value = parseIdentifierNode(&tokens);
|
||||
if (!value) goto parseImportStmtNodeAbort;
|
||||
|
||||
/* Check for the question mark token (currently optional) */
|
||||
acceptToken(&tokens, TT_QUESTION);
|
||||
|
||||
/* The library import statement must reside on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseImportStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Create the new ImportStmtNode structure */
|
||||
stmt = createImportStmtNode(value);
|
||||
if (!stmt) goto parseImportStmtNodeAbort;
|
||||
|
||||
/* Create the new StmtNode structure */
|
||||
ret = createStmtNode(ST_IMPORT, stmt);
|
||||
if (!ret) goto parseImportStmtNodeAbort;
|
||||
|
||||
/* Since we're successful, update the token stream */
|
||||
*tokenp = tokens;
|
||||
|
||||
return ret;
|
||||
|
||||
parseImportStmtNodeAbort: /* Exception handling */
|
||||
|
||||
/* Clean up any allocated structures */
|
||||
if (ret) deleteStmtNode(ret);
|
||||
else if (stmt) deleteImportStmtNode(stmt);
|
||||
else {
|
||||
if (value) deleteIdentifierNode(value);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tokens into a statement.
|
||||
*
|
||||
|
@ -4023,6 +4137,10 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
|||
else if (peekToken(&tokens, TT_OHAIIM)) {
|
||||
ret = parseAltArrayDefStmtNode(tokenp);
|
||||
}
|
||||
/* Library import statement */
|
||||
else if (peekToken(&tokens, TT_CANHAS)) {
|
||||
ret = parseImportStmtNode(tokenp);
|
||||
}
|
||||
/* Bare expression */
|
||||
else if ((expr = parseExprNode(&tokens))) {
|
||||
int status;
|
||||
|
|
21
parser.h
21
parser.h
|
@ -229,6 +229,7 @@ typedef enum {
|
|||
ST_EXPR, /**< Expression statement. */
|
||||
ST_ALTARRAYDEF, /**< Function definition statement. */
|
||||
ST_BINDING, /**< Binding to external library. */
|
||||
ST_IMPORT, /**< Library import statement. */
|
||||
} StmtType;
|
||||
|
||||
/**
|
||||
|
@ -365,6 +366,13 @@ typedef struct {
|
|||
IdentifierNode *parent; /**< An optional inherited array. */
|
||||
} AltArrayDefStmtNode;
|
||||
|
||||
/**
|
||||
* Stores a library import statement.
|
||||
*/
|
||||
typedef struct {
|
||||
IdentifierNode *name; /**< The name of the library to import. */
|
||||
} ImportStmtNode;
|
||||
|
||||
/**
|
||||
* Stores a binding to a native function.
|
||||
*/
|
||||
|
@ -726,6 +734,16 @@ AltArrayDefStmtNode *createAltArrayDefStmtNode(IdentifierNode *, BlockNode *, Id
|
|||
void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \name ImportStmtNode modifiers
|
||||
*
|
||||
* Functions for creating and deleting ImportStmtNodes.
|
||||
*/
|
||||
/**@{*/
|
||||
ImportStmtNode *createImportStmtNode(IdentifierNode *);
|
||||
void deleteImportStmtNode(ImportStmtNode *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \name BindingStmtNode modifiers
|
||||
*
|
||||
|
@ -734,7 +752,7 @@ void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *);
|
|||
/**@{*/
|
||||
struct returnobject;
|
||||
struct scopeobject;
|
||||
BindingStmtNode *createBindingStmtNode(struct returnobject *(*binding)(struct scopeobject *));
|
||||
BindingStmtNode *createBindingStmtNode(struct returnobject *(*)(struct scopeobject *));
|
||||
void deleteBindingStmtNode(BindingStmtNode *);
|
||||
/**@}*/
|
||||
|
||||
|
@ -823,6 +841,7 @@ StmtNode *parseLoopStmtNode(Token ***);
|
|||
StmtNode *parseDeallocationStmtNode(Token ***);
|
||||
StmtNode *parseFuncDefStmtNode(Token ***);
|
||||
StmtNode *parseAltArrayDefStmtNode(Token ***);
|
||||
StmtNode *parseImportStmtNode(Token ***);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -319,15 +319,6 @@ Token **tokenizeLexemes(LexemeList *list)
|
|||
token = createToken(TT_BOOLEAN, "WIN", fname, line);
|
||||
token->data.i = 1;
|
||||
}
|
||||
/* CAN HAS STDIO? */
|
||||
else if (n < list->num - 2
|
||||
&& !strcmp(lexeme->image, "CAN")
|
||||
&& !strcmp(list->lexemes[n + 1]->image, "HAS")
|
||||
&& !strcmp(list->lexemes[n + 2]->image, "STDIO?")) {
|
||||
n += 2;
|
||||
/* Just for fun; not actually in spec */
|
||||
continue;
|
||||
}
|
||||
/* Newline */
|
||||
/* Note that the spec is unclear as to whether a command *must*
|
||||
* follow a comma. For now, we let commas end a line. */
|
||||
|
|
|
@ -104,6 +104,8 @@ typedef enum {
|
|||
TT_OHAIIM, /**< Alternate array declaration. */
|
||||
TT_IMLIEK, /**< Alternate inherited object declaration. */
|
||||
TT_KTHX, /**< End of alternate array declaration. */
|
||||
TT_CANHAS, /**< Library import declaration. */
|
||||
TT_QUESTION, /**< End of library import declaration. */
|
||||
|
||||
TT_ENDOFTOKENS /**< Sentinel end of this enum -- don't move it! */
|
||||
} TokenType;
|
||||
|
@ -181,6 +183,8 @@ static const char *keywords[] = {
|
|||
"O HAI IM", /* TT_OHAIIM */
|
||||
"IM LIEK", /* TT_IMLIEK */
|
||||
"KTHX", /* TT_KTHX */
|
||||
"CAN HAS", /* TT_CANHAS */
|
||||
"?", /* TT_QUESTION */
|
||||
"" /* TT_ENDOFTOKENS */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue