Merged cleaned up source code
This commit is contained in:
commit
977e3dfde5
6
Makefile
6
Makefile
|
@ -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/
|
||||
|
|
336
interpreter.c
336
interpreter.c
|
@ -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;
|
||||
|
|
|
@ -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
19
lexer.c
|
@ -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
20
main.c
|
@ -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';
|
||||
|
||||
|
|
29
parser.h
29
parser.h
|
@ -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__ */
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
HAI 1.3
|
||||
CAN HAS STDIO?
|
||||
KTHXBYE
|
|
@ -0,0 +1 @@
|
|||
This test checks that the include statement ``CAN HAS STDIO?'' is ignored.
|
118
tokenizer.c
118
tokenizer.c
|
@ -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) {
|
||||
|
|
76
tokenizer.h
76
tokenizer.h
|
@ -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 *);
|
||||
|
|
50
unicode.c
50
unicode.c
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue