Added new functions, stored as values; updated EBNF

This commit is contained in:
Justin J. Meza 2010-11-16 00:25:51 -05:00
parent 35963b63b9
commit a90bf070f0
18 changed files with 397 additions and 493 deletions

View File

@ -108,6 +108,24 @@ ValueObject *createStringValueObject(char *data) /**< [in] The string data to st
return p;
}
/** Creates a function type ValueObject structure.
*
* \return A pointer to a function type ValueObject structure with definition \a data.
*
* \retval NULL malloc was unable to allocate memory. */
ValueObject *createFunctionValueObject(FuncDefStmtNode *data) /**< [in] The function definition to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
if (!p) {
perror("malloc");
return NULL;
}
p->type = VT_FUNC;
p->data.fn = data;
p->semaphore = 1;
return p;
}
/** Copies a ValueObject structure.
*
* \note What this function actually does is increment a semaphore in \a value
@ -167,6 +185,7 @@ void deleteValueObject(ValueObject *value) /**< [in,out] A pointer to the ValueO
P(value);
if (!value->semaphore) {
if (value->type == VT_STRING) free(value->data.s);
/* FuncDefStmtNode structures get freed with the parse tree */
free(value);
}
}
@ -1131,12 +1150,27 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
FuncCallExprNode *expr = (FuncCallExprNode *)node->expr;
unsigned int n;
ScopeObject *outer = createScopeObject(scope);
ValueObject *def = NULL;
ReturnObject *retval = NULL;
ValueObject *ret = NULL;
if (!outer) return NULL;
for (n = 0; n < expr->def->args->num; n++) {
def = getScopeValue(scope, expr->name);
if (!def || def->type != VT_FUNC) {
IdentifierNode *id = (IdentifierNode *)(expr->name);
fprintf(stderr, "%s:%d: undefined function at: %s\n", id->fname, id->line, id->image);
deleteScopeObject(outer);
return NULL;
}
/* Check for correct supplied arity */
if (getFunction(def)->args->num != expr->args->num) {
IdentifierNode *id = (IdentifierNode *)(expr->name);
fprintf(stderr, "%s:%d: incorrect number of arguments supplied to: %s\n", id->fname, id->line, id->image);
deleteScopeObject(outer);
return NULL;
}
for (n = 0; n < getFunction(def)->args->num; n++) {
ValueObject *val = NULL;
if (!createScopeValue(outer, expr->def->args->ids[n])) {
if (!createScopeValue(outer, getFunction(def)->args->ids[n])) {
deleteScopeObject(outer);
return NULL;
}
@ -1144,7 +1178,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
deleteScopeObject(outer);
return NULL;
}
if (!updateScopeValue(outer, expr->def->args->ids[n], val)) {
if (!updateScopeValue(outer, getFunction(def)->args->ids[n], val)) {
deleteScopeObject(outer);
deleteValueObject(val);
return NULL;
@ -1154,7 +1188,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
* here because we want to have access to the function's ScopeObject
* as we may need to retrieve the implicit variable in the case of
* a default return. */
if (!(retval = interpretStmtNodeList(expr->def->body->stmts, outer))) {
if (!(retval = interpretStmtNodeList(getFunction(def)->body->stmts, outer))) {
deleteScopeObject(outer);
return NULL;
}
@ -2522,7 +2556,7 @@ static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = {
/** Interprets the contents of an ExprNode structure.
*
* \pre \a node was created by parseExprNode(Token ***, FunctionTable *).
* \pre \a node was created by parseExprNode(Token ***).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -3252,9 +3286,24 @@ ReturnObject *interpretDeallocationStmtNode(StmtNode *node, /**< [in] A poin
ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see note). */
ScopeObject *scope) /**< Not used (see note). */
{
/* Skip over this; we have already parsed and stored it */
node = NULL;
scope = NULL;
/* Add the function to the current scope */
FuncDefStmtNode *stmt = (FuncDefStmtNode *)node->stmt;
ValueObject *init = NULL;
if (getLocalScopeValue(scope, stmt->name)) {
IdentifierNode *id = (IdentifierNode *)(stmt->name);
fprintf(stderr, "%s:%d: function name already used by existing variable at: %s\n", id->fname, id->line, id->image);
return NULL;
}
init = createFunctionValueObject(stmt);
if (!init) return NULL;
if (!createScopeValue(scope, stmt->name)) {
deleteValueObject(init);
return NULL;
}
if (!updateScopeValue(scope, stmt->name, init)) {
deleteValueObject(init);
return NULL;
}
return createReturnObject(RT_DEFAULT, NULL);
}
@ -3312,7 +3361,7 @@ static ReturnObject *(*StmtJumpTable[13])(StmtNode *, ScopeObject *) = {
/** Interprets the contents of a StmtNode structure.
*
* \pre \a node was created by parseStmtNode(Token ***, FunctionTable *).
* \pre \a node was created by parseStmtNode(Token ***).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -3371,7 +3420,7 @@ ReturnObject *interpretStmtNodeList(StmtNodeList *list, /**< [in] A pointer to t
/** Interprets the contents of a BlockNode structure.
*
* \pre \a node was created by parseBlockNode(Token ***, FunctionTable *).
* \pre \a node was created by parseBlockNode(Token ***).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -3398,7 +3447,7 @@ ReturnObject *interpretBlockNode(BlockNode *node, /**< [in] A pointer to a Bl
/** Interprets the contents of a MainNode structure.
*
* \pre \a node was created by parseMainNode(Token **, FunctionTable *).
* \pre \a node was created by parseMainNode(Token **).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).

View File

@ -25,6 +25,8 @@
#define getFloat(value) (value->data.f)
/** Gets the string data associated with a ValueObject structure. */
#define getString(value) (value->data.s)
/** Gets the function definition associated with a ValueObject structure. */
#define getFunction(value) (value->data.fn)
/** Denotes the type of a value. */
typedef enum {
@ -32,14 +34,16 @@ typedef enum {
VT_FLOAT, /**< A floating point decimal value. */
VT_BOOLEAN, /**< A true/false value. */
VT_STRING, /**< A character string value. */
VT_NIL /**< Represents no value. */
VT_NIL, /**< Represents no value. */
VT_FUNC /**< A function. */
} ValueType;
/** Stores the data associated with a ValueObject structure. */
typedef union {
int i; /**< Integer data. */
float f; /**< Floating point data. */
char *s; /**< Character string data. */
int i; /**< Integer data. */
float f; /**< Floating point data. */
char *s; /**< Character string data. */
FuncDefStmtNode *fn; /**< Function definition. */
} ValueData;
/** Increments the semaphore of a ValueObject structure. */
@ -94,6 +98,7 @@ ValueObject *createBooleanValueObject(int);
ValueObject *createIntegerValueObject(int);
ValueObject *createFloatValueObject(float);
ValueObject *createStringValueObject(char *);
ValueObject *createFunctionValueObject(FuncDefStmtNode *);
ValueObject *copyValueObject(ValueObject *);
void deleteValueObject(ValueObject *);
ReturnObject *createReturnObject(ReturnType, ValueObject *);

9
main.c
View File

@ -134,7 +134,6 @@ int main(int argc, char **argv)
char *buffer = NULL;
LexemeList *lexemes = NULL;
Token **tokens = NULL;
FunctionTable *functab = NULL;
MainNode *node = NULL;
char *fname = NULL;
FILE *file = NULL;
@ -166,7 +165,6 @@ int main(int argc, char **argv)
buffer = fname = NULL;
lexemes = NULL;
tokens = NULL;
functab = NULL;
node = NULL;
file = NULL;
@ -224,12 +222,7 @@ int main(int argc, char **argv)
return 1;
}
deleteLexemeList(lexemes);
if (!(functab = setupFunctionTable(tokens))) {
deleteFunctionTable(functab);
return 1;
}
if (!(node = parseMainNode(tokens, functab))) {
deleteFunctionTable(functab);
if (!(node = parseMainNode(tokens))) {
deleteTokens(tokens);
return 1;
}

637
parser.c
View File

@ -16,16 +16,13 @@ void debug(const char *info)
/** Creates a MainNode structure.
*
* \pre \a block was created by createBlockNode(StmtNodeList *).
* \pre \a functab was created by createFunctionTable(void) and contains
* items added by addFuncDefStmtNode(FunctionTable *, FuncDefStmtNode *).
*
* \return A pointer to a MainNode structure with the desired properties.
*
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteMainNode(MainNode *) */
MainNode *createMainNode(BlockNode *block, /**< [in] A pointer to the block of code to execute first. */
FunctionTable *functab) /**< [in] A pointer to the function table associated with this block of code. */
MainNode *createMainNode(BlockNode *block) /**< [in] A pointer to the block of code to execute first. */
{
MainNode *p = malloc(sizeof(MainNode));
if (!p) {
@ -33,23 +30,21 @@ MainNode *createMainNode(BlockNode *block, /**< [in] A pointer to the bloc
return NULL;
}
p->block = block;
p->functab = functab;
return p;
}
/** Deletes a MainNode structure.
*
* \pre \a node was created by createMainNode(BlockNode *, FunctionTable *).
* \pre \a node was created by createMainNode(BlockNode *).
*
* \post The memory at \a node and any of its associated members will be
* freed.
*
* \see createMainNode(BlockNode *, FunctionTable *) */
* \see createMainNode(BlockNode *) */
void deleteMainNode(MainNode *node) /**< [in,out] A pointer to the MainNode structure to be deleted. */
{
if (!node) return;
deleteBlockNode(node->block);
deleteFunctionTable(node->functab);
free(node);
}
@ -1210,9 +1205,10 @@ void deleteCastExprNode(CastExprNode *node) /**< [in,out] A pointer to the CastE
/** Creates a FuncCallExprNode structure.
*
* \pre \a def was created by createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *).
* \pre \a args was created by createExprNodeList(void) and contains items
* added by addExprNode(ExprNodeList *, ExprNode *).
* \pre \a scope was created by createIdentifierNode(char *).
* \pre \a name was created by createIdentifierNode(char *).
* \pre \a args was created by createIdentifierNodeList(void) and contains
* items added by addIdentifierNode(IdentifierNodeList *, IdentifierNode *).
*
* \return A pointer to a FuncCallExprNode structure with the desired
* properties.
@ -1220,30 +1216,34 @@ void deleteCastExprNode(CastExprNode *node) /**< [in,out] A pointer to the CastE
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteFuncCallExprNode(FuncCallExprNode *) */
FuncCallExprNode *createFuncCallExprNode(FuncDefStmtNode *def, /**< [in] A pointer to the function definition to call. */
ExprNodeList *args) /**< [in] A pointer to an ExprNodeList structure of arguments to be supplied to the function defined by \a def. */
FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope, /**< [in] A pointer to the scope the function is defined in. */
IdentifierNode *name, /**< [in] A pointer to the name of the function. */
ExprNodeList *args) /**< [in] A pointer to a list of ExprNode structure arguments supplied to the function definition. */
{
FuncCallExprNode *p = malloc(sizeof(FuncCallExprNode));
if (!p) {
perror("malloc");
return NULL;
}
p->def = def;
p->scope = scope;
p->name = name;
p->args = args;
return p;
}
/** Deletes a FuncCallExprNode structure.
*
* \pre \a node was created by createFuncCallExprNode(FuncDefStmtNode *, ExprNodeList *).
* \pre \a node was created by createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *).
*
* \post The memory at \a node and any of its associated members will be
* freed.
*
* \see createFuncCallExprNode(FuncDefStmtNode *, ExprNodeList *) */
* \see createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *) */
void deleteFuncCallExprNode(FuncCallExprNode *node) /**< [in,out] A pointer to the FuncCallExprNode structure to be deleted. */
{
if (!node) return;
deleteIdentifierNode(node->scope);
deleteIdentifierNode(node->name);
deleteExprNodeList(node->args);
free(node);
}
@ -1286,92 +1286,6 @@ void deleteOpExprNode(OpExprNode *node) /**< [in,out] A pointer to the OpExprNod
free(node);
}
/** Creates a FunctionTable structure.
*
* \return A pointer to a FunctionTable structure with no elements.
*
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteFunctionTable(FunctionTable *) */
FunctionTable *createFunctionTable(void)
{
FunctionTable *p = malloc(sizeof(FunctionTable));
if (!p) {
perror("malloc");
return NULL;
}
p->num = 0;
p->funcs = NULL;
return p;
}
/** Adds a FuncDefStmtNode to a FunctionTable structure.
*
* \pre \a table was created by createFunctionTable(void).
* \pre \a node was created by createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *).
*
* \post \a node will be added on to the end of \a table and the size of
* \a table will be updated accordingly.
*
* \return A pointer to the added FuncDefStmtNode structure (will be the same
* as \a node).
*
* \retval NULL realloc was unable to allocate memory.
*
* \see lookupFuncDefStmtNode(FunctionTable *, const char *) */
FuncDefStmtNode *addFuncDefStmtNode(FunctionTable *table, /**< [in,out] A pointer to the FunctionTable structure to add \a node to. */
FuncDefStmtNode *node) /**< [in] A pointer to the FuncDefStmtNode structure to add to \a table. */
{
unsigned int newsize = table->num + 1;
void *mem = realloc(table->funcs, sizeof(FuncDefStmtNode *) * newsize);
if (!mem) {
perror("realloc");
return NULL;
}
table->funcs = mem;
table->funcs[table->num] = node;
table->num = newsize;
return node;
}
/** Deletes a FunctionTable structure.
*
* \pre \a table was created by createFunctionTable(void).
*
* \post The memory of the function table and any of its associated members
* will be freed.
*
* \see createFunctionTable(void) */
void deleteFunctionTable(FunctionTable *table) /**< [in,out] A pointer to the FunctionTable structure to delete. */
{
if (!table) return;
/* Don't delete the FuncDefStmtNode structures because they will be
* deleted by deleteMainNode. */
free(table->funcs);
free(table);
}
/** Looks up a function definition by its name.
*
* \pre \a table was created by createFunctionTable(void) and contains items
* added by addFuncDefStmtNode(FunctionTable *, FuncDefStmtNode *).
*
* \return A pointer to the FuncDefStmtNode structure named \a name.
*
* \retval NULL No such FuncDefStmtNode structure exists.
*
* \see addFuncDefStmtNode(FunctionTable *, FuncDefStmtNode *) */
FuncDefStmtNode *lookupFuncDefStmtNode(FunctionTable *table, /**< [in] A pointer to the FunctionTable structure to search for \a name. */
const char *name) /**< [in] The name of the function to look up. */
{
unsigned int n;
for (n = 0; n < table->num; n++) {
FuncDefStmtNode *fun = (table->funcs)[n];
if (!strcmp(fun->name->image, name)) return fun;
}
return NULL;
}
/** Checks if the token pointed to by \a tokenp matches \a token and if it does,
* advances the token pointer to the next token in the array.
*
@ -1476,10 +1390,10 @@ void error(const char *info, /**< [in] The array of characters to print. */
*
* \see parseTypeNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
* \see parseExprNode(Token ***)
* \see parseStmtNode(Token ***)
* \see parseBlockNode(Token ***)
* \see parseMainNode(Token **) */
ConstantNode *parseConstantNode(Token ***tokenp)
{
Token **tokens = *tokenp;
@ -1556,10 +1470,10 @@ ConstantNode *parseConstantNode(Token ***tokenp)
*
* \see parseConstantNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
* \see parseExprNode(Token ***)
* \see parseStmtNode(Token ***)
* \see parseBlockNode(Token ***)
* \see parseMainNode(Token **) */
TypeNode *parseTypeNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
Token **tokens = *tokenp;
@ -1570,7 +1484,7 @@ TypeNode *parseTypeNode(Token ***tokenp) /**< [in,out] A pointer to the position
/* Nil */
if (acceptToken(&tokens, TT_NOOB)) {
#ifdef DEBUG
debug("CT_NI");
debug("CT_NIL");
#endif
ret = createTypeNode(CT_NIL);
if (!ret) return NULL;
@ -1629,10 +1543,10 @@ TypeNode *parseTypeNode(Token ***tokenp) /**< [in,out] A pointer to the position
*
* \see parseConstantNode(Token ***)
* \see parseTypeNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
* \see parseExprNode(Token ***)
* \see parseStmtNode(Token ***)
* \see parseBlockNode(Token ***)
* \see parseMainNode(Token **) */
IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
Token **tokens = *tokenp;
@ -1671,11 +1585,10 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to
* \see parseConstantNode(Token ***)
* \see parseTypeNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the position of the next token to parse. */
FunctionTable *functab) /**< [in,out] A pointer to the table of defined functions. */
* \see parseStmtNode(Token ***)
* \see parseBlockNode(Token ***)
* \see parseMainNode(Token **) */
ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
Token **tokens = *tokenp;
ExprNode *ret = NULL;
@ -1690,7 +1603,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
#ifdef DEBUG
debug("ET_CAST");
#endif
target = parseExprNode(&tokens, functab);
target = parseExprNode(&tokens);
if (!target) return NULL;
acceptToken(&tokens, TT_A);
newtype = parseTypeNode(&tokens);
@ -1734,53 +1647,76 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
return NULL;
}
}
/* Note that identifiers may refer to function calls and if so, must
* contain an appropriate number of arguments. */
else if (peekToken(&tokens, TT_IDENTIFIER)) {
FuncDefStmtNode *fun = NULL;
/* Function Call */
if ((fun = lookupFuncDefStmtNode(functab, (*tokens)->image))) {
FuncCallExprNode *node = NULL;
ExprNodeList *args = NULL;
unsigned int n;
acceptToken(&tokens, TT_IDENTIFIER); /* Will succeed, checked for this above */
/* Function call */
else if (nextToken(&tokens, TT_IZ)) {
IdentifierNode *scope = NULL;
IdentifierNode *name = NULL;
ExprNodeList *args = NULL;
FuncCallExprNode *node = NULL;
#ifdef DEBUG
debug("ET_FUNCCA");
debug("ET_FUNCCALL");
#endif
args = createExprNodeList();
for (n = 0; n < fun->args->num; n++) {
ExprNode *arg = parseExprNode(&tokens, functab);
scope = parseIdentifierNode(&tokens);
if (!scope) return NULL;
acceptToken(&tokens, TT_IZ); /* Will succeed, checked for this above */
name = parseIdentifierNode(&tokens);
if (!name) {
deleteIdentifierNode(scope);
return NULL;
}
args = createExprNodeList();
if (acceptToken(&tokens, TT_YR)) {
ExprNode *arg = parseExprNode(&tokens);
if (!arg) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
addExprNode(args, arg);
while (acceptToken(&tokens, TT_ANYR)) {
arg = parseExprNode(&tokens);
if (!arg) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
addExprNode(args, arg);
}
node = createFuncCallExprNode(fun, args);
if (!node) {
deleteExprNodeList(args);
return NULL;
}
ret = createExprNode(ET_FUNCCALL, node);
if (!ret) {
deleteExprNodeList(args);
deleteFuncCallExprNode(node);
return NULL;
}
}
/* Identifier */
else {
IdentifierNode *node = NULL;
if (!acceptToken(&tokens, TT_MKAY)) {
error("expected MKAY", tokens);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
node = createFuncCallExprNode(scope, name, args);
if (!node) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
ret = createExprNode(ET_FUNCCALL, node);
if (!ret) {
deleteFuncCallExprNode(node);
return NULL;
}
}
/* Identifier */
else if (peekToken(&tokens, TT_IDENTIFIER)) {
IdentifierNode *node = NULL;
#ifdef DEBUG
debug("ET_IDENTIFIER");
debug("ET_IDENTIFIER");
#endif
node = parseIdentifierNode(&tokens);
if (!node) return NULL;
ret = createExprNode(ET_IDENTIFIER, node);
if (!ret) {
deleteIdentifierNode(node);
return NULL;
}
node = parseIdentifierNode(&tokens);
if (!node) return NULL;
ret = createExprNode(ET_IDENTIFIER, node);
if (!ret) {
deleteIdentifierNode(node);
return NULL;
}
}
/* Binary operations */
@ -1878,7 +1814,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
}
args = createExprNodeList();
if (!args) return NULL;
arg = parseExprNode(&tokens, functab);
arg = parseExprNode(&tokens);
if (!arg) {
deleteExprNodeList(args);
return NULL;
@ -1889,7 +1825,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
return NULL;
}
acceptToken(&tokens, TT_AN);
arg = parseExprNode(&tokens, functab);
arg = parseExprNode(&tokens);
if (!arg) {
deleteExprNodeList(args);
return NULL;
@ -1935,7 +1871,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
if (!(args = createExprNodeList())) return NULL;
while (1) {
ExprNode *arg = NULL;
if (!(arg = parseExprNode(&tokens, functab))) {
if (!(arg = parseExprNode(&tokens))) {
deleteExprNodeList(args);
return NULL;
}
@ -1969,7 +1905,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
if (!(args = createExprNodeList())) return NULL;
while (1) {
ExprNode *arg = NULL;
if (!(arg = parseExprNode(&tokens, functab))) {
if (!(arg = parseExprNode(&tokens))) {
deleteExprNodeList(args);
return NULL;
}
@ -2000,7 +1936,7 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
debug("ET_OP (OP_NOT)");
#endif
if (!(args = createExprNodeList())) return NULL;
if (!(arg = parseExprNode(&tokens, functab))) {
if (!(arg = parseExprNode(&tokens))) {
deleteExprNodeList(args);
return NULL;
}
@ -2041,11 +1977,10 @@ ExprNode *parseExprNode(Token ***tokenp, /**< [in,out] A pointer to the p
* \see parseConstantNode(Token ***)
* \see parseTypeNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the position of the next token to parse. */
FunctionTable *functab) /**< [in,out] A pointer to the table of defined functions. */
* \see parseExprNode(Token ***)
* \see parseBlockNode(Token ***)
* \see parseMainNode(Token **) */
StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
Token **tokens = *tokenp;
StmtNode *ret = NULL;
@ -2098,7 +2033,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
if (!(args = createExprNodeList())) return NULL;
do {
ExprNode *arg = NULL;
if (!(arg = parseExprNode(&tokens, functab))) {
if (!(arg = parseExprNode(&tokens))) {
deleteExprNodeList(args);
return NULL;
}
@ -2164,7 +2099,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
deleteIdentifierNode(target);
return NULL;
}
expr = parseExprNode(&tokens, functab);
expr = parseExprNode(&tokens);
if (!expr) {
deleteIdentifierNode(target);
return NULL;
@ -2210,7 +2145,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
return NULL;
}
if (acceptToken(&tokens, TT_ITZ)) {
expr = parseExprNode(&tokens, functab);
expr = parseExprNode(&tokens);
if (!expr) {
deleteIdentifierNode(scope);
deleteIdentifierNode(target);
@ -2253,7 +2188,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
BlockNode *no = NULL;
IfThenElseStmtNode *stmt = NULL;
#ifdef DEBUG
debug("ST_CONDITIONA");
debug("ST_CONDITIONAL");
#endif
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of expression", tokens);
@ -2267,7 +2202,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
error("expected end of expression", tokens);
return NULL;
}
yes = parseBlockNode(&tokens, functab);
yes = parseBlockNode(&tokens);
if (!yes) return NULL;
guards = createExprNodeList();
if (!guards) {
@ -2283,7 +2218,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
while (acceptToken(&tokens, TT_MEBBE)) {
ExprNode *guard = NULL;
BlockNode *block = NULL;
guard = parseExprNode(&tokens, functab);
guard = parseExprNode(&tokens);
if (!guard) {
deleteBlockNode(yes);
deleteExprNodeList(guards);
@ -2304,7 +2239,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
deleteBlockNodeList(blocks);
return NULL;
}
block = parseBlockNode(&tokens, functab);
block = parseBlockNode(&tokens);
if (!block) {
deleteBlockNode(yes);
deleteExprNodeList(guards);
@ -2327,7 +2262,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
deleteBlockNodeList(blocks);
return NULL;
}
no = parseBlockNode(&tokens, functab);
no = parseBlockNode(&tokens);
if (!no) {
deleteBlockNode(yes);
deleteExprNodeList(guards);
@ -2446,7 +2381,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
deleteBlockNodeList(blocks);
return NULL;
}
block = parseBlockNode(&tokens, functab);
block = parseBlockNode(&tokens);
if (!block) {
deleteExprNodeList(guards);
deleteBlockNodeList(blocks);
@ -2465,7 +2400,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
deleteBlockNodeList(blocks);
return NULL;
}
def = parseBlockNode(&tokens, functab);
def = parseBlockNode(&tokens);
if (!def) {
deleteExprNodeList(guards);
deleteBlockNodeList(blocks);
@ -2517,7 +2452,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
#ifdef DEBUG
debug("ST_RETURN");
#endif
value = parseExprNode(&tokens, functab);
value = parseExprNode(&tokens);
if (!value) return NULL;
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of expression", tokens);
@ -2658,80 +2593,82 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
return NULL;
}
}
else if ((def = lookupFuncDefStmtNode(functab, (*tokens)->image))) {
tokens++;
if (!acceptToken(&tokens, TT_YR)) {
error("expected YR", tokens);
deleteIdentifierNode(name1);
else if (nextToken(&tokens, TT_IZ)) {
IdentifierNode *scope = NULL;
IdentifierNode *name = NULL;
ExprNodeList *args = NULL;
FuncCallExprNode *node = NULL;
ExprNode *ret = NULL;
ExprNode *arg = NULL;
IdentifierNode *temp = NULL;
#ifdef DEBUG
debug("ET_FUNCCALL");
#endif
scope = parseIdentifierNode(&tokens);
if (!scope) return NULL;
acceptToken(&tokens, TT_IZ); /* Will succeed, checked for this above */
name = parseIdentifierNode(&tokens);
if (!name) {
deleteIdentifierNode(scope);
return NULL;
}
args = createExprNodeList();
/* Check for unary function */
if (def->args->num == 1) {
IdentifierNode *varcopy = NULL;
ExprNode *arg = NULL;
ExprNodeList *args = NULL;
FuncCallExprNode *func = NULL;
#ifdef DEBUG
shiftout();
debug("ET_FUNCCA");
#endif
var = parseIdentifierNode(&tokens);
if (!var) {
deleteIdentifierNode(name1);
return NULL;
}
#ifdef DEBUG
shiftin();
#endif
varcopy = createIdentifierNode(var->image, var->fname, var->line);
if (!varcopy) {
deleteIdentifierNode(name1);
deleteIdentifierNode(var);
return NULL;
}
arg = createExprNode(ET_IDENTIFIER, varcopy);
if (!arg) {
deleteIdentifierNode(name1);
deleteIdentifierNode(var);
deleteIdentifierNode(varcopy);
return NULL;
}
args = createExprNodeList();
if (!args) {
deleteIdentifierNode(name1);
deleteIdentifierNode(var);
deleteExprNode(arg);
return NULL;
}
if (!addExprNode(args, arg)) {
deleteIdentifierNode(name1);
deleteIdentifierNode(var);
deleteExprNode(arg);
deleteExprNodeList(args);
return NULL;
}
func = createFuncCallExprNode(def, args);
if (!func) {
deleteIdentifierNode(name1);
deleteIdentifierNode(var);
deleteExprNodeList(args);
return NULL;
}
update = createExprNode(ET_FUNCCALL, func);
if (!update) {
deleteFuncCallExprNode(func);
return NULL;
}
}
else {
if (!acceptToken(&tokens, TT_YR)) {
error("expected unary function", tokens);
deleteIdentifierNode(name1);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
arg = parseExprNode(&tokens);
if (!arg) {
deleteIdentifierNode(name1);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
if (arg->type != ET_IDENTIFIER) {
error("expected identifier", tokens);
deleteExprNode(arg);
deleteIdentifierNode(name1);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
addExprNode(args, arg);
temp = (IdentifierNode *)(arg->expr);
/* Copy the identifier to make it the loop variable */
var = createIdentifierNode(temp->image, temp->fname, temp->line);
/* Check for unary function */
if (!acceptToken(&tokens, TT_MKAY)) {
error("expected MKAY", tokens);
deleteIdentifierNode(name1);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
node = createFuncCallExprNode(scope, name, args);
if (!node) {
deleteIdentifierNode(name1);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteExprNodeList(args);
return NULL;
}
update = createExprNode(ET_FUNCCALL, node);
if (!update) {
deleteFuncCallExprNode(node);
return NULL;
}
}
if (update) {
if (acceptToken(&tokens, TT_WILE)) {
guard = parseExprNode(&tokens, functab);
guard = parseExprNode(&tokens);
if (!guard) {
deleteIdentifierNode(name1);
deleteExprNode(update);
@ -2746,7 +2683,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
shiftout();
debug("ET_OP (OP_NOT)");
#endif
arg = parseExprNode(&tokens, functab);
arg = parseExprNode(&tokens);
if (!arg) {
deleteIdentifierNode(name1);
deleteExprNode(update);
@ -2792,7 +2729,7 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
if (guard) deleteExprNode(guard);
return NULL;
}
body = parseBlockNode(&tokens, functab);
body = parseBlockNode(&tokens);
if (!body) {
deleteIdentifierNode(name1);
if (update) deleteExprNode(update);
@ -2878,63 +2815,101 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
}
}
/* Function definition */
else if (acceptToken(&tokens, TT_HOWDUZ)) {
else if (acceptToken(&tokens, TT_HOWIZ)) {
IdentifierNode *scope = NULL;
IdentifierNode *name = NULL;
IdentifierNodeList *args = NULL;
BlockNode *body;
FuncDefStmtNode *proto = NULL;
#ifdef DEBUG
debug("ST_FUNCDEF");
#endif
/* Skip over the scope as it has already been parsed */
FuncDefStmtNode *stmt = NULL;
scope = parseIdentifierNode(&tokens);
if (!scope) return NULL;
deleteIdentifierNode(scope);
name = parseIdentifierNode(&tokens);
if (!name) return NULL;
/* Lookup function prototype to update it after parsing body */
proto = lookupFuncDefStmtNode(functab, name->image);
deleteIdentifierNode(name);
if (!proto) {
error("function prototype not found", tokens);
if (!name) {
deleteIdentifierNode(scope);
return NULL;
}
/* Skip over the arguments as they have already been parsed */
args = createIdentifierNodeList();
if (!args) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
}
if (acceptToken(&tokens, TT_YR)) {
IdentifierNode *arg = parseIdentifierNode(&tokens);
if (!arg) return NULL;
deleteIdentifierNode(arg);
if (!arg) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
return NULL;
}
if (!addIdentifierNode(args, arg)) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
deleteIdentifierNode(arg);
return NULL;
}
while (acceptToken(&tokens, TT_ANYR)) {
arg = parseIdentifierNode(&tokens);
if (!arg) return NULL;
deleteIdentifierNode(arg);
if (!arg) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
return NULL;
}
if (!addIdentifierNode(args, arg)) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
deleteIdentifierNode(arg);
return NULL;
}
}
}
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of statement", tokens);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
return NULL;
}
body = parseBlockNode(&tokens);
if (!body) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
return NULL;
}
body = parseBlockNode(&tokens, functab);
if (!body) return NULL;
if (!acceptToken(&tokens, TT_IFUSAYSO)) {
error("expected IF YOU SAY SO", tokens);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
deleteBlockNode(body);
return NULL;
}
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of statement", tokens);
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
deleteBlockNode(body);
return NULL;
}
/* Update the function body */
proto->body = body;
ret = createStmtNode(ST_FUNCDEF, proto);
stmt = createFuncDefStmtNode(scope, name, args, body);
if (!stmt) {
deleteIdentifierNode(scope);
deleteIdentifierNode(name);
deleteIdentifierNodeList(args);
deleteBlockNode(body);
return NULL;
}
ret = createStmtNode(ST_FUNCDEF, stmt);
if (!ret) {
deleteStmtNode(ret);
deleteFuncDefStmtNode(stmt);
}
}
/* Expression Evaluation */
else if ((expr = parseExprNode(&tokens, functab))) {
/* Expression evaluation */
else if ((expr = parseExprNode(&tokens))) {
#ifdef DEBUG
debug("ST_EXPR");
#endif
@ -2968,11 +2943,10 @@ StmtNode *parseStmtNode(Token ***tokenp, /**< [in,out] A pointer to the p
* \see parseConstantNode(Token ***)
* \see parseTypeNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseMainNode(Token **, FunctionTable *) */
BlockNode *parseBlockNode(Token ***tokenp, /**< [in,out] A pointer to the position of the next token to parse. */
FunctionTable *functab) /**< [in,out] A pointer to the table of defined functions. */
* \see parseExprNode(Token ***)
* \see parseStmtNode(Token ***)
* \see parseMainNode(Token **) */
BlockNode *parseBlockNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
Token **tokens = *tokenp;
StmtNodeList *stmts = NULL;
@ -2989,7 +2963,7 @@ BlockNode *parseBlockNode(Token ***tokenp, /**< [in,out] A pointer to the
&& !peekToken(&tokens, TT_MEBBE) && !peekToken(&tokens, TT_OMG)
&& !peekToken(&tokens, TT_OMGWTF) && !peekToken(&tokens, TT_IMOUTTAYR)
&& !peekToken(&tokens, TT_IFUSAYSO)) {
StmtNode *s = parseStmtNode(&tokens, functab);
StmtNode *s = parseStmtNode(&tokens);
if (!s) {
deleteStmtNodeList(stmts);
return NULL;
@ -3014,7 +2988,6 @@ BlockNode *parseBlockNode(Token ***tokenp, /**< [in,out] A pointer to the
* interpreter.
*
* \pre \a tokens was created by tokenizeLexemes(Lexeme **).
* \pre \a functab was created by setupFunctionTable(Token **).
*
* \return A pointer to the generated MainNode structure.
*
@ -3023,11 +2996,10 @@ BlockNode *parseBlockNode(Token ***tokenp, /**< [in,out] A pointer to the
* \see parseConstantNode(Token ***)
* \see parseTypeNode(Token ***)
* \see parseIdentifierNode(Token ***)
* \see parseExprNode(Token ***, FunctionTable *)
* \see parseStmtNode(Token ***, FunctionTable *)
* \see parseBlockNode(Token ***, FunctionTable *) */
MainNode *parseMainNode(Token **tokens, /**< [in] A pointer to an array of tokens to parse. */
FunctionTable *functab) /**< [in,out] A pointer to a table of function prototypes. */
* \see parseExprNode(Token ***)
* \see parseStmtNode(Token ***)
* \see parseBlockNode(Token ***) */
MainNode *parseMainNode(Token **tokens) /**< [in] A pointer to an array of tokens to parse. */
{
if (acceptToken(&tokens, TT_HAI)) {
BlockNode *block = NULL;
@ -3040,14 +3012,14 @@ MainNode *parseMainNode(Token **tokens, /**< [in] A pointer to an array
error("expected end of statement", tokens);
return NULL;
}
block = parseBlockNode(&tokens, functab);
block = parseBlockNode(&tokens);
if (!block) return NULL;
if (!acceptToken(&tokens, TT_KTHXBYE)) {
error("expected KTHXBYE", tokens);
deleteBlockNode(block);
return NULL;
}
_main = createMainNode(block, functab);
_main = createMainNode(block);
if (!_main) {
deleteBlockNode(block);
return NULL;
@ -3059,100 +3031,3 @@ MainNode *parseMainNode(Token **tokens, /**< [in] A pointer to an array
return NULL;
}
}
/** Sets up a FunctionTable structure filled with the prototypes of all declared
* functions. This structure is then passed as an argument to parseMainNode(Token **, FunctionTable *)
* so that functions may be called before their definition as well as recursively.
*
* \pre \a tokens was created by tokenizeLexemes(Lexeme **).
*
* \return A pointer to the generated FunctionTable structure.
*
* \retval NULL An error occurred during setup. */
FunctionTable *setupFunctionTable(Token **tokens) /**< [in] A pointer to an array of tokens to scan for function prototypes. */
{
FunctionTable *p = createFunctionTable();
#ifdef DEBUG
fprintf(stderr, "Setting up function table...\n");
#endif
while (*tokens) {
if (acceptToken(&tokens, TT_HOWDUZ)) {
IdentifierNode *scope = NULL;
IdentifierNode *name = NULL;
IdentifierNodeList *args = NULL;
FuncDefStmtNode *stmt = NULL;
scope = parseIdentifierNode(&tokens);
if (!scope) {
deleteFunctionTable(p);
return NULL;
}
name = parseIdentifierNode(&tokens);
if (!name) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
return NULL;
}
args = createIdentifierNodeList();
if (!args) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
}
if (acceptToken(&tokens, TT_YR)) {
IdentifierNode *arg = parseIdentifierNode(&tokens);
if (!arg) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
return NULL;
}
if (!addIdentifierNode(args, arg)) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
deleteIdentifierNode(arg);
return NULL;
}
while (acceptToken(&tokens, TT_ANYR)) {
arg = parseIdentifierNode(&tokens);
if (!arg) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
return NULL;
}
if (!addIdentifierNode(args, arg)) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
deleteIdentifierNode(arg);
return NULL;
}
}
}
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of statement", tokens);
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
return NULL;
}
stmt = createFuncDefStmtNode(scope, name, args, NULL);
if (!stmt) {
deleteFunctionTable(p);
deleteIdentifierNode(scope);
deleteIdentifierNodeList(args);
return NULL;
}
if (!addFuncDefStmtNode(p, stmt)) {
deleteFunctionTable(p);
deleteFuncDefStmtNode(stmt);
return NULL;
}
}
else tokens++;
}
#ifdef DEBUG
fprintf(stderr, "Done setting up function table...\n");
#endif
return p;
}

View File

@ -33,7 +33,7 @@
* \par
* BlockNode ::= StmtNode *
*
* \section stmtebnf Statements
* \section typesebnf Types
*
* These production rules specify some general types of parse structures.
*
@ -57,7 +57,7 @@
* CastStmtNode ::= IdentifierNode \c TT_ISNOWA TypeNode \c TT_NEWLINE
*
* \par
* PrintStmtNode ::= \c TT_VISIBLE ExprNodeList \c [ \c TT_BANG ] TT_NEWLINE
* PrintStmtNode ::= \c TT_VISIBLE ExprNodeList \c TT_BANG ? TT_NEWLINE
*
* \par
* InputStmtNode ::= \c TT_GIMMEH IdentifierNode TT_NEWLINE
@ -66,13 +66,13 @@
* AssignmentStmtNode ::= IdentifierNode \c TT_R ExprNode \c TT_NEWLINE
*
* \par
* DeclarationStmtNode ::= IdentifierNode \c TT_HASA IdentifierNode [ Initialization ] \c TT_NEWLINE
* DeclarationStmtNode ::= IdentifierNode \c TT_HASA IdentifierNode Initialization ? \c TT_NEWLINE
*
* \par
* Initialization ::= \c TT_ITZ ExprNode | \c TT_ITZA TypeNode
*
* \par
* IfThenElseStmtNode ::= \c TT_ORLY \c TT_NEWLINE \c TT_YARLY \c TT_NEWLINE BlockNode ElseIf * [ Else ] \c TT_OIC \c TT_NEWLINE
* IfThenElseStmtNode ::= \c TT_ORLY \c TT_NEWLINE \c TT_YARLY \c TT_NEWLINE BlockNode ElseIf * Else ? \c TT_OIC \c TT_NEWLINE
*
* \par
* ElseIf ::= \c TT_MEBBE ExprNode \c TT_NEWLINE BlockNode
@ -81,7 +81,7 @@
* Else ::= \c TT_NOWAI \c TT_NEWLINE BlockNode
*
* \par
* SwitchStmtNode ::= \c TT_WTF \c TT_NEWLINE Case + [ DefaultCase ] \c TT_OIC \c TT_NEWLINE
* SwitchStmtNode ::= \c TT_WTF \c TT_NEWLINE Case + DefaultCase ? \c TT_OIC \c TT_NEWLINE
*
* \par
* Case ::= \c TT_OMG ExprNode \c TT_NEWLINE BlockNode
@ -96,7 +96,7 @@
* ReturnStmtNode ::= \c TT_FOUNDYR ExprNode \c TT_NEWLINE
*
* \par
* LoopStmtNode ::= \c TT_IMINYR IdentifierNode [ LoopUpdate ] [ LoopGuard ] \c TT_NEWLINE \c TT_IMOUTTAYR IdentifierNode \c TT_NEWLINE
* LoopStmtNode ::= \c TT_IMINYR IdentifierNode LoopUpdate ? LoopGuard ? \c TT_NEWLINE BlockNode \c TT_IMOUTTAYR IdentifierNode \c TT_NEWLINE
*
* \par
* LoopUpdate ::= LoopUpdateOp \c TT_YR IdentifierNode
@ -111,16 +111,16 @@
* LoopGuard ::= \c TT_TIL ExprNode | \c TT_WILE ExprNode
*
* \par
* \c TT_RNOOB
* DeallocationStmtNode ::= IdentifierNode \c TT_RNOOB
*
* \par
* FuncDefStmtNode ::= \c TT_HOWDUZ IdentifierNode IdentifierNode [ FunctionDefArgs ] \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE
* FuncDefStmtNode ::= \c TT_HOWIZ IdentifierNode IdentifierNode FunctionArgs ? \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE
*
* \par
* FunctionDefArgs ::= \c TT_YR IdentifierNode FunctionDefArg *
* FunctionArgs ::= \c TT_YR IdentifierNode FunctionArg *
*
* \par
* FunctionDefArg ::= \c TT_ANYR IdentifierNode
* FunctionArg ::= \c TT_ANYR IdentifierNode
*
* \par
* ExprStmt ::= ExprNode \c TT_NEWLINE
@ -136,7 +136,7 @@
* CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode
*
* \par
* FuncCallExprNode ::= IdentifierNode
* FuncCallExprNode ::= IdentifierNode \c TT_IZ IdentifierNode FunctionArgs ? TT_MKAY
*
* \par
* OpExprNode ::= UnaryOp | BinaryOp | NaryOp
@ -148,7 +148,7 @@
* UnaryOpType ::= \c TT_NOT
*
* \par
* BinaryOp ::= BinaryOpType ExprNode [ \c TT_AN ] ExprNode
* BinaryOp ::= BinaryOpType ExprNode \c TT_AN ? ExprNode
*
* \par
* BinaryOpType ::= \c TT_SUMOF | \c TT_DIFFOF | \c TT_PRODUKTOF | \c TT_QUOSHUNTOF | \c TT_MODOF | \c BIGGROF | \c SMALLROF | \c TT_BOTHOF | \c TT_EITHEROF | \c TT_WONOF
@ -163,7 +163,7 @@
* NaryOpArgs ::= ExprNode NaryOpArg +
*
* \par
* NaryOpArg ::= [ \c TT_AN ] ExprNode
* NaryOpArg ::= \c TT_AN ? ExprNode
*
* \par
* ImplicitVariable ::= \c TT_IT */
@ -330,15 +330,6 @@ typedef struct {
BlockNode *body; /**< A pointer to the block of code defined by the function. */
} FuncDefStmtNode;
/** Stores the contents of the function table. The function table contains the
* definitions of all declared functions. It is used for making sure function
* calls provide a valid arity, typechecking, however, is performed at
* runtime. */
typedef struct {
unsigned int num; /**< The number of declared functions. */
FuncDefStmtNode **funcs; /**< A pointer to an array of declared functions. */
} FunctionTable;
/** Stores the main block of code a program executes. This structure could be
* accomplished using only a BlockNode instead, but its logical importance to
* program control flow (namely, it is the first portion of code executed)
@ -348,7 +339,6 @@ typedef struct {
* \see deleteMainNode(MainNode *) */
typedef struct {
BlockNode *block; /**< A pointer to the block of code to execute first. */
FunctionTable *functab; /**< A pointer to the function table associated with this block of code. */
} MainNode;
/** Stores a variable type.
@ -493,16 +483,12 @@ typedef struct {
* the return value of the function defined in \a def called with the arguments
* listed in \a args.
*
* \note \a args is not an ExprNodeList because its arity is known in advance
* (because a FuncDefStmtNode for it has presumably been created) and
* thus the benefit of an ExprNodeList (easy syntax for adding new elements)
* would not be relevant.
*
* \see createFuncCallExprNode(FuncDefStmtNode *, ExprNodeList *)
* \see createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *)
* \see deleteFuncCallExprNode(FuncCallExprNode *) */
typedef struct {
FuncDefStmtNode *def; /**< A pointer to the function definition to call. */
ExprNodeList *args; /**< A pointer to a list of ExprNode structure arguments to be supplied to the function defined by \a def. */
IdentifierNode *scope; /**< A pointer to the scope the function is defined in. */
IdentifierNode *name; /**< A pointer to the name of the function. */
ExprNodeList *args; /**< A pointer to a list of ExprNode structure arguments to be supplied to the function. */
} FuncCallExprNode;
/** Denotes the type of operation an OpExprNode performs. */
@ -536,7 +522,7 @@ typedef struct {
ExprNodeList *args; /**< A pointer to the arguments to perform the operation on. */
} OpExprNode;
MainNode *createMainNode(BlockNode *, FunctionTable *);
MainNode *createMainNode(BlockNode *);
void deleteMainNode(MainNode *);
BlockNode *createBlockNode(StmtNodeList *);
@ -599,17 +585,12 @@ void deleteExprNodeList(ExprNodeList *);
CastExprNode *createCastExprNode(ExprNode *, TypeNode *);
void deleteCastExprNode(CastExprNode *);
FuncCallExprNode *createFuncCallExprNode(FuncDefStmtNode *, ExprNodeList *);
FuncCallExprNode *createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *);
void deleteFuncCallExprNode(FuncCallExprNode *);
OpExprNode *createOpExprNode(OpType, ExprNodeList *);
void deleteOpExprNode(OpExprNode *);
FunctionTable *createFunctionTable(void);
FuncDefStmtNode *addFuncDefStmtNode(FunctionTable *, FuncDefStmtNode *);
void deleteFunctionTable(FunctionTable *);
FuncDefStmtNode *lookupFuncDefStmtNode(FunctionTable *, const char *);
int acceptToken(Token ***, TokenType);
int peekToken(Token ***, TokenType);
int nextToken(Token ***, TokenType);
@ -619,11 +600,10 @@ void error(const char *, Token **);
ConstantNode *parseConstantNode(Token ***);
TypeNode *parseTypeNode(Token ***);
IdentifierNode *parseIdentifierNode(Token ***);
ExprNode *parseExprNode(Token ***, FunctionTable *);
StmtNode *parseStmtNode(Token ***, FunctionTable *);
BlockNode *parseBlockNode(Token ***, FunctionTable *);
MainNode *parseMainNode(Token **, FunctionTable *);
FunctionTable *setupFunctionTable(Token **);
ExprNode *parseExprNode(Token ***);
StmtNode *parseStmtNode(Token ***);
BlockNode *parseBlockNode(Token ***);
MainNode *parseMainNode(Token **);
ConstantNode *createBooleanConstantNode(int);
ConstantNode *createIntegerConstantNode(int);

View File

@ -1,9 +1,9 @@
HAI 1.3
HOW DUZ I plustwoin YR var
HOW IZ I plustwoin YR var
FOUND YR SUM OF var AN 2
IF U SAY SO
IM IN YR loop plustwoin YR var
IM IN YR loop I IZ plustwoin YR var MKAY
VISIBLE var
BOTH SAEM var AN 10
O RLY?

View File

@ -1,17 +1,17 @@
HAI 1.3
HOW DUZ I fun1
HOW IZ I fun1
VISIBLE "a"
IF U SAY SO
HOW DUZ I fun2 YR arg
HOW IZ I fun2 YR arg
VISIBLE arg
IF U SAY SO
HOW DUZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
HOW IZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
VISIBLE SMOOSH arg1 AN arg2 AN arg3 AN arg4 AN arg5 AN arg6 AN arg7 AN arg8 AN arg9 AN arg10 MKAY
IF U SAY SO
fun1
fun2 "b"
fun3 "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
I IZ fun1 MKAY
I IZ fun2 YR "b" MKAY
I IZ fun3 YR "c" AN YR "d" AN YR "e" AN YR "f" AN YR "g" AN YR "h" AN YR "i" AN YR "j" AN YR "k" AN YR "l" MKAY
KTHXBYE

View File

@ -1,7 +1,7 @@
HAI 1.3
HOW DUZ I fun YR a AN YR b AN YR c
HOW IZ I fun YR a AN YR b AN YR c
VISIBLE a AN b AN c
IF U SAY SO
fun 1 2
I IZ fun YR 1 AN YR 2 MKAY
KTHXBYE

View File

@ -1,6 +1,6 @@
HAI 1.3
HOW DUZ I fun
HOW IZ I fun
IF U SAY SO
fun
I IZ fun MKAY
KTHXBYE

View File

@ -1,17 +1,17 @@
HAI 1.3
HOW DUZ I fun1
HOW IZ I fun1
FOUND YR "a"
IF U SAY SO
HOW DUZ I fun2 YR arg
HOW IZ I fun2 YR arg
FOUND YR arg
IF U SAY SO
HOW DUZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
HOW IZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
FOUND YR SMOOSH arg1 AN arg2 AN arg3 AN arg4 AN arg5 AN arg6 AN arg7 AN arg8 AN arg9 AN arg10 MKAY
IF U SAY SO
VISIBLE fun1
VISIBLE fun2 "b"
VISIBLE fun3 "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
VISIBLE I IZ fun1 MKAY
VISIBLE I IZ fun2 YR "b" MKAY
VISIBLE I IZ fun3 YR "c" AN YR "d" AN YR "e" AN YR "f" AN YR "g" AN YR "h" AN YR "i" AN YR "j" AN YR "k" AN YR "l" MKAY
KTHXBYE

View File

@ -1,17 +1,17 @@
HAI 1.3
HOW DUZ I fun1
HOW IZ I fun1
"a"
IF U SAY SO
HOW DUZ I fun2 YR arg
HOW IZ I fun2 YR arg
arg
IF U SAY SO
HOW DUZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
HOW IZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
SMOOSH arg1 AN arg2 AN arg3 AN arg4 AN arg5 AN arg6 AN arg7 AN arg8 AN arg9 AN arg10 MKAY
IF U SAY SO
VISIBLE fun1
VISIBLE fun2 "b"
VISIBLE fun3 "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
VISIBLE I IZ fun1 MKAY
VISIBLE I IZ fun2 YR "b" MKAY
VISIBLE I IZ fun3 YR "c" AN YR "d" AN YR "e" AN YR "f" AN YR "g" AN YR "h" AN YR "i" AN YR "j" AN YR "k" AN YR "l" MKAY
KTHXBYE

View File

@ -1,20 +1,20 @@
HAI 1.3
HOW DUZ I fun1
HOW IZ I fun1
"a"
GTFO
IF U SAY SO
HOW DUZ I fun2 YR arg
HOW IZ I fun2 YR arg
arg
GTFO
IF U SAY SO
HOW DUZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
HOW IZ I fun3 YR arg1 AN YR arg2 AN YR arg3 AN YR arg4 AN YR arg5 AN YR arg6 AN YR arg7 AN YR arg8 AN YR arg9 AN YR arg10
SMOOSH arg1 AN arg2 AN arg3 AN arg4 AN arg5 AN arg6 AN arg7 AN arg8 AN arg9 AN arg10 MKAY
GTFO
IF U SAY SO
VISIBLE SUM OF 0 AN NOT fun1
VISIBLE SUM OF 0 AN NOT fun2 "b"
VISIBLE SUM OF 0 AN NOT fun3 "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
VISIBLE SUM OF 0 AN NOT I IZ fun1 MKAY
VISIBLE SUM OF 0 AN NOT I IZ fun2 YR "b" MKAY
VISIBLE SUM OF 0 AN NOT I IZ fun3 YR "c" AN YR "d" AN YR "e" AN YR "f" AN YR "g" AN YR "h" AN YR "i" AN YR "j" AN YR "k" AN YR "l" MKAY
KTHXBYE

View File

@ -1,13 +1,13 @@
HAI 1.3
HOW DUZ I fun YR a
HOW IZ I fun YR a
VISIBLE a
BOTH SAEM a AN 0
O RLY?
YA RLY
GTFO
OIC
fun DIFF OF a AN 1
I IZ fun YR DIFF OF a AN 1 MKAY
IF U SAY SO
fun 9
I IZ fun YR 9 MKAY
KTHXBYE

View File

@ -1,23 +1,23 @@
HAI 1.3
HOW DUZ I fun1 YR a
HOW IZ I fun1 YR a
VISIBLE a
BOTH SAEM a AN 0
O RLY?
YA RLY
GTFO
OIC
fun2 DIFF OF a AN 1
I IZ fun2 YR DIFF OF a AN 1 MKAY
IF U SAY SO
HOW DUZ I fun2 YR a
HOW IZ I fun2 YR a
VISIBLE a
BOTH SAEM a AN 0
O RLY?
YA RLY
GTFO
OIC
fun1 DIFF OF a AN 1
I IZ fun1 YR DIFF OF a AN 1 MKAY
IF U SAY SO
fun1 9
I IZ fun1 YR 9 MKAY
KTHXBYE

View File

@ -1,7 +1,7 @@
HAI 1.3
HOW DUZ I fun YR a
HOW IZ I fun YR a
VISIBLE a
IF U SAY SO
fun SUM OF 1 AN 2.345
I IZ fun YR SUM OF 1 AN 2.345 MKAY
KTHXBYE

View File

@ -1,7 +1,7 @@
HAI 1.3
HOW DUZ I fun
HOW IZ I fun
VISIBLE "a"
IF U SAY SO
fun "b"
I IZ fun YR "b" MKAY
KTHXBYE

View File

@ -1,7 +1,7 @@
HAI 1.3
HOW DUZ I fun YR a
HOW IZ I fun YR a
VISIBLE a
IF U SAY SO
fun 1 2
I IZ fun YR 1 AN YR 2 MKAY
KTHXBYE

View File

@ -87,7 +87,8 @@ typedef enum {
TT_TIL,
TT_WILE,
TT_IMOUTTAYR,
TT_HOWDUZ,
TT_HOWIZ,
TT_IZ,
TT_IFUSAYSO,
TT_FOUNDYR,
TT_ENDOFTOKENS
@ -155,7 +156,8 @@ static const char *keywords[] = {
"TIL", /* TT_TIL */
"WILE", /* TT_WILE */
"IM OUTTA YR", /* TT_IMOUTTAYR */
"HOW DUZ", /* TT_HOWDUZ */
"HOW IZ", /* TT_HOWIZ */
"IZ", /* TT_IZ */
"IF U SAY SO", /* TT_IFUSAYSO */
"FOUND YR", /* TT_FOUNDYR */
"", /* TT_ENDOFTOKENS */