From 0d060b7ef6ea3cdd3ae505f41826d96d3ca12070 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sat, 28 Jan 2012 14:54:41 +1000 Subject: Add some of the flow control stuff, still needs lots of work. --- LuaSL/src/LuaSL_LSL_tree.h | 20 +-- LuaSL/src/LuaSL_compile.c | 306 ++++++++++++++++++++++++++++++++++------- LuaSL/src/LuaSL_lemon_yaccer.y | 28 ++-- 3 files changed, 279 insertions(+), 75 deletions(-) (limited to 'LuaSL/src') diff --git a/LuaSL/src/LuaSL_LSL_tree.h b/LuaSL/src/LuaSL_LSL_tree.h index f2fccd0..349d74f 100644 --- a/LuaSL/src/LuaSL_LSL_tree.h +++ b/LuaSL/src/LuaSL_LSL_tree.h @@ -179,7 +179,7 @@ struct _LSL_Leaf LSL_Leaf *listValue; const char *stringValue; opType operationValue; - LSL_Parenthesis *parenthesis; + LSL_Parenthesis *parenthesis; LSL_Identifier *identifierValue; LSL_Statement *statementValue; LSL_Block *blockValue; @@ -208,17 +208,21 @@ struct _LSL_Identifier // For variables and function parameters. struct _LSL_Statement { Eina_Clist statement; // For block statement lists, this is the entry. - union - { +// union +// { LSL_Identifier *identifier; LSL_Parenthesis *parenthesis; - } stuff; // Nothing has an identifier AND parenthesis, and there will be LOTS of statements, so save some space. +// } stuff; // Nothing has an identifier AND parenthesis, and there will be LOTS of statements, so save some space. + // Damn, function identifiers do. LSL_Leaf *expressions; // A for statement will have three expressions, everything else has zero or one. - LSL_Block *block; + LSL_Leaf *block; LSL_Type type; // Expression type. /* -expr expr -Variable defines identifier, optional expr +LSL_Leaf *addStatement(LSL_Leaf *lval, LSL_Type type, LSL_Leaf *left, LSL_Leaf *expr, LSL_Leaf *right, LSL_Leaf *block); + +expr expr // Might be bogus, +Variable defines identifier, optional expr // For these we only store the variable leaf in expressions. +Function define identifier, block, parens // Also function params, but that's stored in the function anyway. state change identifier Labels identifier goto identifier @@ -376,7 +380,7 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, LSL_Leaf *addParameter(LuaSL_compiler *compiler, LSL_Leaf *type, LSL_Leaf *newParam); LSL_Leaf *addParenthesis(LSL_Leaf *lval, LSL_Leaf *expr, LSL_Type type, LSL_Leaf *rval); LSL_Leaf *addState(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf *block); -LSL_Leaf *addStatement(LSL_Leaf *lval, LSL_Type type, LSL_Leaf *expr); +LSL_Leaf *addStatement(LuaSL_compiler *compiler, LSL_Leaf *lval, LSL_Type type, LSL_Leaf *left, LSL_Leaf *expr, LSL_Leaf *right, LSL_Leaf *block, LSL_Leaf *identifier); LSL_Leaf *addTypecast(LSL_Leaf *lval, LSL_Leaf *type, LSL_Leaf *rval, LSL_Leaf *expr); LSL_Leaf *addVariable(LuaSL_compiler *compiler, LSL_Leaf *type, LSL_Leaf *identifier, LSL_Leaf *assignment, LSL_Leaf *expr); diff --git a/LuaSL/src/LuaSL_compile.c b/LuaSL/src/LuaSL_compile.c index c1a1a5e..8fc3cb5 100644 --- a/LuaSL/src/LuaSL_compile.c +++ b/LuaSL/src/LuaSL_compile.c @@ -551,15 +551,12 @@ LSL_Leaf *addFunction(LuaSL_compiler *compiler, LSL_Leaf *type, LSL_Leaf *identi LSL_Leaf *addFunctionBody(LuaSL_compiler *compiler, LSL_Leaf *function, LSL_Leaf *block) { - LSL_Leaf *statement = newLeaf(LSL_STATEMENT, NULL, NULL); + LSL_Leaf *statement = NULL; if (function) { function->value.functionValue->block = block; - if (statement) - { - addStatement(statement, LSL_FUNCTION, function); - } + statement = addStatement(compiler, NULL, LSL_FUNCTION, NULL, function, NULL, NULL, NULL); } return statement; @@ -639,19 +636,90 @@ LSL_Leaf *addState(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf *blo return identifier; } -LSL_Leaf *addStatement(LSL_Leaf *lval, LSL_Type type, LSL_Leaf *expr) +LSL_Leaf *addStatement(LuaSL_compiler *compiler, LSL_Leaf *lval, LSL_Type type, LSL_Leaf *left, LSL_Leaf *expr, LSL_Leaf *right, LSL_Leaf *block, LSL_Leaf *identifier) { + gameGlobals *game = compiler->game; LSL_Statement *stat = calloc(1, sizeof(LSL_Statement)); + if (NULL == lval) + lval = newLeaf(LSL_STATEMENT, NULL, NULL); + if (stat) { stat->type = type; stat->expressions = expr; + stat->block = block; eina_clist_element_init(&(stat->statement)); + if (identifier) + stat->identifier = identifier->value.identifierValue; + if (left) + { + LSL_Leaf *parens = addParenthesis(left, expr, LSL_TYPECAST_OPEN, right); + + if (parens) + stat->parenthesis = parens->value.parenthesis; + } + + switch (type) + { + case LSL_EXPRESSION : + { + break; + } + case LSL_FUNCTION : + { + break; + } + case LSL_DO : + { + break; + } + case LSL_FOR : + { + break; + } + case LSL_IF : + { + break; + } + case LSL_ELSE : + { + break; + } + case LSL_JUMP : + { + break; + } + case LSL_RETURN : + { + break; + } + case LSL_STATE_CHANGE : + { + break; + } + case LSL_WHILE : + { + stat->identifier = NULL; + // TODO - need to stash the while's white space somewhere. + break; + } + case LSL_IDENTIFIER : + { + break; + } + default : + { + PE("Should not be here %d.", type); + break; + } + } + if (lval) lval->value.statementValue = stat; } + return lval; } @@ -1028,7 +1096,60 @@ static LSL_Leaf *evaluateStatementToken(LSL_Leaf *content, LSL_Leaf *left, LSL_L if (content) { - result = evaluateLeaf(content->value.statementValue->expressions, left, right); + switch (content->value.statementValue->type) + { + case LSL_EXPRESSION : + { + result = evaluateLeaf(content->value.statementValue->expressions, left, right); + break; + } + case LSL_FUNCTION : + { + break; + } + case LSL_DO : + { + break; + } + case LSL_FOR : + { + break; + } + case LSL_IF : + { + break; + } + case LSL_ELSE : + { + break; + } + case LSL_JUMP : + { + break; + } + case LSL_RETURN : + { + break; + } + case LSL_STATE_CHANGE : + { + break; + } + case LSL_WHILE : + { + break; + } + case LSL_IDENTIFIER : + { + break; + } + default : + { +// PE("Should not be here %d.", type); + break; + } + } + if (result) { switch (result->basicType) @@ -1065,37 +1186,6 @@ static void outputLeaf(FILE *file, outputMode mode, LSL_Leaf *leaf) } } -static void outputBlockToken(FILE *file, outputMode mode, LSL_Leaf *content) -{ - if (content) - { - if (LUASL_DIFF_CHECK) - fprintf(file, "\n{"); - else - fprintf(file, "\n{\n"); - if (content->value.blockValue) - { - LSL_Statement *statement = NULL; - - EINA_CLIST_FOR_EACH_ENTRY(statement, &(content->value.blockValue->statements), LSL_Statement, statement) - { - outputLeaf(file, mode, statement->expressions); - if (LSL_FUNCTION != statement->type) - { - if (LUASL_DIFF_CHECK) - fprintf(file, ";"); - else - fprintf(file, ";\n"); - } - } - } - if (LUASL_DIFF_CHECK) - fprintf(file, "\n}"); - else - fprintf(file, "}"); - } -} - static void outputFloatToken(FILE *file, outputMode mode, LSL_Leaf *content) { if (content) @@ -1165,23 +1255,26 @@ static void outputParameterListToken(FILE *file, outputMode mode, LSL_Leaf *cont outputLeaf(file, mode, content->value.listValue); } -static void outputParenthesisToken(FILE *file, outputMode mode, LSL_Leaf *content) +static void outputRawParenthesisToken(FILE *file, outputMode mode, LSL_Parenthesis *parenthesis, const char *typeName) { - if (content) - { fprintf(file, "("); - if (LSL_TYPECAST_OPEN == content->value.parenthesis->type) - fprintf(file, "%s", allowed[content->basicType].name); // TODO - We are missing the type ignorable text here. + if (LSL_TYPECAST_OPEN == parenthesis->type) + fprintf(file, "%s", typeName); // TODO - We are missing the type ignorable text here. else - outputLeaf(file, mode, content->value.parenthesis->contents); + outputLeaf(file, mode, parenthesis->contents); #if LUASL_DIFF_CHECK - fprintf(file, "%s)", eina_strbuf_string_get(content->value.parenthesis->rightIgnorableText)); + fprintf(file, "%s)", eina_strbuf_string_get(parenthesis->rightIgnorableText)); #else fprintf(file, ")"); #endif - if (LSL_TYPECAST_OPEN == content->value.parenthesis->type) - outputLeaf(file, mode, content->value.parenthesis->contents); - } + if (LSL_TYPECAST_OPEN == parenthesis->type) + outputLeaf(file, mode, parenthesis->contents); +} + +static void outputParenthesisToken(FILE *file, outputMode mode, LSL_Leaf *content) +{ + if (content) + outputRawParenthesisToken(file, mode, content->value.parenthesis, allowed[content->basicType].name); } static void outputStateToken(FILE *file, outputMode mode, LSL_Leaf *content) @@ -1202,19 +1295,126 @@ static void outputStateToken(FILE *file, outputMode mode, LSL_Leaf *content) } } +// Circular references, so declare this one first. +static void outputBlockToken(FILE *file, outputMode mode, LSL_Leaf *content); + +static void outputRawStatement(FILE *file, outputMode mode, LSL_Statement *statement) +{ + boolean isBlock = FALSE; + + switch (statement->type) + { + case LSL_EXPRESSION : + { + break; + } + case LSL_FUNCTION : + { + isBlock = TRUE; + break; + } + case LSL_DO : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_FOR : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_IF : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_ELSE : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_JUMP : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_RETURN : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_STATE_CHANGE : + { + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_WHILE : + { + isBlock = TRUE; + fprintf(file, "%s", tokens[statement->type - lowestToken]->token); + break; + } + case LSL_IDENTIFIER : + { + break; + } + default : + { + fprintf(file, "@@Should not be here %s.@@", tokens[statement->type - lowestToken]->token); + break; + } + } + + if (statement->parenthesis) + outputRawParenthesisToken(file, mode, statement->parenthesis, ""); + else + outputLeaf(file, mode, statement->expressions); + + if (statement->block) + outputBlockToken(file, mode, statement->block); + + if (!isBlock) + { + fprintf(file, ";"); + if (!LUASL_DIFF_CHECK) + fprintf(file, "\n"); + } + +} + static void outputStatementToken(FILE *file, outputMode mode, LSL_Leaf *content) { if (content) { - outputLeaf(file, mode, content->value.statementValue->expressions); + outputRawStatement(file, mode, content->value.statementValue); #if LUASL_DIFF_CHECK if (content->ignorableText) fwrite(eina_strbuf_string_get(content->ignorableText), 1, eina_strbuf_length_get(content->ignorableText), file); #endif - if (LSL_FUNCTION != content->value.statementValue->type) - fprintf(file, "%s", content->token->token); - if (!LUASL_DIFF_CHECK) - fprintf(file, "\n"); + } +} + +static void outputBlockToken(FILE *file, outputMode mode, LSL_Leaf *content) +{ + if (content) + { + if (LUASL_DIFF_CHECK) + fprintf(file, "\n{"); + else + fprintf(file, "\n{\n"); + if (content->value.blockValue) + { + LSL_Statement *statement = NULL; + + EINA_CLIST_FOR_EACH_ENTRY(statement, &(content->value.blockValue->statements), LSL_Statement, statement) + { + outputRawStatement(file, mode, statement); + } + } + if (LUASL_DIFF_CHECK) + fprintf(file, "\n}"); + else + fprintf(file, "}"); } } diff --git a/LuaSL/src/LuaSL_lemon_yaccer.y b/LuaSL/src/LuaSL_lemon_yaccer.y index 42b02c7..f5b5981 100644 --- a/LuaSL/src/LuaSL_lemon_yaccer.y +++ b/LuaSL/src/LuaSL_lemon_yaccer.y @@ -42,7 +42,7 @@ functionList(A) ::= functionList(B) functionBody(C). { A = collectStatements( //functionList(A) ::= functionBody(C). { A = collectStatements(compiler, NULL, C); } functionList(A) ::= . { A = collectStatements(compiler, NULL, NULL); } -functionBody(A) ::= function(B) funcBlock(C). { A = addFunctionBody(compiler, B, C); } +functionBody(A) ::= function(F) funcBlock(B). { A = addFunctionBody(compiler, F, B); } // addFunctionBody has an implied addStatement(compiler, NULL, LSL_FUNCTION, NULL, B, NULL, NULL); parameterList(A) ::= parameterList(B) LSL_COMMA(C) parameter(D). { A = collectParameters(compiler, B, C, D); } parameterList(A) ::= parameter(D). { A = collectParameters(compiler, NULL, NULL, D); } @@ -67,26 +67,26 @@ statementList(A) ::= . { A = collectStatements(compiler, NULL, NULL); } %nonassoc LSL_DO LSL_FOR LSL_ELSE_IF LSL_IF LSL_JUMP LSL_RETURN LSL_STATE_CHANGE LSL_WHILE. %nonassoc LSL_ELSE. -statement ::= LSL_DO block LSL_WHILE LSL_PARENTHESIS_OPEN expr LSL_PARENTHESIS_CLOSE LSL_STATEMENT. -statement ::= LSL_FOR LSL_PARENTHESIS_OPEN expr LSL_STATEMENT expr LSL_STATEMENT expr LSL_PARENTHESIS_CLOSE block. +statement(A) ::= LSL_DO(F) block(B) LSL_WHILE(W) LSL_PARENTHESIS_OPEN(L) expr(E) LSL_PARENTHESIS_CLOSE(R) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, L, E, R, B, W); } +statement(A) ::= LSL_FOR(F) LSL_PARENTHESIS_OPEN(L) expr(E0) LSL_STATEMENT(S0) expr(E1) LSL_STATEMENT(S1) expr(E2) LSL_PARENTHESIS_CLOSE(R) block(B). { A = addStatement(compiler, NULL, F->token->type, L, NULL, R, B, NULL); } // three expressions, two semi colons ifBlock ::= ifBlock LSL_ELSE block. ifBlock ::= block. // The [LSL_ELSE] part causes a conflict. -statement ::= LSL_IF LSL_PARENTHESIS_OPEN expr LSL_PARENTHESIS_CLOSE ifBlock. [LSL_ELSE] +statement(A) ::= LSL_IF(F) LSL_PARENTHESIS_OPEN(L) expr(E) LSL_PARENTHESIS_CLOSE(R) ifBlock(B). [LSL_ELSE] { A = addStatement(compiler, NULL, F->token->type, L, E, R, B, NULL); } // optional else, optional else if -statement ::= LSL_JUMP LSL_IDENTIFIER LSL_STATEMENT. -statement ::= LSL_RETURN expr LSL_STATEMENT. -statement ::= LSL_RETURN LSL_STATEMENT. -statement ::= LSL_STATE_CHANGE LSL_DEFAULT LSL_STATEMENT. -statement ::= LSL_STATE_CHANGE LSL_IDENTIFIER LSL_STATEMENT. -statement ::= LSL_WHILE LSL_PARENTHESIS_OPEN expr LSL_PARENTHESIS_CLOSE block. +statement(A) ::= LSL_JUMP(F) LSL_IDENTIFIER(I) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, NULL, NULL, NULL, I); } +statement(A) ::= LSL_RETURN(F) expr(E) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, E, NULL, NULL, NULL); } +statement(A) ::= LSL_RETURN(F) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, NULL, NULL, NULL, NULL); } +statement(A) ::= LSL_STATE_CHANGE(F) LSL_DEFAULT(I) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, NULL, NULL, NULL, I); } +statement(A) ::= LSL_STATE_CHANGE(F) LSL_IDENTIFIER(I) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, NULL, NULL, NULL, I); } +statement(A) ::= LSL_WHILE(F) LSL_PARENTHESIS_OPEN(L) expr(E) LSL_PARENTHESIS_CLOSE(R) block(B). { A = addStatement(compiler, NULL, F->token->type, L, E, R, B, NULL); } %nonassoc LSL_LABEL. -statement ::= LSL_LABEL LSL_IDENTIFIER LSL_STATEMENT. +statement(A) ::= LSL_LABEL(F) LSL_IDENTIFIER(I) LSL_STATEMENT(S). { A = addStatement(compiler, S, F->token->type, NULL, NULL, NULL, NULL, I); } // This might be bogus, or might be valid LSL, but it let us test the expression parser by evaluating them. -statement(A) ::= expr(B) LSL_STATEMENT(D). { A = addStatement(D, LSL_EXPRESSION, B); } +statement(A) ::= expr(E) LSL_STATEMENT(S). { A = addStatement(compiler, S, LSL_EXPRESSION, NULL, E, NULL, NULL, NULL); } // Various forms of expression. @@ -171,8 +171,8 @@ expr(A) ::= identifier(B) LSL_ASSIGNMENT_PLAIN(C) expr(D). { A = addOperation(c // Hmm think this can have commas seperating the assignment parts, or is that only in C?. If so, best to separate them when converting to Lua, as it uses that syntax for something else. // Well, not in OpenSim at least, nor in SL. So we are safe. B-) -statement(A) ::= type(B) LSL_IDENTIFIER(C) LSL_ASSIGNMENT_PLAIN(D) expr(E) LSL_STATEMENT(F). { A = addStatement(F, LSL_IDENTIFIER, addVariable(compiler, B, C, D, E)); } -statement(A) ::= type(B) LSL_IDENTIFIER(C) LSL_STATEMENT(F). { A = addStatement(F, LSL_IDENTIFIER, addVariable(compiler, B, C, NULL, NULL)); } +statement(A) ::= type(T) LSL_IDENTIFIER(I) LSL_ASSIGNMENT_PLAIN(D) expr(E) LSL_STATEMENT(S). { A = addStatement(compiler, S, LSL_IDENTIFIER, NULL, addVariable(compiler, T, I, D, E), NULL, NULL, I); } +statement(A) ::= type(T) LSL_IDENTIFIER(I) LSL_STATEMENT(S). { A = addStatement(compiler, S, LSL_IDENTIFIER, NULL, addVariable(compiler, T, I, NULL, NULL), NULL, NULL, I); } %right LSL_DOT LSL_IDENTIFIER LSL_FUNCTION_CALL. identifier(A) ::= identifier LSL_DOT LSL_IDENTIFIER(B). { A = checkVariable(compiler, B); A->basicType = OT_float; } // Just a stub to get it to work for now. -- cgit v1.1