Merged SRS and de-linted code

This commit is contained in:
Justin J. Meza 2010-12-21 03:20:31 -05:00
parent 233aa9481d
commit 78456aabfd
29 changed files with 725 additions and 301 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

@ -230,9 +230,68 @@ void deleteReturnObject(ReturnObject *object) /**< [in,out] The ReturnObject str
free(object);
}
/** 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) goto resolveIdentifierNameAbort;
if (id->type == IT_DIRECT) {
/* 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);
/* 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:%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.
@ -242,7 +301,7 @@ void deleteReturnObject(ReturnObject *object) /**< [in,out] The ReturnObject str
* \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) {
@ -276,8 +335,7 @@ void deleteScopeObject(ScopeObject *scope) /**< [in,out] The ScopeObject structu
unsigned int n;
if (!scope) return;
for (n = 0; n < scope->numvals; n++) {
/* The individual names are pointers to existing IdentifierNode
* structures, so don't free them here. */
free(scope->names[n]);
deleteValueObject(scope->values[n]);
}
free(scope->names);
@ -306,15 +364,24 @@ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject str
IdentifierNode *target) /**< [in] The name of the value to find. */
{
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;
/* Check for value in current scope */
for (n = 0; n < current->numvals; n++) {
if (!strcmp(current->names[n]->image, target->image))
if (!strcmp(current->names[n], name)) {
free(name);
return current->values[n];
}
}
} while ((current = current->parent));
free(name);
return NULL;
}
@ -338,11 +405,20 @@ ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObjec
IdentifierNode *target) /**< [in] The name of the value to find. */
{
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]->image, target->image))
if (!strcmp(scope->names[n], name)) {
free(name);
return scope->values[n];
}
}
free(name);
return NULL;
}
@ -367,20 +443,28 @@ 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) {
perror("realloc");
free(name);
return NULL;
}
mem2 = realloc(scope->values, sizeof(ValueObject *) * newnumvals);
if (!mem2) {
perror("realloc");
free(name);
return NULL;
}
scope->names = mem1;
scope->values = mem2;
scope->names[scope->numvals] = target;
scope->names[scope->numvals] = name;
scope->values[scope->numvals] = createNilValueObject();
if (!scope->values[scope->numvals])
return NULL;
@ -414,12 +498,19 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to
ValueObject *value) /**< [in] A pointer to the ValueObject structure containing the value to copy for the update. */
{
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;
/* Check for existing value in current scope */
for (n = 0; n < current->numvals; n++) {
if (!strcmp(current->names[n]->image, target->image)) {
if (!strcmp(current->names[n], name)) {
free(name);
/* Wipe out the old value */
deleteValueObject(current->values[n]);
/* Assign the new value */
@ -431,7 +522,8 @@ ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to
}
}
} while ((current = current->parent));
fprintf(stderr, "%s:%d: unable to store variable at: %s\n", target->fname, target->line, target->image);
fprintf(stderr, "%s:%u: unable to store variable at: %s\n", target->fname, target->line, name);
free(name);
return NULL;
}
@ -451,15 +543,22 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco
IdentifierNode *target) /**< [in] A pointer to the IdentifierNode structure containing the name of the value to delete. */
{
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;
/* Check for existing value in current scope */
for (n = 0; n < current->numvals; n++) {
if (!strcmp(current->names[n]->image, target->image)) {
if (!strcmp(current->names[n], name)) {
unsigned int i;
unsigned int newnumvals = scope->numvals - 1;
void *mem1 = NULL, *mem2 = NULL;
free(name);
/* Don't delete anything in the names table
* because it's just pointers to IdentifierNode
* structures in the parse tree. */
@ -488,6 +587,7 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco
}
}
} while ((current = current->parent));
free(name);
}
/** Checks if a string of characters follows the format for a number.
@ -496,8 +596,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 */
@ -517,8 +617,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 */
@ -687,7 +787,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 */
@ -700,9 +800,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
@ -734,7 +838,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 */
@ -747,7 +851,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;
@ -758,12 +866,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
@ -793,7 +908,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:
@ -808,7 +923,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;
@ -819,12 +938,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
@ -892,7 +1018,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);
@ -920,12 +1047,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)) {
@ -936,7 +1070,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;
@ -955,22 +1094,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) {
@ -988,9 +1135,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"))
@ -1000,7 +1154,7 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st
/* Create a new IdentifierNode
* structure and lookup its
* value */
target = createIdentifierNode(image, NULL, 0);
target = createIdentifierNode(IT_DIRECT, image, NULL, 0);
if (!target) {
free(temp);
return NULL;
@ -1043,9 +1197,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.
@ -1157,14 +1316,22 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t
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);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: undefined function at: %s\n", id->fname, id->line, name);
free(name);
}
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);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: incorrect number of arguments supplied to: %s\n", id->fname, id->line, name);
free(name);
}
deleteScopeObject(outer);
return NULL;
}
@ -1243,7 +1410,11 @@ ValueObject *interpretIdentifierExprNode(ExprNode *node, /**< [in] A pointer
ValueObject *val = getScopeValue(scope, node->expr);
if (!val) {
IdentifierNode *id = (IdentifierNode *)(node->expr);
fprintf(stderr, "%s:%d: variable does not exist at: %s\n", id->fname, id->line, id->image);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: variable does not exist at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
}
return copyValueObject(val);
@ -1502,7 +1673,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.
@ -1522,7 +1693,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.
@ -1542,7 +1713,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.
@ -1564,11 +1735,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.
@ -1588,7 +1759,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.
@ -1608,7 +1779,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.
@ -1628,11 +1799,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.
@ -1737,7 +1908,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.
@ -1757,7 +1928,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.
@ -1781,7 +1952,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.
@ -1859,7 +2030,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;
}
@ -1920,11 +2091,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
@ -2096,7 +2267,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) {
@ -2175,7 +2346,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.
@ -2190,7 +2361,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.
@ -2205,7 +2376,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.
@ -2220,7 +2391,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.
@ -2234,7 +2405,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.
@ -2248,7 +2419,7 @@ 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.
@ -2608,7 +2779,11 @@ ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to t
ValueObject *cast = NULL;
if (!val) {
IdentifierNode *id = (IdentifierNode *)(stmt->target);
fprintf(stderr, "%s:%d: variable does not exist at: %s\n", id->fname, id->line, id->image);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: variable does not exist at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
}
switch(stmt->newtype->type) {
@ -2711,7 +2886,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;
@ -2719,7 +2894,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;
@ -2731,7 +2906,7 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to
}
temp = mem;
}
temp[cur] = c;
temp[cur] = (char)c;
cur++;
}
temp[cur] = '\0';
@ -2815,7 +2990,11 @@ ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A point
ValueObject *init = NULL;
if (getLocalScopeValue(scope, stmt->target)) {
IdentifierNode *id = (IdentifierNode *)(stmt->target);
fprintf(stderr, "%s:%d: redefinition of existing variable at: %s\n", id->fname, id->line, id->image);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: redefinition of existing variable at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
}
if (stmt->expr)
@ -2991,7 +3170,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:
@ -3291,7 +3470,11 @@ ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see no
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);
char *name = resolveIdentifierName(id, scope);
if (name) {
fprintf(stderr, "%s:%u: function name already used by existing variable at: %s\n", id->fname, id->line, name);
free(name);
}
return NULL;
}
init = createFunctionValueObject(stmt);

View File

@ -88,7 +88,7 @@ typedef struct scopeobject {
struct scopeobject *parent; /**< A pointer to the parent ScopeObject. */
ValueObject *impvar; /**< A pointer to the ValueObject representing the implicit variable for this scope. */
unsigned int numvals; /**< The number of ValueObject structures in \a values. */
IdentifierNode **names; /**< A pointer to the IdentifierNode structures naming the values in the scope. */
char **names; /**< A pointer to the array of character strings naming the values in the scope. */
ValueObject **values; /**< A pointer to an array of ValueObject structures in the scope. */
} ScopeObject;
@ -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;

18
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;
@ -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';

263
parser.c
View File

@ -112,7 +112,10 @@ BlockNodeList *createBlockNodeList(void)
* \a list will be updated accordingly.
*
* \retval 0 realloc was unable to allocate memory.
* \retval 1 \a node was added to \a list. */
* \retval 1 \a node was added to \a list.
*
* \see createBlockNodeList(void)
* \see deleteBlockNodeList(BlockNodeList *) */
int addBlockNode(BlockNodeList *list, /**< [in,out] A pointer to the BlockNodeList structure to add \a node to. */
BlockNode *node) /**< [in] A pointer to the BlockNode structure to add to \a list. */
{
@ -245,9 +248,6 @@ void deleteConstantNode(ConstantNode *node) /**< [in,out] A pointer to the Const
}
/** Creates an IdentifierNode structure.
*
* \note \a image is \b copied for use within the structure so it must be freed
* by the caller.
*
* \return A pointer to an IdentifierNode structure with the desired
* properties.
@ -255,23 +255,25 @@ void deleteConstantNode(ConstantNode *node) /**< [in,out] A pointer to the Const
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteIdentifierNode(IdentifierNode *) */
IdentifierNode *createIdentifierNode(char *image, /**< [in] An array of characters that name the identifier. */
const char *fname, /**< [in] A pointer to the name of the file containing the identifier. */
unsigned int line) /**< [in] The line number from the source file that the identifier occurred on. */
IdentifierNode *createIdentifierNode(IdentifierType type, /**< [in] The type of IdentifierNode stored in \a id. */
void *id, /**< [in] A pointer to the stored identifier data. */
const char *fname, /**< [in] A pointer to the name of the file containing the identifier. */
unsigned int line) /**< [in] The line number from the source file that the identifier occurred on. */
{
IdentifierNode *p = malloc(sizeof(IdentifierNode));
if (!p) {
perror("malloc");
return NULL;
}
p->image = malloc(sizeof(char) * (strlen(image) + 1));
if (!p->image) {
free(p);
perror("malloc");
return NULL;
p->type = type;
p->id = id;
if (fname) {
p->fname = malloc(sizeof(char) * (strlen(fname) + 1));
strcpy(p->fname, fname);
}
else {
p->fname = NULL;
}
strcpy(p->image, image);
p->fname = fname;
p->line = line;
return p;
}
@ -287,7 +289,20 @@ IdentifierNode *createIdentifierNode(char *image, /**< [in] An array of ch
void deleteIdentifierNode(IdentifierNode *node) /**< [in,out] A pointer to the IdentifierNode structure to be deleted. */
{
if (!node) return;
free(node->image);
switch (node->type) {
case IT_DIRECT: {
free(node->id);
break;
}
case IT_INDIRECT: {
deleteExprNode(node->id);
break;
}
default:
fprintf(stderr, "Unable to delete unknown identifier type\n");
break;
}
if (node->fname) free(node->fname);
free(node);
}
@ -320,7 +335,10 @@ IdentifierNodeList *createIdentifierNodeList(void)
* \a list will be updated accordingly.
*
* \retval 0 realloc was unable to allocate memory.
* \retval 1 \a node was added to \a list. */
* \retval 1 \a node was added to \a list.
*
* \see createIdentifierNodeList(void)
* \see deleteIdentifierNodeList(IdentifierNodeList *) */
int addIdentifierNode(IdentifierNodeList *list, /**< [in,out] A pointer to the IdentifierNodeList structure to add \a node to. */
IdentifierNode *node) /**< [in] A pointer to the IdentifierNode structure to add to \a list. */
{
@ -530,7 +548,10 @@ StmtNodeList *createStmtNodeList(void)
* \a list will be updated accordingly.
*
* \retval 0 malloc was unable to allocate memory.
* \retval 1 \a node was added to \a list. */
* \retval 1 \a node was added to \a list.
*
* \see createStmtNodeList(void)
* \see deleteStmtNodeList(StmtNodeList *) */
int addStmtNode(StmtNodeList *list, /**< [in,out] A pointer to the StmtNodeList structure to add \a node to. */
StmtNode *node) /**< [in] A pointer to the StmtNode structure to add to \a list. */
{
@ -1123,7 +1144,10 @@ ExprNodeList *createExprNodeList(void)
* \a list will be updated accordingly.
*
* \retval 0 realloc was unable to allocate memory.
* \retval 1 \a node was added to \a list. */
* \retval 1 \a node was added to \a list.
*
* \see createExprNodeList(void)
* \see deleteExprNodeList(ExprNodeList *) */
int addExprNode(ExprNodeList *list, /**< [in,out] A pointer to the ExprNodeList structure to add \a node to. */
ExprNode *node) /**< [in] A pointer to the ExprNode structure to add to \a list. */
{
@ -1367,7 +1391,7 @@ int nextToken(Token ***tokenp, /**< [in] A pointer to the position of the next t
void error(const char *info, /**< [in] The array of characters to print. */
Token **tokens) /**< [in] A pointer to an array of tokens to parse. */
{
fprintf(stderr, "%s:%d: %s at: %s\n", (*tokens)->fname, (*tokens)->line, info, (*tokens)->image);
fprintf(stderr, "%s:%u: %s at: %s\n", (*tokens)->fname, (*tokens)->line, info, (*tokens)->image);
}
/** Parses a set of tokens into a ConstantNode structure. Parsing begins at the
@ -1451,7 +1475,7 @@ ConstantNode *parseConstantNode(Token ***tokenp)
}
/* String */
else if (peekToken(&tokens, TT_STRING)) {
unsigned int len = strlen((*tokens)->image);
size_t len = strlen((*tokens)->image);
data = malloc(sizeof(char) * (len - 1));
if (!data) {
perror("malloc");
@ -1606,6 +1630,12 @@ parseTypeNodeAbort: /* Exception handling */
* \see parseMainNode(Token **) */
IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */
{
/* For direct identifier */
char *temp = NULL;
/* For indirect identifier */
ExprNode *expr = NULL;
IdentifierNode *ret = NULL;
int status;
@ -1616,13 +1646,18 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to
shiftout();
#endif
/* Make sure there is an identifier to parse */
/* Direct identifier */
if (peekToken(&tokens, TT_IDENTIFIER)) {
#ifdef DEBUG
debug("IDENTIFIER");
debug("IT_DIRECT");
#endif
/* Copy the token image */
temp = malloc(sizeof(char) * (strlen((*tokens)->image) + 1));
if (!temp) goto parseIdentifierNodeAbort;
strcpy(temp, (*tokens)->image);
/* Create the new IdentifierNode structure */
ret = createIdentifierNode((*tokens)->image, (*tokens)->fname, (*tokens)->line);
ret = createIdentifierNode(IT_DIRECT, temp, (*tokens)->fname, (*tokens)->line);
if (!ret) goto parseIdentifierNodeAbort;
/* This should succeed; it was checked for above */
@ -1632,6 +1667,18 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to
goto parseIdentifierNodeAbort;
}
}
else if (acceptToken(&tokens, TT_SRS)) {
#ifdef DEBUG
debug("IT_INDIRECT");
#endif
/* Parse the expression representing the identifier */
expr = parseExprNode(&tokens);
if (!expr) goto parseIdentifierNodeAbort;
/* Create the new IdentifierNode structure */
ret = createIdentifierNode(IT_INDIRECT, expr, (*tokens)->fname, (*tokens)->line);
if (!ret) goto parseIdentifierNodeAbort;
}
else {
error("expected identifier", tokens);
}
@ -1649,6 +1696,13 @@ parseIdentifierNodeAbort: /* Exception handling */
/* Clean up any allocated structures */
if (ret) deleteIdentifierNode(ret);
else {
/* For indirect identifier */
if (expr) deleteExprNode(expr);
/* For direct identifier */
if (temp) free(temp);
}
return NULL;
}
@ -1696,7 +1750,7 @@ ExprNode *parseCastExprNode(Token ***tokenp)
if (!target) goto parseCastExprNodeAbort;
/* Optionally parse the cast-to token */
acceptToken(&tokens, TT_A);
status = acceptToken(&tokens, TT_A);
/* Parse the type to cast to */
newtype = parseTypeNode(&tokens);
@ -1748,7 +1802,6 @@ ExprNode *parseConstantExprNode(Token ***tokenp)
{
ConstantNode *node = NULL;
ExprNode *ret = NULL;
int status;
/* Work from a copy of the token stream in case something goes wrong */
Token **tokens = *tokenp;
@ -1802,7 +1855,6 @@ ExprNode *parseIdentifierExprNode(Token ***tokenp)
{
IdentifierNode *node = NULL;
ExprNode *ret = NULL;
int status;
/* Work from a copy of the token stream in case something goes wrong */
Token **tokens = *tokenp;
@ -1967,9 +2019,9 @@ parseFuncCallExprNodeAbort: /* Exception handling */
ExprNode *parseOpExprNode(Token ***tokenp)
{
enum ArityType {
AR_UNARY,
AR_BINARY,
AR_NARY,
AT_UNARY,
AT_BINARY,
AT_NARY
};
enum ArityType arity;
ExprNodeList *args = NULL;
@ -1985,7 +2037,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
/* Unary operations */
if (acceptToken(&tokens, TT_NOT)) {
type = OP_NOT;
arity = AR_UNARY;
arity = AT_UNARY;
#ifdef DEBUG
debug("ET_OP (OP_NOT)");
#endif
@ -1993,84 +2045,84 @@ ExprNode *parseOpExprNode(Token ***tokenp)
/* Binary operations */
else if (acceptToken(&tokens, TT_SUMOF)) {
type = OP_ADD;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_ADD)");
#endif
}
else if(acceptToken(&tokens, TT_DIFFOF)) {
type = OP_SUB;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_SUB)");
#endif
}
else if(acceptToken(&tokens, TT_PRODUKTOF)) {
type = OP_MULT;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_MULT)");
#endif
}
else if(acceptToken(&tokens, TT_QUOSHUNTOF)) {
type = OP_DIV;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_DIV)");
#endif
}
else if(acceptToken(&tokens, TT_MODOF)) {
type = OP_MOD;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_MOD)");
#endif
}
else if(acceptToken(&tokens, TT_BIGGROF)) {
type = OP_MAX;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_MAX)");
#endif
}
else if(acceptToken(&tokens, TT_SMALLROF)) {
type = OP_MIN;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_MIN)");
#endif
}
else if(acceptToken(&tokens, TT_BOTHOF)) {
type = OP_AND;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_AND)");
#endif
}
else if(acceptToken(&tokens, TT_EITHEROF)) {
type = OP_OR;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_OR)");
#endif
}
else if(acceptToken(&tokens, TT_WONOF)) {
type = OP_XOR;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_XOR)");
#endif
}
else if(acceptToken(&tokens, TT_BOTHSAEM)) {
type = OP_EQ;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_EQ)");
#endif
}
else if(acceptToken(&tokens, TT_DIFFRINT)) {
type = OP_NEQ;
arity = AR_BINARY;
arity = AT_BINARY;
#ifdef DEBUG
debug("ET_OP (OP_NEQ)");
#endif
@ -2078,21 +2130,21 @@ ExprNode *parseOpExprNode(Token ***tokenp)
/* N-ary operators */
else if (acceptToken(&tokens, TT_ALLOF)) {
type = OP_AND;
arity = AR_NARY;
arity = AT_NARY;
#ifdef DEBUG
debug("ET_OP (OP_AND)");
#endif
}
else if(acceptToken(&tokens, TT_ANYOF)) {
type = OP_OR;
arity = AR_NARY;
arity = AT_NARY;
#ifdef DEBUG
debug("ET_OP (OP_OR)");
#endif
}
else if(acceptToken(&tokens, TT_SMOOSH)) {
type = OP_CAT;
arity = AR_NARY;
arity = AT_NARY;
#ifdef DEBUG
debug("ET_OP (OP_CAT)");
#endif
@ -2107,7 +2159,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
if (!args) goto parseOpExprNodeAbort;
/* Parse the operation arguments */
if (arity == AR_UNARY) {
if (arity == AT_UNARY) {
/* Parse the argument */
arg = parseExprNode(&tokens);
if (!arg) goto parseOpExprNodeAbort;
@ -2117,7 +2169,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
if (!status) goto parseOpExprNodeAbort;
arg = NULL;
}
else if (arity == AR_BINARY) {
else if (arity == AT_BINARY) {
/* Parse the first argument */
arg = parseExprNode(&tokens);
if (!arg) goto parseOpExprNodeAbort;
@ -2128,7 +2180,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
arg = NULL;
/* Optionally parse the argument-separator token */
acceptToken(&tokens, TT_AN);
status = acceptToken(&tokens, TT_AN);
/* Parse the second argument */
arg = parseExprNode(&tokens);
@ -2139,7 +2191,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
if (!status) goto parseOpExprNodeAbort;
arg = NULL;
}
else if (arity == AR_NARY) {
else if (arity == AT_NARY) {
/* Parse as many arguments as possible */
while (1) {
/* Parse an argument */
@ -2155,7 +2207,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
if (acceptToken(&tokens, TT_MKAY)) break;
/* Optionally parse the argument-separator token */
acceptToken(&tokens, TT_AN);
status = acceptToken(&tokens, TT_AN);
}
}
@ -2227,7 +2279,8 @@ ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position
ret = parseFuncCallExprNode(tokenp);
}
/* Identifier */
else if (peekToken(&tokens, TT_IDENTIFIER)) {
else if (peekToken(&tokens, TT_IDENTIFIER)
|| peekToken(&tokens, TT_SRS)) {
ret = parseIdentifierExprNode(tokenp);
}
/* Operation */
@ -2419,7 +2472,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
arg = NULL;
/* Arguments can optionally be separated by an AN keyword */
acceptToken(&tokens, TT_AN);
status = acceptToken(&tokens, TT_AN);
} while (!peekToken(&tokens, TT_NEWLINE)
&& !peekToken(&tokens, TT_BANG));
@ -2988,7 +3041,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
if (((c->type == CT_BOOLEAN || c->type == CT_INTEGER)
&& c->data.i == test->data.i)
|| (c->type == CT_FLOAT
&& c->data.f == test->data.f)
&& fabs(c->data.f - test->data.f) < FLT_EPSILON)
|| (c->type == CT_STRING
&& !strcmp(c->data.s, test->data.s))) {
error("OMG literal must be unique", tokens);
@ -3259,6 +3312,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
IdentifierNode *name2 = NULL;
LoopStmtNode *stmt = NULL;
ExprNodeList *args = NULL;
char *id = NULL;
/* For increment and decrement loops */
IdentifierNode *varcopy = NULL;
@ -3298,6 +3352,10 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
/* Parse the loop name */
name1 = parseIdentifierNode(&tokens);
if (!name1) goto parseLoopStmtNodeAbort;
else if (name1->type != IT_DIRECT) {
error("expected loop name", tokens);
goto parseLoopStmtNodeAbort;
}
/* Check if an increment or decrement loop */
if (peekToken(&tokens, TT_UPPIN) || peekToken(&tokens, TT_NERFIN)) {
@ -3339,8 +3397,12 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
shiftin();
#endif
/* Make a copy of the variable for use as a function argument */
varcopy = createIdentifierNode(var->image, var->fname, var->line);
id = malloc(sizeof(char) * (strlen(var->id) + 1));
if (!id) goto parseLoopStmtNodeAbort;
strcpy(id, var->id);
varcopy = createIdentifierNode(IT_DIRECT, id, var->fname, var->line);
if (!varcopy) goto parseLoopStmtNodeAbort;
id = NULL;
/* Package the variable into an identifier expression */
arg1 = createExprNode(ET_IDENTIFIER, varcopy);
@ -3424,8 +3486,12 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
arg = NULL;
/* Copy the identifier to make it the loop variable */
var = createIdentifierNode(temp->image, temp->fname, temp->line);
id = malloc(sizeof(char) * (strlen(temp->id) + 1));
if (!id) goto parseLoopStmtNodeAbort;
strcpy(id, temp->id);
var = createIdentifierNode(IT_DIRECT, id, temp->fname, temp->line);
if (!var) goto parseLoopStmtNodeAbort;
id = NULL;
/* Check for unary function */
status = acceptToken(&tokens, TT_MKAY);
@ -3503,9 +3569,13 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
/* Parse the end-of-loop name */
name2 = parseIdentifierNode(&tokens);
if (!name2) goto parseLoopStmtNodeAbort;
else if (name2->type != IT_DIRECT) {
error("expected loop name", tokens);
goto parseLoopStmtNodeAbort;
}
/* Make sure the beginning-of-loop and end-of-loop names match */
if (strcmp(name1->image, name2->image)) {
if (strcmp((char *)(name1->id), (char *)(name2->id))) {
error("expected matching loop name", tokens);
goto parseLoopStmtNodeAbort;
}
@ -3546,6 +3616,7 @@ parseLoopStmtNodeAbort: /* Exception handling */
if (update) deleteExprNode(update);
if (var) deleteIdentifierNode(var);
if (name1) deleteIdentifierNode(name1);
if (id) free(id);
/* For increment and decrement loops */
if (op) deleteOpExprNode(op);
@ -3646,6 +3717,8 @@ parseDeallocationStmtNodeAbort: /* Exception handling */
else {
if (target) deleteIdentifierNode(target);
}
return NULL;
}
/** Parses a set of tokens into a StmtNode structure containing a
@ -3783,6 +3856,8 @@ parseFuncDefStmtNodeAbort: /* Exception handling */
if (name) deleteIdentifierNode(name);
if (scope) deleteIdentifierNode(scope);
}
return NULL;
}
/** Parses a set of tokens into a StmtNode structure. Parsing begins at the
@ -3815,9 +3890,64 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position
shiftout();
#endif
/* Casting */
if (nextToken(&tokens, TT_ISNOWA)) {
ret = parseCastStmtNode(tokenp);
/* Parse context-sensitive expressions */
if (peekToken(&tokens, TT_IDENTIFIER)
|| peekToken(&tokens, TT_SRS)) {
IdentifierNode *id = NULL;
/* Remove the identifier from the token stream */
id = parseIdentifierNode(&tokens);
if (!id) return NULL;
/* We do not need to hold onto it */
deleteIdentifierNode(id);
/* Casting */
if (peekToken(&tokens, TT_ISNOWA)) {
ret = parseCastStmtNode(tokenp);
}
/* Assignment */
else if (peekToken(&tokens, TT_R)) {
ret = parseAssignmentStmtNode(tokenp);
}
/* Variable declaration */
else if (peekToken(&tokens, TT_HASA)) {
ret = parseDeclarationStmtNode(tokenp);
}
/* Deallocation */
else if (peekToken(&tokens, TT_RNOOB)) {
ret = parseDeallocationStmtNode(tokenp);
}
/* Bare identifier expression */
else {
/* Reset state and continue parsing */
tokens = *tokenp;
/* Parse the expression */
expr = parseExprNode(&tokens);
if (!expr) return NULL;
#ifdef DEBUG
debug("ST_EXPR");
#endif
/* The expression should appear on its own line */
if (!acceptToken(&tokens, TT_NEWLINE)) {
error("expected end of expression", tokens);
deleteExprNode(expr);
return NULL;
}
/* Create the new StmtNode structure */
ret = createStmtNode(ST_EXPR, expr);
if (!ret) {
deleteExprNode(expr);
return NULL;
}
/* Since we're successful, update the token stream */
*tokenp = tokens;
}
}
/* Print */
else if (peekToken(&tokens, TT_VISIBLE)) {
@ -3827,14 +3957,6 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position
else if (peekToken(&tokens, TT_GIMMEH)) {
ret = parseInputStmtNode(tokenp);
}
/* Assignment */
else if (nextToken(&tokens, TT_R)) {
ret = parseAssignmentStmtNode(tokenp);
}
/* Variable declaration */
else if (nextToken(&tokens, TT_HASA)) {
ret = parseDeclarationStmtNode(tokenp);
}
/* If/then/else */
else if (peekToken(&tokens, TT_ORLY)) {
ret = parseIfThenElseStmtNode(tokenp);
@ -3855,15 +3977,11 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position
else if (peekToken(&tokens, TT_IMINYR)) {
ret = parseLoopStmtNode(tokenp);
}
/* Deallocation */
else if (nextToken(&tokens, TT_RNOOB)) {
ret = parseDeallocationStmtNode(tokenp);
}
/* Function definition */
else if (peekToken(&tokens, TT_HOWIZ)) {
ret = parseFuncDefStmtNode(tokenp);
}
/* Expression evaluation */
/* Bare expression */
else if ((expr = parseExprNode(&tokens))) {
int status;
@ -3879,6 +3997,7 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position
return NULL;
}
/* Create the new StmtNode structure */
ret = createStmtNode(ST_EXPR, expr);
if (!ret) {
deleteExprNode(expr);

View File

@ -41,7 +41,7 @@
* ConstantNode ::= Boolean | Integer | Float | String
*
* \par
* IdentifierNode ::= Identifier
* IdentifierNode ::= Identifier | \c TT_SRS ExprNode
*
* \par
* TypeNode ::= \c TT_NOOB | \c TT_TROOF | \c TT_NUMBR | \c TT_NUMBAR | \c TT_YARN
@ -174,33 +174,13 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include "tokenizer.h"
#undef DEBUG
/** Stores an identifier. An identifier is the string of characters that are
* used to uniquely name a particular variable.
*
* \see createIdentifierNode(char *, const char *, unsigned int)
* \see deleteIdentifierNode(IdentifierNode *) */
typedef struct {
char *image; /**< An array of characters that name the identifier. */
const char *fname; /**< A pointer to the name of the file containing the identifier. */
unsigned int line; /**< The line number from the source file that the identifier occurred on. */
} IdentifierNode;
/** Stores a list of identifiers. This structure allows sets of identifiers
* to be grouped together.
*
* \see createIdentifierNodeList(void)
* \see addIdentifierNode(IdentifierNodeList *, IdentifierNode *)
* \see deleteIdentifierNodeList(IdentifierNodeList *) */
typedef struct {
unsigned int num; /**< The number of IdentifierNode structures stored. */
IdentifierNode **ids; /**< A pointer to the array of IdentifierNode structures. */
} IdentifierNodeList;
/** Denotes the type of statement a StmtNode stores. */
typedef enum {
ST_CAST, /**< A CastStmtNode structure. */
@ -270,6 +250,35 @@ typedef struct {
ExprNode **exprs; /**< A pointer to an array of ExprNode structures. */
} ExprNodeList;
/** Denotes the type of identifier an IdentifierNode is. */
typedef enum {
IT_DIRECT, /**< A direct IdentifierNode structure. */
IT_INDIRECT /**< An indirect IdentifierNode structure. */
} IdentifierType;
/** Stores an identifier. An identifier either directly or indirectly names
* particular variable.
*
* \see createIdentifierNode(IdentifierType, void *)
* \see deleteIdentifierNode(IdentifierNode *) */
typedef struct {
IdentifierType type; /**< The type of identifier stored in \a id. */
void *id; /**< The identifier data stored. */
char *fname; /**< A pointer to the name of the file containing the identifier. */
unsigned int line; /**< The line number from the source file that the identifier occurred on. */
} IdentifierNode;
/** Stores a list of identifiers. This structure allows sets of identifiers
* to be grouped together.
*
* \see createIdentifierNodeList(void)
* \see addIdentifierNode(IdentifierNodeList *, IdentifierNode *)
* \see deleteIdentifierNodeList(IdentifierNodeList *) */
typedef struct {
unsigned int num; /**< The number of IdentifierNode structures stored. */
IdentifierNode **ids; /**< A pointer to the array of IdentifierNode structures. */
} IdentifierNodeList;
/** Stores a a block of code. A block of code consists of a set of statements.
*
* \see createBlockNode(StmtNodeList *)
@ -531,7 +540,7 @@ BlockNodeList *createBlockNodeList(void);
int addBlockNode(BlockNodeList *, BlockNode *);
void deleteBlockNodeList(BlockNodeList *);
IdentifierNode *createIdentifierNode(char *, const char *, unsigned int);
IdentifierNode *createIdentifierNode(IdentifierType, void *, const char *, unsigned int);
void deleteIdentifierNode(IdentifierNode *);
TypeNode *createTypeNode(ConstantType);
@ -605,11 +614,13 @@ 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 ***);

View File

@ -0,0 +1,9 @@
HAI 1.3
I HAS A var1 ITZ 1
I HAS A var2 ITZ 2.345
I HAS A var3 ITZ "67890"
I HAS A name ITZ "var"
VISIBLE SRS "var1"
VISIBLE SRS SMOOSH name AN SUM OF 1 AN 1 MKAY
VISIBLE SRS ":{name}3"
KTHXBYE

View File

@ -0,0 +1,3 @@
1
2.34
67890

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for variable output.

View File

@ -0,0 +1,5 @@
HAI 1.3
I HAS A name ITZ "var"
I HAS A SRS name ITZ 1
VISIBLE var
KTHXBYE

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for variable initialization.

View File

@ -0,0 +1,6 @@
HAI 1.3
I HAS A name ITZ "var"
I HAS A var ITZ 1
SRS name R 2.345
VISIBLE var
KTHXBYE

View File

@ -0,0 +1 @@
2.34

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for variable assignment.

View File

@ -0,0 +1,5 @@
HAI 1.3
I HAS A name ITZ "var"
I HAS A SRS name ITZ A NUMBR
VISIBLE var
KTHXBYE

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for variable type initialization.

View File

@ -0,0 +1,17 @@
HAI 1.3
I HAS A var1
I HAS A var2 ITZ WIN
I HAS A var3 ITZ 1
I HAS A var4 ITZ 2.345
I HAS A var5 ITZ "Lorem ipsum dolor sit."
SRS "var1" R NOOB
SRS "var2" R NOOB
SRS "var3" R NOOB
SRS "var4" R NOOB
SRS "var5" R NOOB
VISIBLE SUM OF 0 AN NOT var1
VISIBLE SUM OF 0 AN NOT var2
VISIBLE SUM OF 0 AN NOT var3
VISIBLE SUM OF 0 AN NOT var4
VISIBLE SUM OF 0 AN NOT var5
KTHXBYE

View File

@ -0,0 +1,5 @@
1
1
1
1
1

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for variable deallocation.

View File

@ -0,0 +1,15 @@
HAI 1.3
I HAS A name1 ITZ "fun"
I HAS A name2 ITZ "arg"
HOW IZ I SRS SMOOSH name1 AN 1 MKAY
VISIBLE "a"
IF U SAY SO
HOW IZ I SRS SMOOSH name1 AN 2 MKAY YR SRS name2
VISIBLE SRS name2
IF U SAY SO
I IZ SRS SMOOSH name1 AN 1 MKAY MKAY
I IZ SRS SMOOSH name1 AN 2 MKAY YR "b" MKAY
KTHXBYE

View File

@ -0,0 +1,2 @@
a
b

View File

@ -0,0 +1,3 @@
This test checks the functionality of the indirect identifier keyword, ``SRS''
to make sure it allows variable lookup using a provided string or expression
evaluated as a string for function declarations and calls.

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
@ -145,20 +215,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 +235,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 +268,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 +304,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 +342,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 +407,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,
@ -91,78 +93,10 @@ typedef enum {
TT_IZ,
TT_IFUSAYSO,
TT_FOUNDYR,
TT_SRS,
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 */
"", /* TT_ENDOFTOKENS */
};
/** Stores the data associated with a Token structure. */
typedef union {
int i; /**< Integer data. */
@ -184,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

@ -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_ */