Procházet zdrojové kódy

feat: Include语句, Statement复制

复制Statement和StatementList
函数定义的时候会自动复制Statement副本
支持使用include语句包含文件
SongZihuan před 4 roky
rodič
revize
6a61506505
14 změnil soubory, kde provedl 232 přidání a 20 odebrání
  1. 1 0
      include/macro.h
  2. 2 0
      include/run.h
  3. 8 0
      include/statement.h
  4. 1 0
      include/token.h
  5. 1 0
      main.c
  6. 4 3
      parser/__grammar.c
  7. 24 9
      parser/grammar.c
  8. 4 2
      parser/include/__grammar.h
  9. 4 0
      src/inter.c
  10. 5 3
      src/parameter.c
  11. 3 0
      src/run.c
  12. 35 0
      src/runfile.c
  13. 137 1
      src/statement.c
  14. 3 2
      src/value.c

+ 1 - 0
include/macro.h

@@ -1,6 +1,7 @@
 #ifndef VIRTUALMATH_MACRO_H
 #define VIRTUALMATH_MACRO_H
 
+#include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>

+ 2 - 0
include/run.h

@@ -28,6 +28,8 @@ Result restartCode(INTER_FUNCTIONSIG);
 Result returnCode(INTER_FUNCTIONSIG);
 Result raiseCode(INTER_FUNCTIONSIG);
 
+Result includeFile(INTER_FUNCTIONSIG);
+
 Result assCore(Statement *name, LinkValue *value, INTER_FUNCTIONSIG_CORE);
 
 char *setStrVarName(char *old, bool free_old, INTER_FUNCTIONSIG_CORE);

+ 8 - 0
include/statement.h

@@ -24,6 +24,7 @@ struct Statement{
         restart,
         return_code,
         raise_code,
+        include_file,
     } type;
     union StatementU{
         struct base_value{
@@ -116,6 +117,9 @@ struct Statement{
         struct {
             struct Statement *value;
         } raise_code;
+        struct {
+            struct Statement *file;
+        } include_file;
     }u;
     struct Statement *next;
 };
@@ -138,6 +142,8 @@ typedef struct StatementList StatementList;
 
 Statement *makeStatement();
 void freeStatement(Statement *st);
+Statement *copyStatement(Statement *st);
+Statement *copyStatementCore(Statement *st);
 void connectStatement(Statement *base, Statement *new);
 
 Statement *makeOperationStatement(int type);
@@ -157,11 +163,13 @@ Statement *makeRegoStatement(Statement *times);
 Statement *makeRestartStatement(Statement *times);
 Statement *makeReturnStatement(Statement *value);
 Statement *makeRaiseStatement(Statement *value);
+Statement *makeIncludeStatement(Statement *file);
 struct Token *setOperationFromToken(Statement **st_ad, struct Token *left, struct Token *right, int type, bool is_right);
 
 StatementList *makeStatementList(Statement *condition, Statement *var, Statement *code, int type);
 StatementList *connectStatementList(StatementList *base, StatementList *new);
 void freeStatementList(StatementList *base);
+StatementList *copyStatementList(StatementList *sl);
 #define makeConnectStatementList(base, condition, var, code, type) connectStatementList(base, makeStatementList(condition, var, code, type))
 
 #endif //VIRTUALMATH_STATEMENT_H

+ 1 - 0
include/token.h

@@ -107,6 +107,7 @@
 #define TRY_BRANCH -22
 #define RAISE -23
 #define TUPLE -24
+#define INCLUDE -25
 
 #define printTokenEnter(tk, debug, type, message) do{ \
 writeLog(debug, type, message, NULL); \

+ 1 - 0
main.c

@@ -19,4 +19,5 @@ int main(int argc, char *argv[]) {
  * TODO-szh 面向对象
  * TODO-szh import和include语句
  * TODO-szh 错误回溯
+ * TODO-szh 检查文件是否为目录和目录是否为目录
  */

+ 4 - 3
parser/__grammar.c

@@ -168,11 +168,12 @@ bool checkToken_(ParserMessage *pm, int type){
     return true;
 }
 
-bool commandCallControl_(PASERSSIGNATURE, MakeControlFunction callBack, int type, Statement **st, char *message){
-    writeLog_(pm->grammar_debug, GRAMMAR_DEBUG, message, NULL);
+bool commandCallControl_(ParserMessage *pm, Inter *inter, MakeControlFunction callBack, int type, Statement **st,
+                         char *log_message, bool must_operation, char *error_message) {
+    writeLog_(pm->grammar_debug, GRAMMAR_DEBUG, log_message, NULL);
     Token *tmp_token = NULL;
     *st = NULL;
-    parserControl(CALLPASERSSIGNATURE, callBack, type);
+    parserControl(CALLPASERSSIGNATURE, callBack, type, must_operation, error_message);
     if (!call_success(pm) || readBackToken(pm) != type)
         return false;
     tmp_token = popAheadToken(pm);

+ 24 - 9
parser/grammar.c

@@ -28,6 +28,7 @@ ParserMessage *makeParserMessage(char *file_dir, char *debug){
 }
 
 void freeParserMessage(ParserMessage *pm, bool self) {
+    freeBase(pm, return_);
     freeTokenMessage(pm->tm, true, true);
 #if OUT_LOG
     if (pm->paser_debug != NULL)
@@ -39,6 +40,8 @@ void freeParserMessage(ParserMessage *pm, bool self) {
     if (self){
         memFree(pm);
     }
+    return_:
+    return;
 }
 
 /**
@@ -138,28 +141,34 @@ void parserCommand(PASERSSIGNATURE){
             break;
         case MATHER_BREAK :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeBreakStatement, BREAK, &st,
-                                         "Command: call break\n");
+                                         "Command: call break\n", false, NULL);
             break;
         case MATHER_CONTINUE :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeContinueStatement, CONTINUE, &st,
-                                         "Command: call continue\n");
+                                         "Command: call continue\n", false, NULL);
             break;
         case MATHER_RESTART :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeRestartStatement, RESTART, &st,
-                                         "Command: call restart\n");
+                                         "Command: call restart\n", false, NULL);
             break;
         case MATHER_REGO :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeRegoStatement, REGO, &st,
-                                         "Command: call rego\n");
+                                         "Command: call rego\n", false, NULL);
             break;
         case MATHER_RETURN :
-            status = commandCallControl_(CALLPASERSSIGNATURE, makeReturnStatement, RETURN,  &st,
-                                         "Command: call return\n");
+            status = commandCallControl_(CALLPASERSSIGNATURE, makeReturnStatement, RETURN, &st,
+                                         "Command: call return\n", false, NULL);
             break;
         case MATHER_RAISE :
-            status = commandCallControl_(CALLPASERSSIGNATURE, makeRaiseStatement, RAISE,  &st,
-                                         "Command: call raise\n");
+            status = commandCallControl_(CALLPASERSSIGNATURE, makeRaiseStatement, RAISE, &st,
+                                         "Command: call raise\n", false, NULL);
+            break;
+        case MATHER_INCLUDE :
+            status = commandCallControl_(CALLPASERSSIGNATURE, makeIncludeStatement, INCLUDE, &st,
+                                         "Command: call include\n", true,
+                                         "parserInclude: Don't get file after include");
             break;
+        // TODO-szh 对不支持的符号做error处理, 如:except、}、)
         default :
             status = commandCallBack_(CALLPASERSSIGNATURE, parserOperation, OPERATION, &st,
                                       "Command: call operation\n");
@@ -180,8 +189,10 @@ void parserCommand(PASERSSIGNATURE){
  *
  * @param callBack statement生成函数
  * @param type 输出token的类型
+ * @param must_operation 必须匹配 operation
  */
-void parserControl(PASERSSIGNATURE, MakeControlFunction callBack, int type){
+void parserControl(ParserMessage *pm, Inter *inter, MakeControlFunction callBack, int type, bool must_operation,
+                   char *message) {
     Statement *times = NULL;
     Statement *st = NULL;
     delToken(pm);
@@ -194,6 +205,10 @@ void parserControl(PASERSSIGNATURE, MakeControlFunction callBack, int type){
         times = tmp->data.st;
         freeToken(tmp, true, false);
     }
+    else if (must_operation){
+        syntaxError(pm, syntax_error, 1, message);
+        goto return_;
+    }
     st = callBack(times);
     addStatementToken(type, st, pm);
     return_:

+ 4 - 2
parser/include/__grammar.h

@@ -33,7 +33,8 @@ typedef Statement *(*MakeControlFunction)(Statement *);
 typedef int (*TailFunction)(PASERSSIGNATURE, Token *, Statement **);
 
 void parserCommand(PASERSSIGNATURE);
-void parserControl(PASERSSIGNATURE, MakeControlFunction callBack, int type);
+void parserControl(ParserMessage *pm, Inter *inter, MakeControlFunction callBack, int type, bool must_operation,
+                   char *message);
 void parserDef(PASERSSIGNATURE);
 void parserIf(PASERSSIGNATURE);
 void parserWhile(PASERSSIGNATURE);
@@ -53,7 +54,8 @@ int readBackToken(ParserMessage *pm);
 Token *popAheadToken(ParserMessage *pm);
 bool checkToken_(ParserMessage *pm, int type);
 
-bool commandCallControl_(PASERSSIGNATURE, MakeControlFunction callBack, int type, Statement **st, char *message);
+bool commandCallControl_(ParserMessage *pm, Inter *inter, MakeControlFunction callBack, int type, Statement **st,
+                         char *log_message, bool must_operation, char *error_message);
 bool commandCallBack_(PASERSSIGNATURE, PasersFunction callBack, int type, Statement **st, char *message);
 
 bool callParserCode(PASERSSIGNATURE, Statement **st,char *message);

+ 4 - 0
src/inter.c

@@ -28,6 +28,10 @@ Inter *newInter(char *code_file, char *debug_dir, Result *global_result, int *st
         goto return_;
     }
 
+    struct Statement *tmp = copyStatement(global_inter->statement);
+    freeStatement(global_inter->statement);
+    global_inter->statement = tmp;
+
     *global_result = globalIterStatement(global_inter);
     if (global_result->type == error_return){
         writeLog(global_inter->data.debug, ERROR, "Run Error\n", NULL);

+ 5 - 3
src/parameter.c

@@ -89,13 +89,15 @@ Parameter *copyParameter(Parameter *base){
     if (base == NULL)
         return NULL;
     Parameter *tmp = makeParameter(), *base_tmp = tmp;
-    tmp->data = base->data;
+    tmp->data.value = copyStatement(base->data.value);
+    tmp->data.name = copyStatement(base->data.name);
     tmp->type = base->type;
     while (base->next != NULL){
         tmp->next = makeParameter();
         tmp = tmp->next;
         base = base->next;
-        tmp->data = base->data;
+        tmp->data.value = copyStatement(base->data.value);
+        tmp->data.name = copyStatement(base->data.name);
         tmp->type = base->type;
     }
     return base_tmp;
@@ -521,6 +523,6 @@ Result setParameterCore(Argument *call, Parameter *function_base, VarList *funct
     setResult(&result, true ,inter);
 
     return_:
-    freeParameter(tmp_function, false);
+    freeParameter(tmp_function, true);
     return result;
 }

+ 3 - 0
src/run.c

@@ -62,6 +62,9 @@ Result runStatement(INTER_FUNCTIONSIG) {
         case raise_code:
             result = raiseCode(CALL_INTER_FUNCTIONSIG(st, var_list));
             break;
+        case include_file:
+            result = includeFile(CALL_INTER_FUNCTIONSIG(st, var_list));
+            break;
         default:
             setResult(&result, true, inter);
             break;

+ 35 - 0
src/runfile.c

@@ -0,0 +1,35 @@
+#include "__run.h"
+
+Result includeFile(INTER_FUNCTIONSIG) {
+    Result result;
+    Result file;
+    char *file_dir = NULL;
+    ParserMessage *pm = NULL;
+    Statement *new_st = makeStatement();
+
+    if (operationSafeInterStatement(&file, CALL_INTER_FUNCTIONSIG(st->u.include_file.file, var_list)))
+        return file;
+
+    // TODO-szh 类型检查
+    file_dir = file.value->value->data.str.str;
+    if (access(file_dir, R_OK) != 0){
+        setResultError(&result, inter);
+        printf("tag 1\n");
+        goto return_;
+    }
+
+    pm = makeParserMessage(file_dir, NULL);
+    parserCommandList(pm, inter, true, new_st);
+    if (pm->status != success){
+        writeLog(pm->paser_debug, ERROR, "Syntax Error: %s\n", pm->status_message);
+        setResultError(&result, inter);
+        goto return_;
+    }
+
+    functionSafeInterStatement(&result, CALL_INTER_FUNCTIONSIG(new_st, var_list));
+
+    return_:
+    freeStatement(new_st);
+    freeParserMessage(pm, true);
+    return result;
+}

+ 137 - 1
src/statement.c

@@ -169,6 +169,13 @@ Statement *makeRaiseStatement(Statement *value){
     return tmp;
 }
 
+Statement *makeIncludeStatement(Statement *file){
+    Statement *tmp = makeStatement();
+    tmp->type = include_file;
+    tmp->u.include_file.file = file;
+    return tmp;
+}
+
 void connectStatement(Statement *base, Statement *new){
     while (base->next != NULL){
         base = base->next;
@@ -181,7 +188,6 @@ void freeStatement(Statement *st){
     Statement *next_tmp;
     while (st != NULL){
         switch (st->type) {
-            // base-value 不需要释放
             case operation:
                 freeStatement(st->u.operation.right);
                 freeStatement(st->u.operation.left);
@@ -257,6 +263,9 @@ void freeStatement(Statement *st){
             case raise_code:
                 freeStatement(st->u.raise_code.value);
                 break;
+            case include_file:
+                freeStatement(st->u.include_file.file);
+                break;
             default:
                 break;
         }
@@ -268,6 +277,116 @@ void freeStatement(Statement *st){
     return;
 }
 
+Statement *copyStatement(Statement *st){
+    if (st == NULL)
+        return NULL;
+
+    Statement *tmp = copyStatementCore(st);
+    Statement *base_tmp = tmp;
+
+    while (st->next != NULL){
+        tmp->next = copyStatementCore(st->next);
+        tmp = tmp->next;
+        st = st->next;
+    }
+    return base_tmp;
+}
+
+Statement *copyStatementCore(Statement *st){
+    Statement *new = makeStatement();
+    new->type = st->type;
+    new->next = NULL;
+    switch (st->type) {
+        case base_value:
+            new->u.base_value.value = st->u.base_value.value;
+            break;
+        case operation:
+            new->u.operation.OperationType = st->u.operation.OperationType;
+            new->u.operation.right = copyStatement(st->u.operation.right);
+            new->u.operation.left = copyStatement(st->u.operation.left);
+            break;
+        case base_var:
+            new->u.base_var.name = memStrcpy(st->u.base_var.name, 0, false, false);
+            new->u.base_var.times = copyStatement(st->u.base_var.times);
+            break;
+        case base_svar:
+            new->u.base_svar.name = copyStatement(st->u.base_svar.name);
+            new->u.base_svar.times = copyStatement(st->u.base_svar.times);
+            break;
+        case set_function:
+            new->u.set_function.name = copyStatement(st->u.set_function.name);
+            new->u.set_function.function = copyStatement(st->u.set_function.function);
+            new->u.set_function.parameter = copyParameter(st->u.set_function.parameter);
+            break;
+        case call_function:
+            new->u.call_function.function = copyStatement(st->u.call_function.function);
+            new->u.call_function.parameter = copyParameter(st->u.call_function.parameter);
+            break;
+        case base_list:
+            new->u.base_list.type = st->u.base_list.type;
+            new->u.base_list.list = copyParameter(st->u.base_list.list);
+            break;
+        case base_dict:
+            new->u.base_dict.dict = copyParameter(st->u.base_dict.dict);
+            break;
+        case if_branch:
+            new->u.if_branch.if_list = copyStatementList(st->u.if_branch.if_list);
+            new->u.if_branch.finally = copyStatement(st->u.if_branch.finally);
+            new->u.if_branch.else_list = copyStatement(st->u.if_branch.else_list);
+            break;
+        case while_branch:
+            new->u.while_branch.type = st->u.while_branch.type;
+            new->u.while_branch.while_list = copyStatementList(st->u.while_branch.while_list);
+            new->u.while_branch.first = copyStatement(st->u.while_branch.first);
+            new->u.while_branch.after = copyStatement(st->u.while_branch.after);
+            new->u.while_branch.else_list = copyStatement(st->u.while_branch.else_list);
+            new->u.while_branch.finally = copyStatement(st->u.while_branch.finally);
+            break;
+        case for_branch:
+            new->u.for_branch.for_list = copyStatementList(st->u.for_branch.for_list);
+            new->u.for_branch.var = copyStatement(st->u.for_branch.var);
+            new->u.for_branch.iter = copyStatement(st->u.for_branch.iter);
+            new->u.for_branch.else_list = copyStatement(st->u.for_branch.else_list);
+            new->u.for_branch.finally = copyStatement(st->u.for_branch.finally);
+            break;
+        case try_branch:
+            new->u.try_branch.except_list = copyStatementList(st->u.try_branch.except_list);
+            new->u.try_branch.try = copyStatement(st->u.try_branch.try);
+            new->u.try_branch.else_list = copyStatement(st->u.try_branch.else_list);
+            new->u.try_branch.finally = copyStatement(st->u.try_branch.finally);
+            break;
+        case with_branch:
+            new->u.with_branch.with_list = copyStatementList(st->u.with_branch.with_list);
+            new->u.with_branch.else_list = copyStatement(st->u.with_branch.else_list);
+            new->u.with_branch.finally = copyStatement(st->u.with_branch.finally);
+            break;
+        case break_cycle:
+            new->u.break_cycle.times = copyStatement(st->u.break_cycle.times);
+            break;
+        case continue_cycle:
+            new->u.continue_cycle.times = copyStatement(st->u.continue_cycle.times);
+            break;
+        case rego_if:
+            new->u.rego_if.times = copyStatement(st->u.rego_if.times);
+            break;
+        case restart:
+            new->u.restart.times = copyStatement(st->u.restart.times);
+            break;
+        case return_code:
+            new->u.return_code.value = copyStatement(st->u.return_code.value);
+            break;
+        case raise_code:
+            new->u.raise_code.value = copyStatement(st->u.raise_code.value);
+            break;
+        case include_file:
+            new->u.include_file.file = copyStatement(st->u.include_file.file);
+            break;
+        default:
+            break;
+    }
+    return new;
+}
+
 StatementList *makeStatementList(Statement *condition, Statement *var, Statement *code, int type) {
     StatementList *tmp = memCalloc(1, sizeof(StatementList));
     tmp->condition = condition;
@@ -299,3 +418,20 @@ void freeStatementList(StatementList *base){
         memFree(tmp);
     }
 }
+
+StatementList *copyStatementList(StatementList *sl){
+    if (sl == NULL)
+        return NULL;
+
+    StatementList *tmp = makeStatementList(copyStatement(sl->condition), copyStatement(sl->var),
+                                           copyStatement(sl->code), sl->type);
+    StatementList *base_tmp = tmp;
+
+    while (sl->next != NULL){
+        tmp->next = makeStatementList(copyStatement(sl->condition), copyStatement(sl->var),
+                                      copyStatement(sl->code), sl->type);
+        tmp = tmp->next;
+        sl = sl->next;
+    }
+    return base_tmp;
+}

+ 3 - 2
src/value.c

@@ -41,7 +41,7 @@ Value *makeFunctionValue(Statement *st, Parameter *pt, VarList *var_list, Inter
     Value *tmp;
     tmp = makeValue(inter);
     tmp->type = function;
-    tmp->data.function.function = st;
+    tmp->data.function.function = copyStatement(st);
     tmp->data.function.pt = copyParameter(pt);
     tmp->data.function.var = copyVarList(var_list, false, inter);
     return tmp;
@@ -97,7 +97,8 @@ void freeValue(Value *value, Inter *inter){
             break;
         case function: {
             VarList *tmp = value->data.function.var;
-            freeParameter(value->data.function.pt, false);
+            freeParameter(value->data.function.pt, true);
+            freeStatement(value->data.function.function);
             while (tmp != NULL)
                 tmp = freeVarList(tmp, true);
             break;