Merged cleaned up source code

This commit is contained in:
Justin J. Meza 2010-12-22 18:06:32 -05:00
commit 977e3dfde5
14 changed files with 2884 additions and 1606 deletions

View File

@ -5,6 +5,7 @@ SRCS = lexer.c tokenizer.c parser.c interpreter.c unicode.c main.c
HDRS = lexer.h tokenizer.h parser.h interpreter.h unicode.h
INSTALL = /usr/local/bin/install -c
CPPFLAGS = -O3
LINT = splint -nullret -temptrans -compdestroy -usereleased -compdef -compmempass -mustfreefresh -boolops -predboolint -nullpass -nullderef +boolint -predboolothers -uniondef -unqualifiedtrans -nullstate -bufferoverflowhigh -branchstate -mustfreeonly -nullassign -shiftimplementation -exportlocal
prefix = /usr/local
bindir = $(prefix)/bin
@ -16,7 +17,10 @@ $(TARGET): $(OBJS) $(LIBS)
$(CC) $(CPPFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
pedantic: $(OBJS) $(LIBS)
$(CC) -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wundef -W -Wall -ansi -pedantic -g -o $(TARGET) $(OBJS) $(LIBS)
$(CC) -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wundef -Wall -ansi -pedantic -g -o $(TARGET) $(SRCS) $(HDRS) $(LIBS)
lint: all
$(LINT) $(SRCS)
check: all
@cd $(testdir) && ./testDir.sh -q ../$(TARGET) 1.3-Tests/

View File

@ -20,7 +20,14 @@ char *createString(char *data) /**< [in] A pointer to the string data to store.
*
* \return A pointer to a nil type ValueObject structure.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createBooleanValueObject(int)
* \see createIntegerValueObject(int)
* \see createFloatValueObject(float)
* \see createStringValueObject(char *)
* \see createFunctionValueObject(FuncDefStmtNode *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createNilValueObject(void)
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -38,7 +45,14 @@ ValueObject *createNilValueObject(void)
* \return A pointer to a boolean type ValueObject structure with value
* \c 0 if \a data equals 0 and \c 1 otherwise.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createNilValueObject(void)
* \see createIntegerValueObject(int)
* \see createFloatValueObject(float)
* \see createStringValueObject(char *)
* \see createFunctionValueObject(FuncDefStmtNode *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createBooleanValueObject(int data) /**< [in] The boolean data to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -57,7 +71,14 @@ ValueObject *createBooleanValueObject(int data) /**< [in] The boolean data to st
* \return A pointer to an integer type ValueObject structure with value
* \a data.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createNilValueObject(void)
* \see createBooleanValueObject(int)
* \see createFloatValueObject(float)
* \see createStringValueObject(char *)
* \see createFunctionValueObject(FuncDefStmtNode *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createIntegerValueObject(int data) /**< [in] The integer data to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -76,7 +97,14 @@ ValueObject *createIntegerValueObject(int data) /**< [in] The integer data to st
* \return A pointer to a floating point decimal type ValueObject structure
* with value \a data.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createNilValueObject(void)
* \see createBooleanValueObject(int)
* \see createIntegerValueObject(int)
* \see createStringValueObject(char *)
* \see createFunctionValueObject(FuncDefStmtNode *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createFloatValueObject(float data) /**< [in] The floating point data to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -94,7 +122,14 @@ ValueObject *createFloatValueObject(float data) /**< [in] The floating point dat
*
* \return A pointer to a string type ValueObject structure with value \a data.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createNilValueObject(void)
* \see createBooleanValueObject(int)
* \see createIntegerValueObject(int)
* \see createFloatValueObject(float)
* \see createFunctionValueObject(FuncDefStmtNode *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createStringValueObject(char *data) /**< [in] The string data to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -112,7 +147,14 @@ ValueObject *createStringValueObject(char *data) /**< [in] The string data to st
*
* \return A pointer to a function type ValueObject structure with definition \a data.
*
* \retval NULL malloc was unable to allocate memory. */
* \retval NULL malloc was unable to allocate memory.
*
* \see createNilValueObject(void)
* \see createBooleanValueObject(int)
* \see createIntegerValueObject(int)
* \see createFloatValueObject(float)
* \see createStringValueObject(char *)
* \see deleteValueObject(ValueObject *) */
ValueObject *createFunctionValueObject(FuncDefStmtNode *data) /**< [in] The function definition to store. */
{
ValueObject *p = malloc(sizeof(ValueObject));
@ -230,34 +272,68 @@ void deleteReturnObject(ReturnObject *object) /**< [in,out] The ReturnObject str
free(object);
}
/** \todo Document this function */
char *resolveIdentifierName(IdentifierNode *id,
ScopeObject *scope)
/** Translates an identifier into a string naming a variable.
*
* \pre \a id was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
*
* \return A newly-allocated array of characters representing the name of the
* identifier.
*
* \retval NULL malloc was unable to allocate memory. */
char *resolveIdentifierName(IdentifierNode *id, /**< [in] A pointer to the IdentifierNode structure to translate. */
ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to translate \a id under. */
{
ValueObject *val = NULL;
ValueObject *str = NULL;
char *ret = NULL;
if (!id) return NULL;
if (!id) goto resolveIdentifierNameAbort;
if (id->type == IT_DIRECT) {
char *temp = (char *)(id->id);
/* Just return a copy of the character array */
const char *temp = (char *)(id->id);
ret = malloc(sizeof(char) * (strlen(temp) + 1));
strcpy(ret, temp);
}
else if (id->type == IT_INDIRECT) {
ExprNode *expr = (ExprNode *)(id->id);
ValueObject *val = interpretExprNode(expr, scope);
ValueObject *str = castStringExplicit(val, scope);
/* Interpret the identifier expression */
val = interpretExprNode(expr, scope);
if (!val) goto resolveIdentifierNameAbort;
/* Then cast it to a string */
str = castStringExplicit(val, scope);
if (!str) goto resolveIdentifierNameAbort;
deleteValueObject(val);
/* Copy the evaluated string */
ret = createString(getString(str));
if (!ret) goto resolveIdentifierNameAbort;
deleteValueObject(str);
}
else {
fprintf(stderr, "%s:%d: invalid identifier type\n", id->fname, id->line);
fprintf(stderr, "%s:%u: invalid identifier type\n", id->fname, id->line);
}
return ret;
resolveIdentifierNameAbort: /* Exception handline */
/* Clean up any allocated structures */
if (ret) free(ret);
if (str) deleteValueObject(str);
if (val) deleteValueObject(val);
return NULL;
}
/** Creates a ScopeObject structure.
*
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* \pre \a parent was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *)
* or is \c NULL if creating the root parent.
@ -267,7 +343,7 @@ char *resolveIdentifierName(IdentifierNode *id,
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteScopeObject(ScopeObject *) */
ScopeObject *createScopeObject(ScopeObject *parent) /**< [in] A pointer to the parent ScopeObject. */
ScopeObject *createScopeObject(ScopeObject *parent) /**< [in] A pointer to the parent ScopeObject structure. */
{
ScopeObject *p = malloc(sizeof(ScopeObject));
if (!p) {
@ -316,7 +392,7 @@ void deleteScopeObject(ScopeObject *scope) /**< [in,out] The ScopeObject structu
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
* \pre \a target was created by createIdentifierNode(char *, const char *, unsigned int).
* \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
*
* \return A pointer to the stored ValueObject structure named by \a target.
*
@ -331,8 +407,11 @@ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject str
{
ScopeObject *current = scope;
char *name = NULL;
/* Look up the identifier name */
name = resolveIdentifierName(target, scope);
if (!name) return NULL;
/* Traverse upwards through scopes */
do {
unsigned int n;
@ -354,7 +433,7 @@ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject str
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
* \pre \a target was created by createIdentifierNode(char *, const char *, unsigned int).
* \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
*
* \return A pointer to the stored ValueObject structure named by \a target.
*
@ -369,8 +448,11 @@ ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObjec
{
unsigned int n;
char *name = NULL;
/* Look up the identifier name */
name = resolveIdentifierName(target, scope);
if (!name) return NULL;
/* Check for value in current scope */
for (n = 0; n < scope->numvals; n++) {
if (!strcmp(scope->names[n], name)) {
@ -387,7 +469,7 @@ ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObjec
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
* \pre \a target was created by createIdentifierNode(char *, const char *, unsigned int).
* \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
*
* \return A pointer to the newly created ValueObject structure named by
* \a target.
@ -404,8 +486,11 @@ ValueObject *createScopeValue(ScopeObject *scope, /**< [in,out] The ScopeObj
unsigned int newnumvals = scope->numvals + 1;
void *mem1 = NULL, *mem2 = NULL;
char *name = NULL;
/* Look up the identifier name */
name = resolveIdentifierName(target, scope);
if (!name) return NULL;
/* Add value to local scope */
mem1 = realloc(scope->names, sizeof(IdentifierNode *) * newnumvals);
if (!mem1) {
@ -435,7 +520,7 @@ ValueObject *createScopeValue(ScopeObject *scope, /**< [in,out] The ScopeObj
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
* \pre \a target was created by createIdentifierNode(char *, const char *, unsigned int).
* \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
* \pre The value named by \a target was created by createScopeValue(ScopeObject *, IdentifierNode *).
* \pre \a value was created by either createNilValueObject(void), createBooleanValueObject(int),
* createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *),
@ -456,8 +541,11 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to
{
ScopeObject *current = scope;
char *name = NULL;
/* Look up the identifier name */
name = resolveIdentifierName(target, scope);
if (!name) return NULL;
/* Traverse upwards through scopes */
do {
unsigned int n;
@ -476,7 +564,7 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to
}
}
} while ((current = current->parent));
fprintf(stderr, "%s:%d: unable to store variable\n", target->fname, target->line);
fprintf(stderr, "%s:%u: unable to store variable at: %s\n", target->fname, target->line, name);
free(name);
return NULL;
}
@ -487,7 +575,7 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
* \pre \a target was created by createIdentifierNode(char *, const char *, unsigned int).
* \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
*
* \see getScopeValue(ScopeObject *, IdentifierNode *)
* \see getLocalScopeValue(ScopeObject *, IdentifierNode *)
@ -498,8 +586,11 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco
{
ScopeObject *current = scope;
char *name = NULL;
/* Look up the identifier name */
name = resolveIdentifierName(target, scope);
if (!name) return;
/* Traverse upwards through scopes */
do {
unsigned int n;
@ -545,8 +636,8 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco
* \retval 1 The string of characters is a number. */
unsigned int isNumString(const char *stringdata) /**< [in] The array of characters to check the format of. */
{
unsigned int n;
unsigned int len = strlen(stringdata);
size_t n;
size_t len = strlen(stringdata);
/* Check for empty string */
if (len == 0) return 0;
/* Check for non-digit, non-hyphen, and non-period characters */
@ -566,8 +657,8 @@ unsigned int isNumString(const char *stringdata) /**< [in] The array of characte
* \retval 1 The string of characters is a hexadecimal number. */
unsigned int isHexString(const char *stringdata) /**< [in] The array of characters to check the format of. */
{
unsigned int n;
unsigned int len = strlen(stringdata);
size_t n;
size_t len = strlen(stringdata);
/* Check for empty string */
if (len == 0) return 0;
/* Check for non-digit and non-A-through-F characters */
@ -736,7 +827,7 @@ ValueObject *castBooleanExplicit(ValueObject *node, /**< [in] The ValueObject s
case VT_INTEGER:
return createBooleanValueObject(getInteger(node) != 0);
case VT_FLOAT:
return createBooleanValueObject(getFloat(node) != 0.0);
return createBooleanValueObject(fabs(getFloat(node) - 0.0) > FLT_EPSILON);
case VT_STRING:
if (strstr(getString(node), ":{")) {
/* Perform interpolation */
@ -749,9 +840,13 @@ ValueObject *castBooleanExplicit(ValueObject *node, /**< [in] The ValueObject s
}
else
return createBooleanValueObject(getString(node)[0] != '\0');
case VT_FUNC:
fprintf(stderr, "Cannot cast functions to booleans\n");
return NULL;
default:
fprintf(stderr, "Unknown value type encountered during boolean cast\n");
return NULL;
}
fprintf(stderr, "Unknown value type encountered during boolean cast\n");
return NULL;
}
/** Casts the contents of a ValueObject structure to integer type in an
@ -783,7 +878,7 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s
case VT_INTEGER:
return createIntegerValueObject(getInteger(node));
case VT_FLOAT:
return createIntegerValueObject(getFloat(node));
return createIntegerValueObject((int)getFloat(node));
case VT_STRING:
if (strstr(getString(node), ":{")) {
/* Perform interpolation */
@ -796,7 +891,11 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s
deleteValueObject(interp);
return NULL;
}
sscanf(getString(interp), "%i", &value);
if (sscanf(getString(interp), "%i", &value) != 1) {
fprintf(stderr, "Expected integer value\n");
deleteValueObject(interp);
return NULL;
}
ret = createIntegerValueObject(value);
deleteValueObject(interp);
return ret;
@ -807,12 +906,19 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s
fprintf(stderr, "Unable to cast value\n");
return NULL;
}
sscanf(getString(node), "%i", &value);
if (sscanf(getString(node), "%i", &value) != 1) {
fprintf(stderr, "Expected integer value\n");
return NULL;
}
return createIntegerValueObject(value);
}
case VT_FUNC:
fprintf(stderr, "Cannot cast functions to integers\n");
return NULL;
default:
fprintf(stderr, "Unknown value type encountered during integer cast\n");
return NULL;
}
fprintf(stderr, "Unknown value type encountered during integer cast\n");
return NULL;
}
/** Casts the contents of a ValueObject structure to floating point decimal
@ -842,7 +948,7 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str
return createFloatValueObject(0.0);
case VT_BOOLEAN:
case VT_INTEGER:
return createFloatValueObject(getInteger(node));
return createFloatValueObject((float)getInteger(node));
case VT_FLOAT:
return createFloatValueObject(getFloat(node));
case VT_STRING:
@ -857,7 +963,11 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str
deleteValueObject(interp);
return NULL;
}
sscanf(getString(interp), "%f", &value);
if (sscanf(getString(interp), "%f", &value) != 1) {
fprintf(stderr, "Expected floating point decimal value\n");
deleteValueObject(interp);
return NULL;
}
ret = createFloatValueObject(value);
deleteValueObject(interp);
return ret;
@ -868,12 +978,19 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str
fprintf(stderr, "Unable to cast value\n");
return NULL;
}
sscanf(getString(node), "%f", &value);
if (sscanf(getString(node), "%f", &value) != 1) {
fprintf(stderr, "Expected floating point decimal value\n");
return NULL;
}
return createFloatValueObject(value);
}
case VT_FUNC:
fprintf(stderr, "Cannot cast functions to floats\n");
return NULL;
default:
fprintf(stderr, "Unknown value type encountered during floating point decimal cast\n");
return NULL;
}
fprintf(stderr, "Unknown value type encountered during floating point decimal cast\n");
return NULL;
}
/** Casts the contents of a ValueObject structure to string type in an explicit
@ -941,7 +1058,8 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
char *temp = NULL;
char *data = NULL;
char *str = getString(node);
unsigned int a, b, size;
unsigned int a, b;
size_t size;
/* Perform interpolation */
size = strlen(getString(node)) + 1;
temp = malloc(sizeof(char) * size);
@ -969,12 +1087,19 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
else if (!strncmp(str + b, ":(", 2)) {
const char *start = str + b + 2;
const char *end = strchr(start, ')');
unsigned short len = end - start;
char *image = malloc(sizeof(char) * (len + 1));
size_t len;
char *image = NULL;
long codepoint;
char out[3];
unsigned short num;
size_t num;
void *mem = NULL;
if (end < start) {
fprintf(stderr, "Expected closing parenthesis after :(\n");
free(temp);
return NULL;
}
len = (size_t)(end - start);
image = malloc(sizeof(char) * (len + 1));
strncpy(image, start, len);
image[len] = '\0';
if (!isHexString(image)) {
@ -985,7 +1110,12 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
}
codepoint = strtol(image, NULL, 16);
free(image);
num = convertCodePointToUTF8(codepoint, out);
if (codepoint < 0) {
fprintf(stderr, "Code point is supposed to be positive\n");
free(temp);
return NULL;
}
num = convertCodePointToUTF8((unsigned int)codepoint, out);
if (num == 0) {
free(temp);
return NULL;
@ -1004,22 +1134,30 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
else if (!strncmp(str + b, ":[", 2)) {
const char *start = str + b + 2;
const char *end = strchr(start, ']');
unsigned short len = end - start;
char *image = malloc(sizeof(char) * (len + 1));
size_t len;
char *image = NULL;
long codepoint;
char out[3];
unsigned short num;
size_t num;
void *mem = NULL;
if (end < start) {
fprintf(stderr, "Expected closing square bracket after :[\n");
free(temp);
return NULL;
}
len = (size_t)(end - start);
image = malloc(sizeof(char) * (len + 1));
strncpy(image, start, len);
strncpy(image, start, len);
image[len] = '\0';
codepoint = convertNormativeNameToCodePoint(image);
free(image);
if (codepoint < 0) {
fprintf(stderr, "Code point is supposed to be positive\n");
free(temp);
return NULL;
}
num = convertCodePointToUTF8(codepoint, out);
num = convertCodePointToUTF8((unsigned int)codepoint, out);
size += num;
mem = realloc(temp, size);
if (!mem) {
@ -1037,9 +1175,16 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
/* Copy the variable name into image */
const char *start = str + b + 2;
const char *end = strchr(start, '}');
unsigned short len = end - start;
char *image = malloc(sizeof(char) * (len + 1));
size_t len;
char *image = NULL;
void *mem = NULL;
if (end < start) {
fprintf(stderr, "Expected closing curly brace after :{\n");
free(temp);
return NULL;
}
len = (size_t)(end - start);
image = malloc(sizeof(char) * (len + 1));
strncpy(image, start, len);
image[len] = '\0';
if (!strcmp(image, "IT"))
@ -1092,9 +1237,14 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
free(temp);
return createStringValueObject(data);
}
case VT_FUNC: {
fprintf(stderr, "Cannot cast functions to strings\n");
return NULL;
}
default:
fprintf(stderr, "Unknown value type encountered during string cast\n");
return NULL;
}
fprintf(stderr, "Unknown value type encountered during string cast\n");
return NULL;
}
/** Interprets an implicit variable expression.
@ -1179,7 +1329,7 @@ ValueObject *interpretCastExprNode(ExprNode *node, /**< [in] A pointer to an
*
* \pre \a node was created by createExprNode(ExprType type, void *expr)
* where \a type is ET_FUNCCALL and \a expr is a FunctionCallExprNode
* structure created by createFuncCallExprNode(FuncDefStmtNode *, ExprNodeList *).
* structure created by createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -1208,7 +1358,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
IdentifierNode *id = (IdentifierNode *)(expr->name);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: undefined function at: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: undefined function at: %s\n", id->fname, id->line, name);
free(name);
}
deleteScopeObject(outer);
@ -1219,7 +1369,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
IdentifierNode *id = (IdentifierNode *)(expr->name);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: incorrect number of arguments supplied to: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: incorrect number of arguments supplied to: %s\n", id->fname, id->line, name);
free(name);
}
deleteScopeObject(outer);
@ -1276,7 +1426,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
*
* \pre \a node was created by createExprNode(ExprType type, void *expr)
* where \a type is ET_IDENTIFIER and \a expr is an IdentifierNode
* structure created by createIdentifierNode(char *, const char *, unsigned int).
* structure created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -1297,14 +1447,12 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
ValueObject *interpretIdentifierExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure containing the IdentifierNode structure to interpret. */
ScopeObject *scope) /**< Not used (see note). */
{
IdentifierNode *id = NULL;
ValueObject *val = NULL;
id = (IdentifierNode *)(node->expr);
val = getScopeValue(scope, id);
ValueObject *val = getScopeValue(scope, node->expr);
if (!val) {
IdentifierNode *id = (IdentifierNode *)(node->expr);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: variable does not exist at: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: variable does not exist at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
@ -1565,7 +1713,7 @@ ValueObject *opModIntegerInteger(ValueObject *a, /**< [in] The dividend. */
ValueObject *opAddIntegerFloat(ValueObject *a, /**< [in] The first term to add. */
ValueObject *b) /**< [in] The second term to add. */
{
return createFloatValueObject(getInteger(a) + getFloat(b));
return createFloatValueObject((float)(getInteger(a) + getFloat(b)));
}
/** Subtracts an integer and a float.
@ -1585,7 +1733,7 @@ ValueObject *opAddIntegerFloat(ValueObject *a, /**< [in] The first term to add.
ValueObject *opSubIntegerFloat(ValueObject *a, /**< [in] The minuend. */
ValueObject *b) /**< [in] The subtrahend. */
{
return createFloatValueObject(getInteger(a) - getFloat(b));
return createFloatValueObject((float)(getInteger(a) - getFloat(b)));
}
/** Multiplies an integer and a float.
@ -1605,7 +1753,7 @@ ValueObject *opSubIntegerFloat(ValueObject *a, /**< [in] The minuend. */
ValueObject *opMultIntegerFloat(ValueObject *a, /**< [in] The first factor to multiply. */
ValueObject *b) /**< [in] The second factor to multiply. */
{
return createFloatValueObject(getInteger(a) * getFloat(b));
return createFloatValueObject((float)(getInteger(a) * getFloat(b)));
}
/** Divides an integer and a float.
@ -1627,11 +1775,11 @@ ValueObject *opMultIntegerFloat(ValueObject *a, /**< [in] The first factor to mu
ValueObject *opDivIntegerFloat(ValueObject *a, /**< [in] The dividend. */
ValueObject *b) /**< [in] The divisor. */
{
if (getFloat(b) == 0.0) {
if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) {
fprintf(stderr, "Division by zero undefined\n");
return NULL;
}
return createFloatValueObject(getInteger(a) / getFloat(b));
return createFloatValueObject((float)(getInteger(a) / getFloat(b)));
}
/** Finds the maximum of an integer and a float.
@ -1651,7 +1799,7 @@ ValueObject *opDivIntegerFloat(ValueObject *a, /**< [in] The dividend. */
ValueObject *opMaxIntegerFloat(ValueObject *a, /**< [in] The first number to compare. */
ValueObject *b) /**< [in] The second number to compare. */
{
return createFloatValueObject(getInteger(a) > getFloat(b) ? getInteger(a) : getFloat(b));
return createFloatValueObject((float)(getInteger(a)) > getFloat(b) ? (float)(getInteger(a)) : getFloat(b));
}
/** Finds the minimum of an integer and a float.
@ -1671,7 +1819,7 @@ ValueObject *opMaxIntegerFloat(ValueObject *a, /**< [in] The first number to com
ValueObject *opMinIntegerFloat(ValueObject *a, /**< [in] The first number to compare. */
ValueObject *b) /**< [in] The second number to compare. */
{
return createFloatValueObject(getInteger(a) < getFloat(b) ? getInteger(a) : getFloat(b));
return createFloatValueObject((float)(getInteger(a)) < getFloat(b) ? (float)(getInteger(a)) : getFloat(b));
}
/** Calculates the modulus of an integer and a float.
@ -1691,11 +1839,11 @@ ValueObject *opMinIntegerFloat(ValueObject *a, /**< [in] The first number to com
ValueObject *opModIntegerFloat(ValueObject *a, /**< [in] The dividend. */
ValueObject *b) /**< [in] The divisor. */
{
if (getFloat(b) == 0.0) {
if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) {
fprintf(stderr, "Division by zero undefined\n");
return NULL;
}
return createFloatValueObject(fmod(getInteger(a), getFloat(b)));
return createFloatValueObject((float)(fmod((double)(getInteger(a)), getFloat(b))));
}
/** Adds a float and an integer.
@ -1800,7 +1948,7 @@ ValueObject *opDivFloatInteger(ValueObject *a, /**< [in] The dividend. */
ValueObject *opMaxFloatInteger(ValueObject *a, /**< [in] The first number to compare. */
ValueObject *b) /**< [in] The second number to compare. */
{
return createFloatValueObject(getFloat(a) > getInteger(b) ? getFloat(a) : getInteger(b));
return createFloatValueObject(getFloat(a) > (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b)));
}
/** Finds the minimum of a float and an integer.
@ -1820,7 +1968,7 @@ ValueObject *opMaxFloatInteger(ValueObject *a, /**< [in] The first number to com
ValueObject *opMinFloatInteger(ValueObject *a, /**< [in] The first number to compare. */
ValueObject *b) /**< [in] The second number to compare. */
{
return createFloatValueObject(getFloat(a) < getInteger(b) ? getFloat(a) : getInteger(b));
return createFloatValueObject(getFloat(a) < (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b)));
}
/** Calculates the modulus of a float and an integer.
@ -1844,7 +1992,7 @@ ValueObject *opModFloatInteger(ValueObject *a, /**< [in] The dividend. */
fprintf(stderr, "Division by zero undefined\n");
return NULL;
}
return createFloatValueObject(fmod(getFloat(a), getInteger(b)));
return createFloatValueObject((float)(fmod(getFloat(a), (double)(getInteger(b)))));
}
/** Adds two floats.
@ -1922,7 +2070,7 @@ ValueObject *opMultFloatFloat(ValueObject *a, /**< [in] The first factor to mult
ValueObject *opDivFloatFloat(ValueObject *a, /**< [in] The dividend. */
ValueObject *b) /**< [in] The divisor. */
{
if (getFloat(b) == 0.0) {
if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) {
fprintf(stderr, "Division by zero undefined\n");
return NULL;
}
@ -1983,11 +2131,11 @@ ValueObject *opMinFloatFloat(ValueObject *a, /**< [in] The first number to compa
ValueObject *opModFloatFloat(ValueObject *a, /**< [in] The dividend. */
ValueObject *b) /**< [in] The divisor. */
{
if (getFloat(b) == 0.0) {
if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) {
fprintf(stderr, "Division by zero undefined\n");
return NULL;
}
return createFloatValueObject(fmod(getFloat(a), getFloat(b)));
return createFloatValueObject((float)(fmod(getFloat(a), getFloat(b))));
}
/* A jump table for arithmetic operations. The first index determines the
@ -2159,7 +2307,7 @@ ValueObject *interpretBoolOpExprNode(OpExprNode *expr, /**< [in] A pointer to
for (n = 0; n < expr->args->num; n++) {
ValueObject *val = interpretExprNode(expr->args->exprs[n], scope);
ValueObject *use = val;
unsigned int temp;
int temp;
unsigned int cast = 0;
if (!val) return NULL;
if (val->type != VT_BOOLEAN && val->type != VT_INTEGER) {
@ -2238,7 +2386,7 @@ ValueObject *opNeqIntegerInteger(ValueObject *a, /**< [in] The first value to te
ValueObject *opEqIntegerFloat(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getInteger(a) == getFloat(b));
return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) < FLT_EPSILON);
}
/** Tests if an integer and a float are not equal.
@ -2253,7 +2401,7 @@ ValueObject *opEqIntegerFloat(ValueObject *a, /**< [in] The first value to test.
ValueObject *opNeqIntegerFloat(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getInteger(a) != getFloat(b));
return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) > FLT_EPSILON);
}
/** Tests if a float and an integer are equal.
@ -2268,7 +2416,7 @@ ValueObject *opNeqIntegerFloat(ValueObject *a, /**< [in] The first value to test
ValueObject *opEqFloatInteger(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getFloat(a) == getInteger(b));
return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) < FLT_EPSILON);
}
/** Tests if a float and an integer are not equal.
@ -2283,7 +2431,7 @@ ValueObject *opEqFloatInteger(ValueObject *a, /**< [in] The first value to test.
ValueObject *opNeqFloatInteger(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getFloat(a) != getInteger(b));
return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) > FLT_EPSILON);
}
/** Tests if two floats are equal.
@ -2297,7 +2445,7 @@ ValueObject *opNeqFloatInteger(ValueObject *a, /**< [in] The first value to test
ValueObject *opEqFloatFloat(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getFloat(a) == getFloat(b));
return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) < FLT_EPSILON);
}
/** Tests if two floats are not equal.
@ -2311,12 +2459,12 @@ ValueObject *opEqFloatFloat(ValueObject *a, /**< [in] The first value to test. *
ValueObject *opNeqFloatFloat(ValueObject *a, /**< [in] The first value to test. */
ValueObject *b) /**< [in] The second value to test. */
{
return createBooleanValueObject(getFloat(a) != getFloat(b));
return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) > FLT_EPSILON);
}
/** Tests if two boolean values are equal.
*
* \pre \a a and \a b were created by createBooleanValueObject(float).
* \pre \a a and \a b were created by createBooleanValueObject(int).
*
* \return A pointer to a ValueObject structure containing a boolean value
* indicating whether \a a is equal to \a b.
@ -2330,7 +2478,7 @@ ValueObject *opEqBooleanBoolean(ValueObject *a, /**< [in] The first value to tes
/** Tests if two boolean values are not equal.
*
* \pre \a a and \a b were created by createBooleanValueObject(float).
* \pre \a a and \a b were created by createBooleanValueObject(int).
*
* \return A pointer to a ValueObject structure containing a boolean value
* indicating whether \a a is not equal to \a b.
@ -2673,7 +2821,7 @@ ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to t
IdentifierNode *id = (IdentifierNode *)(stmt->target);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: variable does not exist at: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: variable does not exist at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
@ -2778,7 +2926,7 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to
unsigned int size = 16;
unsigned int cur = 0;
char *temp = malloc(sizeof(char) * size);
char c;
int c;
void *mem = NULL;
InputStmtNode *stmt = (InputStmtNode *)node->stmt;
ValueObject *val = NULL;
@ -2786,7 +2934,7 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to
/** \note The specification is unclear as to the exact semantics
* of input. Here, we read up until the first newline or
* EOF but do not store it. */
if (c == EOF || c == '\r' || c == '\n') break;
if (c == EOF || c == (int)'\r' || c == (int)'\n') break;
if (cur > size - 1) {
/* Increasing buffer size. */
size *= 2;
@ -2798,7 +2946,7 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to
}
temp = mem;
}
temp[cur] = c;
temp[cur] = (char)c;
cur++;
}
temp[cur] = '\0';
@ -2854,7 +3002,7 @@ ReturnObject *interpretAssignmentStmtNode(StmtNode *node, /**< [in] A pointe
/** Interprets a declaration statement.
*
* \pre \a node was created by createStmtNode(StmtType type, void *stmt) where
* \a type is ST_DECLARATION and \a stmt was created by createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *).
* \a type is ST_DECLARATION and \a stmt was created by createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -2884,7 +3032,7 @@ ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A point
IdentifierNode *id = (IdentifierNode *)(stmt->target);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: redefinition of existing variable at: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: redefinition of existing variable at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
@ -3062,7 +3210,7 @@ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to
done = 1;
break;
case VT_FLOAT:
if (getFloat(use1) == getFloat(use2))
if (fabs(getFloat(use1) - getFloat(use2)) < FLT_EPSILON)
done = 1;
break;
case VT_STRING:
@ -3329,7 +3477,7 @@ ReturnObject *interpretDeallocationStmtNode(StmtNode *node, /**< [in] A poin
/** Interprets a function definition statement.
*
* \pre \a node was created by createStmtNode(StmtType type, void *stmt) where
* \a type is ST_SWITCH and \a stmt was created by createSwitchStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *).
* \a type is ST_SWITCH and \a stmt was created by createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *).
* \pre \a scope was created by createScopeObject(ScopeObject *) and contains
* contents added by createScopeValue(ScopeObject *, IdentifierNode *) and
* contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *).
@ -3364,7 +3512,7 @@ ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see no
IdentifierNode *id = (IdentifierNode *)(stmt->name);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%d: function name already used by existing variable at: %s\n", id->fname, id->line, name);
fprintf(stderr, "%s:%u: function name already used by existing variable at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;

View File

@ -103,6 +103,7 @@ ValueObject *copyValueObject(ValueObject *);
void deleteValueObject(ValueObject *);
ReturnObject *createReturnObject(ReturnType, ValueObject *);
void deleteReturnObject(ReturnObject *);
char *resolveIdentifierName(IdentifierNode *, ScopeObject *);
ScopeObject *createScopeObject(ScopeObject *);
void deleteScopeObject(ScopeObject *);
ValueObject *getScopeValue(ScopeObject *, IdentifierNode *);

19
lexer.c
View File

@ -139,14 +139,15 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
const char *start = buffer;
LexemeList *list = NULL;
unsigned int line = 1;
Lexeme *lex = NULL;
list = createLexemeList();
if (!list) return NULL;
while (start < buffer + size) {
char *temp = NULL;
unsigned int len = 1;
size_t len = 1;
/* Comma (,) is a soft newline */
if (*start == ',') {
Lexeme *lex = createLexeme("\n", fname, line);
lex = createLexeme("\n", fname, line);
if (!lex) {
deleteLexemeList(list);
return NULL;
@ -161,7 +162,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
}
/* Bang (!) is its own lexeme */
if (*start == '!') {
Lexeme *lex = createLexeme("!", fname, line);
lex = createLexeme("!", fname, line);
if (!lex) {
deleteLexemeList(list);
return NULL;
@ -186,7 +187,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
newline = 1;
}
if (newline) {
Lexeme *lex = createLexeme("\n", fname, line);
lex = createLexeme("\n", fname, line);
if (!lex) {
deleteLexemeList(list);
return NULL;
@ -212,7 +213,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
/* Make sure next line is not empty */
while (*test && isspace(*test)) {
if (*test == '\r' || *test == '\n') {
fprintf(stderr, "%s:%d: a line with continuation may not be followed by an empty line\n", fname, line);
fprintf(stderr, "%s:%u: a line with continuation may not be followed by an empty line\n", fname, line);
deleteLexemeList(list);
return NULL;
}
@ -239,7 +240,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
start++;
if (start == buffer || *start == ',' || *start == '\r' || *start == '\n')
continue;
fprintf(stderr, "%s:%d: multiple line comment may not appear on the same line as code\n", fname, line);
fprintf(stderr, "%s:%u: multiple line comment may not appear on the same line as code\n", fname, line);
deleteLexemeList(list);
return NULL;
}
@ -270,7 +271,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
&& *(start + len) != '!'
&& strncmp(start + len, "...", 3)
&& strncmp(start + len, "\xE2\x80\xA6", 3)) {
fprintf(stderr, "%s:%d: expected token delimiter after string literal\n", fname, line);
fprintf(stderr, "%s:%u: expected token delimiter after string literal\n", fname, line);
deleteLexemeList(list);
return NULL;
}
@ -292,7 +293,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
}
strncpy(temp, start, len);
temp[len] = '\0';
Lexeme *lex = createLexeme(temp, fname, line);
lex = createLexeme(temp, fname, line);
if (!lex) {
free(temp);
deleteLexemeList(list);
@ -308,7 +309,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t
start += len;
}
/* Create an end-of-file lexeme */
Lexeme *lex = createLexeme("$", fname, line);
lex = createLexeme("$", fname, line);
if (!lex) {
deleteLexemeList(list);
return NULL;

20
main.c
View File

@ -96,7 +96,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "lexer.h"
@ -110,8 +109,8 @@ static char *program_name;
static char *shortopt = "hv";
static struct option longopt[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, (int)'h' },
{ "version", no_argument, NULL, (int)'v' },
{ 0, 0, 0, 0 }
};
@ -129,8 +128,8 @@ static void version (char *revision) {
int main(int argc, char **argv)
{
long size = 0;
long length = 0;
unsigned int size = 0;
unsigned int length = 0;
char *buffer = NULL;
LexemeList *lexemes = NULL;
Token **tokens = NULL;
@ -139,7 +138,7 @@ int main(int argc, char **argv)
FILE *file = NULL;
int ch;
char *revision = "v0.9.1";
char *revision = "v0.10.1";
program_name = argv[0];
while ((ch = getopt_long(argc, argv, shortopt, longopt, NULL)) != -1) {
@ -148,12 +147,9 @@ int main(int argc, char **argv)
fprintf (stderr, "Incorrect option '%c'\n", ch);
help();
exit(EXIT_FAILURE);
case 'h':
help();
exit(EXIT_SUCCESS);
break;
case 'v':
version(revision);
exit(EXIT_SUCCESS);
@ -188,7 +184,11 @@ int main(int argc, char **argv)
length += fread((buffer + size) - READSIZE, 1, READSIZE, file);
}
fclose(file);
if (fclose(file) != 0) {
fprintf(stderr, "Error closing file.\n");
if (buffer) free(buffer);
return 1;
}
if (!buffer) return 1;
buffer[length] = '\0';

3827
parser.c

File diff suppressed because it is too large Load Diff

View File

@ -174,6 +174,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include "tokenizer.h"
@ -535,7 +537,7 @@ void deleteMainNode(MainNode *);
BlockNode *createBlockNode(StmtNodeList *);
void deleteBlockNode(BlockNode *);
BlockNodeList *createBlockNodeList(void);
BlockNode *addBlockNode(BlockNodeList *, BlockNode *);
int addBlockNode(BlockNodeList *, BlockNode *);
void deleteBlockNodeList(BlockNodeList *);
IdentifierNode *createIdentifierNode(IdentifierType, void *, const char *, unsigned int);
@ -547,7 +549,7 @@ void deleteTypeNode(TypeNode *);
StmtNode *createStmtNode(StmtType, void *);
void deleteStmtNode(StmtNode *);
StmtNodeList *createStmtNodeList(void);
StmtNode *addStmtNode(StmtNodeList *, StmtNode *);
int addStmtNode(StmtNodeList *, StmtNode *);
void deleteStmtNodeList(StmtNodeList *);
CastStmtNode *createCastStmtNode(IdentifierNode *, TypeNode *);
@ -586,7 +588,7 @@ void deleteFuncDefStmtNode(FuncDefStmtNode *);
ExprNode *createExprNode(ExprType, void *);
void deleteExprNode(ExprNode *);
ExprNodeList *createExprNodeList(void);
ExprNode *addExprNode(ExprNodeList *, ExprNode *);
int addExprNode(ExprNodeList *, ExprNode *);
void deleteExprNodeList(ExprNodeList *);
CastExprNode *createCastExprNode(ExprNode *, TypeNode *);
@ -612,6 +614,25 @@ StmtNode *parseStmtNode(Token ***);
BlockNode *parseBlockNode(Token ***);
MainNode *parseMainNode(Token **);
ExprNode *parseCastExprNode(Token ***);
ExprNode *parseConstantExprNode(Token ***);
ExprNode *parseIdentifierExprNode(Token ***);
ExprNode *parseFuncCallExprNode(Token ***);
ExprNode *parseOpExprNode(Token ***);
StmtNode *parseCastStmtNode(Token ***);
StmtNode *parsePrintStmtNode(Token ***);
StmtNode *parseInputStmtNode(Token ***);
StmtNode *parseAssignmentStmtNode(Token ***);
StmtNode *parseDeclarationStmtNode(Token ***);
StmtNode *parseIfThenElseStmtNode(Token ***);
StmtNode *parseSwitchStmtNode(Token ***);
StmtNode *parseBreakStmtNode(Token ***);
StmtNode *parseReturnStmtNode(Token ***);
StmtNode *parseLoopStmtNode(Token ***);
StmtNode *parseDeallocationStmtNode(Token ***);
StmtNode *parseFuncDefStmtNode(Token ***);
ConstantNode *createBooleanConstantNode(int);
ConstantNode *createIntegerConstantNode(int);
ConstantNode *createFloatConstantNode(float);
@ -619,7 +640,7 @@ ConstantNode *createStringConstantNode(char *);
void deleteConstantNode(ConstantNode *);
IdentifierNodeList *createIdentifierNodeList(void);
IdentifierNode *addIdentifierNode(IdentifierNodeList *, IdentifierNode *);
int addIdentifierNode(IdentifierNodeList *, IdentifierNode *);
void deleteIdentifierNodeList(IdentifierNodeList *);
#endif /* __PARSER_H__ */

View File

@ -0,0 +1,3 @@
HAI 1.3
CAN HAS STDIO?
KTHXBYE

View File

@ -0,0 +1 @@
This test checks that the include statement ``CAN HAS STDIO?'' is ignored.

View File

@ -1,5 +1,75 @@
#include "tokenizer.h"
static const char *keywords[] = {
"", /* TT_INTEGER */
"", /* TT_FLOAT */
"", /* TT_STRING */
"", /* TT_IDENTIFIER */
"", /* TT_BOOLEAN */
"IT", /* TT_IT */
"NOOB", /* TT_NOOB */
"NUMBR", /* TT_NUMBR */
"NUMBAR", /* TT_NUMBAR */
"TROOF", /* TT_TROOF */
"YARN", /* TT_YARN */
"", /* TT_EOF */
"", /* TT_NEWLINE */
"HAI", /* TT_HAI */
"KTHXBYE", /* TT_KTHXBYE */
"HAS A", /* TT_HASA */
"ITZ A", /* TT_ITZA */
"ITZ", /* TT_ITZ */
"R NOOB", /* TT_RNOOB */
"R", /* TT_R */
"AN YR", /* TT_ANYR */
"AN", /* TT_AN */
"SUM OF", /* TT_SUMOF */
"DIFF OF", /* TT_DIFFOF */
"PRODUKT OF", /* TT_PRODUKTOF */
"QUOSHUNT OF", /* TT_QUOSHUNTOF */
"MOD OF", /* TT_MODOF */
"BIGGR OF", /* TT_BIGGROF */
"SMALLR OF", /* TT_SMALLROF */
"BOTH OF", /* TT_BOTHOF */
"EITHER OF", /* TT_EITHEROF */
"WON OF", /* TT_WONOF */
"NOT", /* TT_NOT */
"MKAY", /* TT_MKAY */
"ALL OF", /* TT_ALLOF */
"ANY OF", /* TT_ANYOF */
"BOTH SAEM", /* TT_BOTHSAEM */
"DIFFRINT", /* TT_DIFFRINT */
"MAEK", /* TT_MAEK */
"A", /* TT_A */
"IS NOW A", /* TT_ISNOWA */
"VISIBLE", /* TT_VISIBLE */
"SMOOSH", /* TT_SMOOSH */
"!", /* TT_BANG */
"GIMMEH", /* TT_GIMMEH */
"O RLY?", /* TT_ORLY */
"YA RLY", /* TT_YARLY */
"MEBBE", /* TT_MEBBE */
"NO WAI", /* TT_NOWAI */
"OIC", /* TT_OIC */
"WTF?", /* TT_WTF */
"OMG", /* TT_OMG */
"OMGWTF", /* TT_OMGWTF */
"GTFO", /* TT_GTFO */
"IM IN YR", /* TT_IMINYR */
"UPPIN", /* TT_UPPIN */
"NERFIN", /* TT_NERFIN */
"YR", /* TT_YR */
"TIL", /* TT_TIL */
"WILE", /* TT_WILE */
"IM OUTTA YR", /* TT_IMOUTTAYR */
"HOW IZ", /* TT_HOWIZ */
"IZ", /* TT_IZ */
"IF U SAY SO", /* TT_IFUSAYSO */
"FOUND YR", /* TT_FOUNDYR */
"SRS", /* TT_SRS */
"" /* TT_ENDOFTOKENS */
};
/** Checks if a string of characters follows the format for an integer.
* Specifically, it checks if the string of characters matches the regular
* expression: [-]?[1-9][0-9]* | 0
@ -80,11 +150,6 @@ int isIdentifier(const char *image) /**< [in] The string of characters to compar
cur++;
while (*cur) {
if (isalnum(*cur) || *cur == '_') cur++;
/* Proposed LOLCODE Version 1.3 identifiers
* Remember to update expression: [a-zA-Z][a-zA-Z0-9]*([!!|!?][a-zA-Z][a-zA-Z0-9]*)*
else if (*cur == '!' && *(cur + 1) && *(cur + 1) == '!') cur += 2;
else if (*cur == '!' && *(cur + 1) && *(cur + 1) == '?') cur += 2;
*/
else return 0;
}
return 1;
@ -145,20 +210,19 @@ void deleteToken(Token *token)
* \post \a token will be added on to the end of \a list and the value at \a num
* will be updated accordingly.
*
* \return A pointer to the added Token structure (will be the same as \a token).
*
* \retval NULL realloc was unable to allocate memory.
* \retval 0 realloc was unable to allocate memory.
* \retval 1 \a node was added to \a list.
*
* \see deleteTokens(Token **) */
Token *addToken(Token ***list, /**< [in,out] A pointer to a pointer to an array of Token structures to add the new Token onto. */
unsigned int *num, /**< [in,out] A pointer to the number of elements in \a list. */
Token *token) /**< [in] A pointer to the Token structure to add to \a list. */
int addToken(Token ***list, /**< [in,out] A pointer to a pointer to an array of Token structures to add the new Token onto. */
unsigned int *num, /**< [in,out] A pointer to the number of elements in \a list. */
Token *token) /**< [in] A pointer to the Token structure to add to \a list. */
{
unsigned int newsize = *num + 1;
void *mem = realloc(*list, sizeof(Token *) * newsize);
if (!mem) {
perror("realloc");
return NULL;
return 0;
}
*list = mem;
(*list)[*num] = token;
@ -166,7 +230,7 @@ Token *addToken(Token ***list, /**< [in,out] A pointer to a pointer to an ar
#ifdef DEBUG
fprintf(stderr, "Adding token type %d [%s]\n", token->type, token->image);
#endif
return token;
return 1;
}
/** Deletes an array of Token structures.
@ -199,14 +263,15 @@ unsigned int acceptLexemes(LexemeList *lexemes, /**< [in] A pointer to a LexemeL
unsigned int offset = 0;
unsigned int n;
unsigned int i;
for (n = 0, i = 0; match[n] || lexemes->lexemes[start + offset]->image[i]; n++, i++) {
for (n = 0, i = 0; match[n] || lexemes->lexemes[start + offset]->image[i]; n++) {
if (match[n] == ' ') {
offset++;
i = -1;
i = 0;
continue;
}
if (lexemes->lexemes[start + offset]->image[i] != match[n])
return 0;
i++;
}
return offset + 1;
}
@ -234,7 +299,7 @@ Token *isKeyword(LexemeList *lexemes, /**< [in] A pointer to a LexemeList struct
const char *fname = lexemes->lexemes[*start]->fname;
unsigned int line = lexemes->lexemes[*start]->line;
for (type = 0; type != TT_ENDOFTOKENS; type++) {
int num = acceptLexemes(lexemes, *start, keywords[type]);
unsigned int num = acceptLexemes(lexemes, *start, keywords[type]);
if (!num) continue;
token = createToken(type, keywords[type], fname, line);
*start += (num - 1);
@ -272,12 +337,16 @@ Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList st
/* Float */
else if (isFloat(image)) {
token = createToken(TT_FLOAT, image, fname, line);
sscanf(lexeme->image, "%f", &(token->data.f));
if (sscanf(lexeme->image, "%f", &(token->data.f)) != 1) {
fprintf(stderr, "Expected floating point decimal value.\n");
}
}
/* Integer */
else if (isInteger(image)) {
token = createToken(TT_INTEGER, image, fname, line);
sscanf(lexeme->image, "%i", &(token->data.i));
if (sscanf(lexeme->image, "%i", &(token->data.i)) != 1) {
fprintf(stderr, "Expected integer value.\n");
}
}
/* FAIL */
else if (!strcmp(image, "FAIL")) {
@ -333,14 +402,23 @@ Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList st
token = createToken(TT_EOF, "end of file", fname, line);
}
else {
fprintf(stderr, "%s:%d: unknown token at: %s\n", fname, line, image);
fprintf(stderr, "%s:%u: unknown token at: %s\n", fname, line, image);
/* Clean up */
deleteToken(ret[retsize - 1]);
ret[retsize - 1] = NULL;
deleteTokens(ret);
return NULL;
}
addToken(&ret, &retsize, token);
/* Add the token to the token array */
if (!addToken(&ret, &retsize, token)) {
/* Clean up */
if (token) deleteToken(token);
deleteToken(ret[retsize - 1]);
ret[retsize - 1] = NULL;
deleteTokens(ret);
return NULL;
}
}
mem = realloc(ret, sizeof(Token *) * ++retsize);
if (!mem) {

View File

@ -24,7 +24,9 @@
/** Denotes the type of token present. All of the token type names are
* self-explainatory and correspond to either the semantic type of token data
* (in the case of TT_INTEGER, TT_FLOAT, TT_STRING, or TT_IDENTIFIER) or the
* lexemes which make up the particular token. */
* lexemes which make up the particular token.
*
* \note Remember to update the keywords array with the token image. */
typedef enum {
TT_INTEGER,
TT_FLOAT,
@ -95,76 +97,6 @@ typedef enum {
TT_ENDOFTOKENS
} TokenType;
static const char *keywords[] = {
"", /* TT_INTEGER */
"", /* TT_FLOAT */
"", /* TT_STRING */
"", /* TT_IDENTIFIER */
"", /* TT_BOOLEAN */
"IT", /* TT_IT */
"NOOB", /* TT_NOOB */
"NUMBR", /* TT_NUMBR */
"NUMBAR", /* TT_NUMBAR */
"TROOF", /* TT_TROOF */
"YARN", /* TT_YARN */
"", /* TT_EOF */
"", /* TT_NEWLINE */
"HAI", /* TT_HAI */
"KTHXBYE", /* TT_KTHXBYE */
"HAS A", /* TT_HASA */
"ITZ A", /* TT_ITZA */
"ITZ", /* TT_ITZ */
"R NOOB", /* TT_RNOOB */
"R", /* TT_R */
"AN YR", /* TT_ANYR */
"AN", /* TT_AN */
"SUM OF", /* TT_SUMOF */
"DIFF OF", /* TT_DIFFOF */
"PRODUKT OF", /* TT_PRODUKTOF */
"QUOSHUNT OF", /* TT_QUOSHUNTOF */
"MOD OF", /* TT_MODOF */
"BIGGR OF", /* TT_BIGGROF */
"SMALLR OF", /* TT_SMALLROF */
"BOTH OF", /* TT_BOTHOF */
"EITHER OF", /* TT_EITHEROF */
"WON OF", /* TT_WONOF */
"NOT", /* TT_NOT */
"MKAY", /* TT_MKAY */
"ALL OF", /* TT_ALLOF */
"ANY OF", /* TT_ANYOF */
"BOTH SAEM", /* TT_BOTHSAEM */
"DIFFRINT", /* TT_DIFFRINT */
"MAEK", /* TT_MAEK */
"A", /* TT_A */
"IS NOW A", /* TT_ISNOWA */
"VISIBLE", /* TT_VISIBLE */
"SMOOSH", /* TT_SMOOSH */
"!", /* TT_BANG */
"GIMMEH", /* TT_GIMMEH */
"O RLY?", /* TT_ORLY */
"YA RLY", /* TT_YARLY */
"MEBBE", /* TT_MEBBE */
"NO WAI", /* TT_NOWAI */
"OIC", /* TT_OIC */
"WTF?", /* TT_WTF */
"OMG", /* TT_OMG */
"OMGWTF", /* TT_OMGWTF */
"GTFO", /* TT_GTFO */
"IM IN YR", /* TT_IMINYR */
"UPPIN", /* TT_UPPIN */
"NERFIN", /* TT_NERFIN */
"YR", /* TT_YR */
"TIL", /* TT_TIL */
"WILE", /* TT_WILE */
"IM OUTTA YR", /* TT_IMOUTTAYR */
"HOW IZ", /* TT_HOWIZ */
"IZ", /* TT_IZ */
"IF U SAY SO", /* TT_IFUSAYSO */
"FOUND YR", /* TT_FOUNDYR */
"SRS", /* TT_SRS */
"", /* TT_ENDOFTOKENS */
};
/** Stores the data associated with a Token structure. */
typedef union {
int i; /**< Integer data. */
@ -186,7 +118,7 @@ int isString(const char *);
int isIdentifier(const char *);
Token *createToken(TokenType, const char *, const char *, unsigned int);
void deleteToken(Token *);
Token *addToken(Token ***, unsigned int *, Token*);
int addToken(Token ***, unsigned int *, Token*);
void deleteTokens(Token **);
unsigned int acceptLexemes(LexemeList *, unsigned int, const char *);
Token *isKeyword(LexemeList *, unsigned int *);

View File

@ -36870,7 +36870,7 @@ int binarySearch(const char **strings, /**< [in] A pointer to an array of charac
int end, /**< [in] The end of the range to search through. */
const char *find) /**< [in] The entry to search for. */
{
unsigned int midpoint;
int midpoint;
int cmp;
if (end < start) return -1;
midpoint = ((end - start) / 2) + start;
@ -36906,8 +36906,8 @@ long convertNormativeNameToCodePoint(const char *name) /**< [in] A pointer to a
* \return The number of characters in the converted multi-byte character.
*
* \retval 0 An invalid Unicode code point was supplied. */
unsigned int convertCodePointToUTF8(long codepoint, /**< [in] The Unicode code point to convert to UTF-8. */
char *out) /**< [out] A pointer to the location to store the resulting UTF-8 bytes. */
size_t convertCodePointToUTF8(unsigned long codepoint, /**< [in] The Unicode code point to convert to UTF-8. */
char *out) /**< [out] A pointer to the location to store the resulting UTF-8 bytes. */
{
/* Out of range */
if (codepoint > 0x10FFFF) {
@ -36916,36 +36916,36 @@ unsigned int convertCodePointToUTF8(long codepoint, /**< [in] The Unicode code p
}
/* U+010000 to U+10FFFF */
else if (codepoint >= 0x010000) {
char x1 = codepoint & 0x003F;
char x2 = (codepoint & 0x00C0) >> 6;
char y1 = (codepoint & 0x0F00) >> 8;
char y2 = (codepoint & 0xF000) >> 12;
char z1 = (codepoint & 0x30000) >> 16;
char z2 = (codepoint & 0x1C0000) >> 18;
out[0] = 0xF0 | z2;
out[1] = 0x80 | (z1 << 4) | y2;
out[2] = 0x80 | (y1 << 2) | x2;
out[3] = 0x80 | x1;
char x1 = (char)(codepoint & 0x003F);
char x2 = (char)((codepoint & 0x00C0) >> 6);
char y1 = (char)((codepoint & 0x0F00) >> 8);
char y2 = (char)((codepoint & 0xF000) >> 12);
char z1 = (char)((codepoint & 0x30000) >> 16);
char z2 = (char)((codepoint & 0x1C0000) >> 18);
out[0] = (char)(0xF0 | z2);
out[1] = (char)(0x80 | (z1 << 4) | y2);
out[2] = (char)(0x80 | (y1 << 2) | x2);
out[3] = (char)(0x80 | x1);
return 4;
}
/* U+0800 to U+FFFF */
else if (codepoint >= 0x0800) {
char x1 = codepoint & 0x003F;
char x2 = (codepoint & 0x00C0) >> 6;
char y1 = (codepoint & 0x0F00) >> 8;
char y2 = (codepoint & 0xF000) >> 12;
out[0] = 0xE0 | y2;
out[1] = 0x80 | (y1 << 2) | x2;
out[2] = 0x80 | x1;
char x1 = (char)(codepoint & 0x003F);
char x2 = (char)((codepoint & 0x00C0) >> 6);
char y1 = (char)((codepoint & 0x0F00) >> 8);
char y2 = (char)((codepoint & 0xF000) >> 12);
out[0] = (char)(0xE0 | y2);
out[1] = (char)(0x80 | (y1 << 2) | x2);
out[2] = (char)(0x80 | x1);
return 3;
}
/* U+0080 to U+07FF */
else if (codepoint & 0x0080) {
char x1 = codepoint & 0x3F;
char x2 = (codepoint & 0x00C0) >> 6;
char y = (codepoint & 0x0700) >> 8;
out[0] = 0xC0 | (y << 2) | x2;
out[1] = 0x80 | x1;
char x1 = (char)(codepoint & 0x3F);
char x2 = (char)((codepoint & 0x00C0) >> 6);
char y = (char)((codepoint & 0x0700) >> 8);
out[0] = (char)(0xC0 | (y << 2) | x2);
out[1] = (char)(0x80 | x1);
return 2;
}
/* U+0080 to U+07FF */

View File

@ -1,5 +1,5 @@
/** Data and functions for converting from Unicode normative names to
* codepoints.
* code points.
*
* \file unicode.h
*
@ -15,6 +15,6 @@
int binarySearch(const char **, int, int, const char *);
long convertNormativeNameToCodePoint(const char *);
unsigned int convertCodePointToUTF8(long, char *);
size_t convertCodePointToUTF8(unsigned long, char *);
#endif /* __UNICODE_H_ */