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 returnobject;
|
||||||
struct scopeobject;
|
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)
|
struct returnobject *fopenWrapper(struct scopeobject *scope)
|
||||||
{
|
{
|
||||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("filename"), NULL, NULL, 0);
|
ValueObject *arg1 = getArg(scope, "filename");
|
||||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
ValueObject *arg2 = getArg(scope, "mode");
|
||||||
IdentifierNode *id2 = createIdentifierNode(IT_DIRECT, (void *)copyString("mode"), NULL, NULL, 0);
|
char *filename = getString(arg1);
|
||||||
ValueObject *val2 = getScopeValueLocal(scope, scope, id2);
|
char *mode = getString(arg2);
|
||||||
char *filename = getString(val1);
|
|
||||||
char *mode = getString(val2);
|
|
||||||
|
|
||||||
FILE *f = fopen(filename, mode);
|
FILE *f = fopen(filename, mode);
|
||||||
|
|
||||||
ValueObject *ret = createBlobValueObject(f);
|
ValueObject *ret = createBlobValueObject(f);
|
||||||
return createReturnObject(RT_RETURN, ret);
|
return createReturnObject(RT_RETURN, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct returnobject *freadWrapper(struct scopeobject *scope)
|
struct returnobject *freadWrapper(struct scopeobject *scope)
|
||||||
{
|
{
|
||||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("file"), NULL, NULL, 0);
|
ValueObject *arg1 = getArg(scope, "file");
|
||||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
ValueObject *arg2 = getArg(scope, "length");
|
||||||
IdentifierNode *id2 = createIdentifierNode(IT_DIRECT, (void *)copyString("length"), NULL, NULL, 0);
|
FILE *file = (FILE *)getBlob(arg1);
|
||||||
ValueObject *val2 = getScopeValueLocal(scope, scope, id2);
|
int length = getInteger(arg2);
|
||||||
FILE *file = (FILE *)getBlob(val1);
|
|
||||||
int length = getInteger(val2);
|
|
||||||
|
|
||||||
char *buf = malloc((sizeof(char) * length) + 1);
|
char *buf = malloc((sizeof(char) * length) + 1);
|
||||||
fread(buf, 1, length, file);
|
fread(buf, 1, length, file);
|
||||||
|
@ -36,46 +41,83 @@ struct returnobject *freadWrapper(struct scopeobject *scope)
|
||||||
|
|
||||||
struct returnobject *fcloseWrapper(struct scopeobject *scope)
|
struct returnobject *fcloseWrapper(struct scopeobject *scope)
|
||||||
{
|
{
|
||||||
IdentifierNode *id1 = createIdentifierNode(IT_DIRECT, (void *)copyString("file"), NULL, NULL, 0);
|
ValueObject *arg1 = getArg(scope, "file");
|
||||||
ValueObject *val1 = getScopeValueLocal(scope, scope, id1);
|
FILE *file = (FILE *)getBlob(arg1);
|
||||||
FILE *file = (FILE *)getBlob(val1);
|
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
deleteValueObject(arg1);
|
||||||
|
|
||||||
return createReturnObject(RT_DEFAULT, NULL);
|
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 */
|
/* TODO: add error checking and handling */
|
||||||
|
|
||||||
/* stdio */
|
IdentifierNode* id = createIdentifierNode(IT_DIRECT, (void *)copyString(name), NULL, NULL, 0);
|
||||||
ScopeObject *stdio = createScopeObject(scope);
|
StmtNodeList *stmts = createStmtNodeList();
|
||||||
IdentifierNode* name_stdio = createIdentifierNode(IT_DIRECT, (void *)copyString("STDIO"), NULL, NULL, 0);
|
BindingStmtNode *stmt = createBindingStmtNode(binding);
|
||||||
createScopeValue(scope, scope, name_stdio);
|
StmtNode *wrapper = createStmtNode(ST_BINDING, stmt);
|
||||||
ValueObject *val_stdio = createArrayValueObject(stdio);
|
addStmtNode(stmts, wrapper);
|
||||||
updateScopeValue(scope, scope, name_stdio, val_stdio);
|
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 */
|
/* fopen */
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FOPENIN"), NULL, NULL, 0);
|
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();
|
StmtNodeList *stmts = createStmtNodeList();
|
||||||
BindingStmtNode *binding = createBindingStmtNode(&fopenWrapper);
|
BindingStmtNode *binding = createBindingStmtNode(&fopenWrapper);
|
||||||
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
||||||
addStmtNode(stmts, wrapper);
|
addStmtNode(stmts, wrapper);
|
||||||
BlockNode *body = createBlockNode(stmts);
|
BlockNode *body = createBlockNode(stmts);
|
||||||
/* TODO: should this first parameter be NULL? */
|
|
||||||
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
||||||
ValueObject *val = createFunctionValueObject(interface);
|
ValueObject *val = createFunctionValueObject(interface);
|
||||||
createScopeValue(stdio, stdio, name);
|
createScopeValue(stdio, stdio, name);
|
||||||
updateScopeValue(stdio, stdio, name, val);
|
updateScopeValue(stdio, stdio, name, val);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* fread */
|
/* fread */
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FREADIN"), NULL, NULL, 0);
|
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FREADIN"), NULL, NULL, 0);
|
||||||
IdentifierNodeList *args = createIdentifierNodeList();
|
IdentifierNodeList *args = createIdentifierNodeList();
|
||||||
|
@ -88,14 +130,15 @@ void loadBinding(ScopeObject *scope)
|
||||||
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
StmtNode *wrapper = createStmtNode(ST_BINDING, binding);
|
||||||
addStmtNode(stmts, wrapper);
|
addStmtNode(stmts, wrapper);
|
||||||
BlockNode *body = createBlockNode(stmts);
|
BlockNode *body = createBlockNode(stmts);
|
||||||
/* TODO: should this first parameter be NULL? */
|
|
||||||
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
FuncDefStmtNode *interface = createFuncDefStmtNode(NULL, name, args, body);
|
||||||
ValueObject *val = createFunctionValueObject(interface);
|
ValueObject *val = createFunctionValueObject(interface);
|
||||||
createScopeValue(stdio, stdio, name);
|
createScopeValue(stdio, stdio, name);
|
||||||
updateScopeValue(stdio, stdio, name, val);
|
updateScopeValue(stdio, stdio, name, val);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* fclose */
|
/* fclose */
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FCLOSIN"), NULL, NULL, 0);
|
IdentifierNode* name = createIdentifierNode(IT_DIRECT, (void *)copyString("FCLOSIN"), NULL, NULL, 0);
|
||||||
IdentifierNodeList *args = createIdentifierNodeList();
|
IdentifierNodeList *args = createIdentifierNodeList();
|
||||||
|
@ -111,6 +154,7 @@ void loadBinding(ScopeObject *scope)
|
||||||
createScopeValue(stdio, stdio, name);
|
createScopeValue(stdio, stdio, name);
|
||||||
updateScopeValue(stdio, stdio, name, val);
|
updateScopeValue(stdio, stdio, name, val);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
25
binding.h
25
binding.h
|
@ -23,27 +23,8 @@ typedef struct {
|
||||||
FuncDefStmtNode *interface; /**< The interface that exports the binding. */
|
FuncDefStmtNode *interface; /**< The interface that exports the binding. */
|
||||||
} Binding;
|
} Binding;
|
||||||
|
|
||||||
void loadBinding(ScopeObject *); /* TODO: make this take an IdentifierNode library to load */
|
ValueObject *getArg(struct scopeobject *, char *);
|
||||||
|
void loadLibrary(ScopeObject *, IdentifierNode *);
|
||||||
/**
|
void loadBinding(ScopeObject *, char *, const char *, struct returnobject *(*)(struct scopeobject *));
|
||||||
* 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);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif /* __BINDING_H__ */
|
#endif /* __BINDING_H__ */
|
||||||
|
|
|
@ -3683,11 +3683,32 @@ ReturnObject *interpretBindingStmtNode(StmtNode *node,
|
||||||
return (stmt->binding)(scope);
|
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
|
* A jump table for statements. The index of a function in the table is given
|
||||||
* by its its index in the enumerated StmtType type.
|
* by its its index in the enumerated StmtType type.
|
||||||
*/
|
*/
|
||||||
static ReturnObject *(*StmtJumpTable[15])(StmtNode *, ScopeObject *) = {
|
static ReturnObject *(*StmtJumpTable[16])(StmtNode *, ScopeObject *) = {
|
||||||
interpretCastStmtNode,
|
interpretCastStmtNode,
|
||||||
interpretPrintStmtNode,
|
interpretPrintStmtNode,
|
||||||
interpretInputStmtNode,
|
interpretInputStmtNode,
|
||||||
|
@ -3702,7 +3723,8 @@ static ReturnObject *(*StmtJumpTable[15])(StmtNode *, ScopeObject *) = {
|
||||||
interpretFuncDefStmtNode,
|
interpretFuncDefStmtNode,
|
||||||
interpretExprStmtNode,
|
interpretExprStmtNode,
|
||||||
interpretAltArrayDefStmtNode,
|
interpretAltArrayDefStmtNode,
|
||||||
interpretBindingStmtNode };
|
interpretBindingStmtNode,
|
||||||
|
interpretImportStmtNode };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interprets a statement.
|
* Interprets a statement.
|
||||||
|
@ -3798,10 +3820,7 @@ int interpretMainNode(MainNode *main)
|
||||||
{
|
{
|
||||||
ReturnObject *ret = NULL;
|
ReturnObject *ret = NULL;
|
||||||
if (!main) return 1;
|
if (!main) return 1;
|
||||||
ScopeObject *libs = createScopeObject(NULL);
|
ret = interpretBlockNode(main->block, NULL);
|
||||||
if (!libs) return 1;
|
|
||||||
loadBinding(libs);
|
|
||||||
ret = interpretBlockNode(main->block, libs);
|
|
||||||
if (!ret) return 1;
|
if (!ret) return 1;
|
||||||
deleteReturnObject(ret);
|
deleteReturnObject(ret);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -260,6 +260,8 @@ ReturnObject *interpretDeallocationStmtNode(StmtNode *, ScopeObject *);
|
||||||
ReturnObject *interpretFuncDefStmtNode(StmtNode *, ScopeObject *);
|
ReturnObject *interpretFuncDefStmtNode(StmtNode *, ScopeObject *);
|
||||||
ReturnObject *interpretExprStmtNode(StmtNode *, ScopeObject *);
|
ReturnObject *interpretExprStmtNode(StmtNode *, ScopeObject *);
|
||||||
ReturnObject *interpretAltArrayDefStmtNode(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;
|
start += 2;
|
||||||
continue;
|
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 */
|
/* Skip over leading whitespace */
|
||||||
while (isspace(*start)) {
|
while (isspace(*start)) {
|
||||||
unsigned int newline = 0;
|
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])
|
if (start[len] && !isspace(start[len])
|
||||||
&& *(start + len) != ','
|
&& *(start + len) != ','
|
||||||
&& *(start + len) != '!'
|
&& *(start + len) != '!'
|
||||||
|
&& *(start + len) != '?'
|
||||||
&& strncmp(start + len, "'Z", 2)
|
&& strncmp(start + len, "'Z", 2)
|
||||||
&& strncmp(start + len, "...", 3)
|
&& strncmp(start + len, "...", 3)
|
||||||
&& strncmp(start + len, "\xE2\x80\xA6", 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])
|
while (start[len] && !isspace(start[len])
|
||||||
&& *(start + len) != ','
|
&& *(start + len) != ','
|
||||||
&& *(start + len) != '!'
|
&& *(start + len) != '!'
|
||||||
|
&& *(start + len) != '?'
|
||||||
&& strncmp(start + len, "'Z", 2)
|
&& strncmp(start + len, "'Z", 2)
|
||||||
&& strncmp(start + len, "...", 3)
|
&& strncmp(start + len, "...", 3)
|
||||||
&& strncmp(start + len, "\xE2\x80\xA6", 3))
|
&& strncmp(start + len, "\xE2\x80\xA6", 3))
|
||||||
|
|
118
parser.c
118
parser.c
|
@ -514,6 +514,16 @@ void deleteStmtNode(StmtNode *node)
|
||||||
deleteAltArrayDefStmtNode(stmt);
|
deleteAltArrayDefStmtNode(stmt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ST_BINDING: {
|
||||||
|
BindingStmtNode *stmt = (BindingStmtNode *)node->stmt;
|
||||||
|
deleteBindingStmtNode(stmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ST_IMPORT: {
|
||||||
|
ImportStmtNode *stmt = (ImportStmtNode *)node->stmt;
|
||||||
|
deleteImportStmtNode(stmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
error(PR_UNKNOWN_STATEMENT_TYPE);
|
error(PR_UNKNOWN_STATEMENT_TYPE);
|
||||||
break;
|
break;
|
||||||
|
@ -1105,6 +1115,40 @@ void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *node)
|
||||||
free(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.
|
* Creates a binding statement.
|
||||||
*
|
*
|
||||||
|
@ -3905,6 +3949,76 @@ parseAltArrayDefStmtNodeAbort: /* Exception handling */
|
||||||
return NULL;
|
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.
|
* Parses tokens into a statement.
|
||||||
*
|
*
|
||||||
|
@ -4023,6 +4137,10 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
||||||
else if (peekToken(&tokens, TT_OHAIIM)) {
|
else if (peekToken(&tokens, TT_OHAIIM)) {
|
||||||
ret = parseAltArrayDefStmtNode(tokenp);
|
ret = parseAltArrayDefStmtNode(tokenp);
|
||||||
}
|
}
|
||||||
|
/* Library import statement */
|
||||||
|
else if (peekToken(&tokens, TT_CANHAS)) {
|
||||||
|
ret = parseImportStmtNode(tokenp);
|
||||||
|
}
|
||||||
/* Bare expression */
|
/* Bare expression */
|
||||||
else if ((expr = parseExprNode(&tokens))) {
|
else if ((expr = parseExprNode(&tokens))) {
|
||||||
int status;
|
int status;
|
||||||
|
|
21
parser.h
21
parser.h
|
@ -229,6 +229,7 @@ typedef enum {
|
||||||
ST_EXPR, /**< Expression statement. */
|
ST_EXPR, /**< Expression statement. */
|
||||||
ST_ALTARRAYDEF, /**< Function definition statement. */
|
ST_ALTARRAYDEF, /**< Function definition statement. */
|
||||||
ST_BINDING, /**< Binding to external library. */
|
ST_BINDING, /**< Binding to external library. */
|
||||||
|
ST_IMPORT, /**< Library import statement. */
|
||||||
} StmtType;
|
} StmtType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -365,6 +366,13 @@ typedef struct {
|
||||||
IdentifierNode *parent; /**< An optional inherited array. */
|
IdentifierNode *parent; /**< An optional inherited array. */
|
||||||
} AltArrayDefStmtNode;
|
} 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.
|
* Stores a binding to a native function.
|
||||||
*/
|
*/
|
||||||
|
@ -726,6 +734,16 @@ AltArrayDefStmtNode *createAltArrayDefStmtNode(IdentifierNode *, BlockNode *, Id
|
||||||
void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *);
|
void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *);
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name ImportStmtNode modifiers
|
||||||
|
*
|
||||||
|
* Functions for creating and deleting ImportStmtNodes.
|
||||||
|
*/
|
||||||
|
/**@{*/
|
||||||
|
ImportStmtNode *createImportStmtNode(IdentifierNode *);
|
||||||
|
void deleteImportStmtNode(ImportStmtNode *);
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \name BindingStmtNode modifiers
|
* \name BindingStmtNode modifiers
|
||||||
*
|
*
|
||||||
|
@ -734,7 +752,7 @@ void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *);
|
||||||
/**@{*/
|
/**@{*/
|
||||||
struct returnobject;
|
struct returnobject;
|
||||||
struct scopeobject;
|
struct scopeobject;
|
||||||
BindingStmtNode *createBindingStmtNode(struct returnobject *(*binding)(struct scopeobject *));
|
BindingStmtNode *createBindingStmtNode(struct returnobject *(*)(struct scopeobject *));
|
||||||
void deleteBindingStmtNode(BindingStmtNode *);
|
void deleteBindingStmtNode(BindingStmtNode *);
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
|
@ -823,6 +841,7 @@ StmtNode *parseLoopStmtNode(Token ***);
|
||||||
StmtNode *parseDeallocationStmtNode(Token ***);
|
StmtNode *parseDeallocationStmtNode(Token ***);
|
||||||
StmtNode *parseFuncDefStmtNode(Token ***);
|
StmtNode *parseFuncDefStmtNode(Token ***);
|
||||||
StmtNode *parseAltArrayDefStmtNode(Token ***);
|
StmtNode *parseAltArrayDefStmtNode(Token ***);
|
||||||
|
StmtNode *parseImportStmtNode(Token ***);
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -319,15 +319,6 @@ Token **tokenizeLexemes(LexemeList *list)
|
||||||
token = createToken(TT_BOOLEAN, "WIN", fname, line);
|
token = createToken(TT_BOOLEAN, "WIN", fname, line);
|
||||||
token->data.i = 1;
|
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 */
|
/* Newline */
|
||||||
/* Note that the spec is unclear as to whether a command *must*
|
/* Note that the spec is unclear as to whether a command *must*
|
||||||
* follow a comma. For now, we let commas end a line. */
|
* follow a comma. For now, we let commas end a line. */
|
||||||
|
|
|
@ -104,6 +104,8 @@ typedef enum {
|
||||||
TT_OHAIIM, /**< Alternate array declaration. */
|
TT_OHAIIM, /**< Alternate array declaration. */
|
||||||
TT_IMLIEK, /**< Alternate inherited object declaration. */
|
TT_IMLIEK, /**< Alternate inherited object declaration. */
|
||||||
TT_KTHX, /**< End of alternate array 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! */
|
TT_ENDOFTOKENS /**< Sentinel end of this enum -- don't move it! */
|
||||||
} TokenType;
|
} TokenType;
|
||||||
|
@ -181,6 +183,8 @@ static const char *keywords[] = {
|
||||||
"O HAI IM", /* TT_OHAIIM */
|
"O HAI IM", /* TT_OHAIIM */
|
||||||
"IM LIEK", /* TT_IMLIEK */
|
"IM LIEK", /* TT_IMLIEK */
|
||||||
"KTHX", /* TT_KTHX */
|
"KTHX", /* TT_KTHX */
|
||||||
|
"CAN HAS", /* TT_CANHAS */
|
||||||
|
"?", /* TT_QUESTION */
|
||||||
"" /* TT_ENDOFTOKENS */
|
"" /* TT_ENDOFTOKENS */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue