Bladeren bron

feat: 加入变量控制语句

允许使用default, global, 和nonlocal语句
SongZihuan 4 jaren geleden
bovenliggende
commit
b11f2c6755
12 gewijzigde bestanden met toevoegingen van 152 en 19 verwijderingen
  1. 2 1
      include/run.h
  2. 10 0
      include/statement.h
  3. 1 0
      include/token.h
  4. 13 0
      include/var.h
  5. 1 1
      main.c
  6. 0 1
      parser/__grammar.c
  7. 36 10
      parser/grammar.c
  8. 1 0
      parser/include/__grammar.h
  9. 3 0
      src/run.c
  10. 27 3
      src/runoperation.c
  11. 14 0
      src/statement.c
  12. 44 3
      src/var.c

+ 2 - 1
include/run.h

@@ -10,7 +10,6 @@ typedef struct Statement Statement;
 typedef struct Inter Inter;
 typedef struct VarList VarList;
 typedef struct Parameter Parameter;
-
 typedef ResultType (*VarInfo)(char **name, int *times, INTER_FUNCTIONSIG);
 
 ResultType globalIterStatement(Result *result, LinkValue *base_father, Inter *inter, Statement *st);
@@ -30,6 +29,8 @@ ResultType getVar(INTER_FUNCTIONSIG, VarInfo var_info);
 ResultType getBaseValue(INTER_FUNCTIONSIG);
 ResultType getList(INTER_FUNCTIONSIG);
 ResultType getDict(INTER_FUNCTIONSIG);
+ResultType setDefault(INTER_FUNCTIONSIG);
+
 ResultType ifBranch(INTER_FUNCTIONSIG);
 ResultType whileBranch(INTER_FUNCTIONSIG);
 ResultType tryBranch(INTER_FUNCTIONSIG);

+ 10 - 0
include/statement.h

@@ -31,6 +31,7 @@ struct Statement{
         include_file,
         import_file,
         from_import_file,
+        default_var,
     } type;
     union StatementU{
         struct base_value{
@@ -147,6 +148,14 @@ struct Statement{
             struct Parameter *pt;
             struct Parameter *as;
         } from_import_file;
+        struct {
+            struct Parameter *var;
+            enum DefaultType{
+                default_,
+                global_,
+                nonlocal_,
+            } default_type;
+        } default_var;
     }u;
     long int line;
     char *code_file;
@@ -198,6 +207,7 @@ Statement *makeRaiseStatement(Statement *value, long int line, char *file);
 Statement *makeIncludeStatement(Statement *file, long int line, char *file_dir);
 Statement *makeImportStatement(Statement *file, Statement *as);
 Statement *makeFromImportStatement(Statement *file, Parameter *as, Parameter *pt);
+Statement *makeDefaultVarStatement(Parameter *var, long int line, char *file_dir, enum DefaultType type);
 struct Token *setOperationFromToken(Statement **st_ad, struct Token *left, struct Token *right, enum OperationType type, bool is_right);
 
 StatementList *makeStatementList(Statement *condition, Statement *var, Statement *code, int type);

+ 1 - 0
include/token.h

@@ -113,6 +113,7 @@
 #define INCLUDE -25
 #define POINT -26
 #define IMPORT -27
+#define VARCONTROL -28
 
 #define printTokenEnter(tk, debug, type, message) do{ \
 writeLog(debug, type, message, NULL); \

+ 13 - 0
include/var.h

@@ -20,13 +20,21 @@ struct HashTable{
     struct HashTable *gc_last;
 };
 
+struct DefaultVar{
+    char *name;
+    NUMBER_TYPE times;
+    struct DefaultVar *next;
+};
+
 struct VarList{
     struct HashTable *hashtable;
+    struct DefaultVar *default_var;
     struct VarList *next;
 };
 
 typedef struct Var Var;
 typedef struct HashTable HashTable;
+typedef struct DefaultVar DefaultVar;
 typedef struct VarList VarList;
 
 Var *makeVar(char *name, LinkValue *value, LinkValue *name_, Inter *inter);
@@ -53,4 +61,9 @@ bool comparVarList(VarList *dest, VarList *src);
 VarList *connectSafeVarListBack(VarList *base, VarList *back);
 VarList *makeObjectVarList(FatherValue *value, Inter *inter);
 
+NUMBER_TYPE findDefault(DefaultVar *base, char *name);
+DefaultVar *connectDefaultVar(DefaultVar *base, char *name, NUMBER_TYPE times);
+DefaultVar *freeDefaultVar(DefaultVar *dv);
+DefaultVar *makeDefaultVar(char *name, NUMBER_TYPE times);
+
 #endif //VIRTUALMATH_VAR_H

+ 1 - 1
main.c

@@ -21,7 +21,6 @@ int main(int argc, char *argv[]) {
 
 
 /**
- * TODO-szh 变量控制
  * TODO-szh 断言
  * TODO-szh 代码块
  * TODO-szh 类super语句
@@ -29,4 +28,5 @@ int main(int argc, char *argv[]) {
  * TODO-szh 生成语法树
  * TODO-szh 取反符号 -
  * TODO-szh 字面量后缀
+ * TODO-szh 去掉free的self参数
  */

+ 0 - 1
parser/__grammar.c

@@ -161,7 +161,6 @@ bool commandCallControl_(PASERSSIGNATURE, MakeControlFunction callBack, int type
 }
 
 inline bool commandCallBack_(PASERSSIGNATURE, PasersFunction callBack, int type, Statement **st, char *message){
-    
     return callChildStatement(CALLPASERSSIGNATURE, callBack, type, st, NULL);
 }
 

+ 36 - 10
parser/grammar.c

@@ -90,22 +90,23 @@ void parserCommand(PASERSSIGNATURE){
     Statement *st = NULL;
     token_type = readBackToken(pm);
     switch (token_type) {
+        case MATHER_NONLOCAL :
+        case MATHER_GLOBAL :
+        case MATHER_DEFAULT :
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserVarControl, VARCONTROL, &st, "Command: call var control\n");  // TODO-szh 取消message
+            break;
         case MATHER_CLASS :
         case MATHER_DEF :
-            status = commandCallBack_(CALLPASERSSIGNATURE, parserDef, FUNCTION, &st,
-                                      "Command: call def\n");
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserDef, FUNCTION, &st, "Command: call def/class\n");
             break;
         case MATHER_IF :
-            status = commandCallBack_(CALLPASERSSIGNATURE, parserIf, IF_BRANCH, &st,
-                                      "Command: call if\n");
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserIf, IF_BRANCH, &st, "Command: call if\n");
             break;
         case MATHER_WHILE :
-            status = commandCallBack_(CALLPASERSSIGNATURE, parserWhile, WHILE_BRANCH, &st,
-                                      "Command: call while\n");
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserWhile, WHILE_BRANCH, &st, "Command: call while\n");
             break;
         case MATHER_TRY :
-            status = commandCallBack_(CALLPASERSSIGNATURE, parserTry, TRY_BRANCH, &st,
-                                      "Command: call try\n");
+            status = commandCallBack_(CALLPASERSSIGNATURE, parserTry, TRY_BRANCH, &st, "Command: call try\n");
             break;
         case MATHER_BREAK :
             status = commandCallControl_(CALLPASERSSIGNATURE, makeBreakStatement, BREAK, &st,
@@ -220,6 +221,32 @@ void parserImport(PASERSSIGNATURE) {
     return;
 }
 
+
+/**
+ * 控制语句匹配
+ * parserControl
+ * | (control token) NULL
+ * | (control token) parserOperation
+ * @param callBack statement生成函数
+ * @param type 输出token的类型
+ * @param must_operation 必须匹配 operation
+ */
+void parserVarControl(PASERSSIGNATURE) {
+    Parameter *var = NULL;
+    Statement *st = NULL;
+    Token *tmp = NULL;
+    int token_type = readBackToken(pm);
+    long int line = delToken(pm);
+    if (!parserParameter(CALLPASERSSIGNATURE, &var, true, true, true, MATHER_COMMA, MATHER_ASSIGNMENT) || var == NULL) {
+        syntaxError(pm, syntax_error, line, 1, "Don't get any var");
+        goto return_;
+    }
+    st = makeDefaultVarStatement(var, line, pm->file, token_type == MATHER_DEFAULT ? default_ : token_type == MATHER_GLOBAL ? global_ : nonlocal_);
+    addStatementToken(VARCONTROL, st, pm);
+    return_:
+    return;
+}
+
 /**
  * 控制语句匹配
  * parserControl
@@ -233,8 +260,7 @@ void parserControl(PASERSSIGNATURE, MakeControlFunction callBack, int type, bool
     Statement *opt = NULL;
     Statement *st = NULL;
     Token *tmp = NULL;
-    long int line = 0;
-    line = delToken(pm);
+    long int line = delToken(pm);
     parserOperation(CALLPASERSSIGNATURE);
     if (!call_success(pm) || readBackToken(pm) != OPERATION && must_operation){
         syntaxError(pm, syntax_error, line, 1, message);

+ 1 - 0
parser/include/__grammar.h

@@ -33,6 +33,7 @@ void parserFactor(PASERSSIGNATURE);
 void parserAssignment(PASERSSIGNATURE);
 void parserTuple(PASERSSIGNATURE);
 void parserImport(PASERSSIGNATURE);
+void parserVarControl(PASERSSIGNATURE);
 
 void syntaxError(ParserMessage *pm, int status,long int line , int num, ...);
 

+ 3 - 0
src/run.c

@@ -76,6 +76,9 @@ ResultType runStatement(INTER_FUNCTIONSIG) {
         case from_import_file:
             type = fromImportFile(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
             break;
+        case default_var:
+            type = setDefault(CALL_INTER_FUNCTIONSIG(st, var_list, result, father));
+            break;
         default:
             setResult(result, inter, father);
             break;

+ 27 - 3
src/runoperation.c

@@ -315,7 +315,7 @@ ResultType getVar(INTER_FUNCTIONSIG, VarInfo var_info) {
 }
 
 ResultType getBaseValue(INTER_FUNCTIONSIG) {
-    freeResult(result);
+    setResultCore(result);
     if (st->u.base_value.type == link_value)
         result->value = st->u.base_value.value;
     else if (st->u.base_value.type == number_str){
@@ -334,7 +334,7 @@ ResultType getList(INTER_FUNCTIONSIG) {
     Argument *at = NULL;
     Argument *at_tmp = NULL;
 
-    freeResult(result);
+    setResultCore(result);
     at = getArgument(st->u.base_list.list, false, CALL_INTER_FUNCTIONSIG_NOT_ST (var_list, result, father));
     at_tmp = at;
     if (!run_continue(result)){
@@ -353,7 +353,7 @@ ResultType getDict(INTER_FUNCTIONSIG) {
     Argument *at = NULL;
     Argument *at_tmp = NULL;
 
-    freeResult(result);
+    setResultCore(result);
     at = getArgument(st->u.base_dict.dict, true, CALL_INTER_FUNCTIONSIG_NOT_ST (var_list, result, father));
     at_tmp = at;
     if (!run_continue(result)){
@@ -375,3 +375,27 @@ ResultType getDict(INTER_FUNCTIONSIG) {
 
     return result->type;
 }
+
+ResultType setDefault(INTER_FUNCTIONSIG){
+    enum DefaultType type = st->u.default_var.default_type;
+    int base = 0;  // 用于nonlocal和global
+    setResultCore(result);
+    if (type == global_)
+        for (VarList *tmp = var_list; tmp->next != NULL; tmp = tmp->next)
+            base++;
+    else if (type == nonlocal_)
+        base = 1;
+    for (Parameter *pt = st->u.default_var.var; pt != NULL; pt = pt->next){
+        char *name = NULL;
+        int times = 0;
+        freeResult(result);
+        getVarInfo(&name, &times, CALL_INTER_FUNCTIONSIG(pt->data.value, var_list, result, father));
+        if (!run_continue(result))
+            break;
+        if (type != default_)
+            times = base;
+        var_list->default_var = connectDefaultVar(var_list->default_var, name, times);
+        memFree(name);
+    }
+    return result->type;
+}

+ 14 - 0
src/statement.c

@@ -218,6 +218,14 @@ Statement *makeFromImportStatement(Statement *file, Parameter *as, Parameter *pt
     return tmp;
 }
 
+Statement *makeDefaultVarStatement(Parameter *var, long int line, char *file_dir, enum DefaultType type) {
+    Statement *tmp = makeStatement(line, file_dir);
+    tmp->type = default_var;
+    tmp->u.default_var.var = var;
+    tmp->u.default_var.default_type = type;
+    return tmp;
+}
+
 void connectStatement(Statement *base, Statement *new){
     for (PASS; base->next != NULL; base = base->next)
         PASS;
@@ -329,6 +337,9 @@ void freeStatement(Statement *st){
                 freeParameter(st->u.from_import_file.as, true);
                 freeParameter(st->u.from_import_file.pt, true);
                 break;
+            case default_var:
+                freeParameter(st->u.default_var.var, true);
+                break;
             default:
                 break;
         }
@@ -457,6 +468,9 @@ Statement *copyStatementCore(Statement *st){
             new->u.from_import_file.as = copyParameter(st->u.from_import_file.as);
             new->u.from_import_file.pt = copyParameter(st->u.from_import_file.pt);
             break;
+        case default_var:
+            new->u.default_var.var = copyParameter(st->u.default_var.var);
+            break;
         default:
             break;
     }

+ 44 - 3
src/var.c

@@ -82,11 +82,14 @@ VarList *makeVarList(Inter *inter) {
     VarList *tmp = calloc(1, sizeof(VarList));
     tmp->next = NULL;
     tmp->hashtable = makeHashTable(inter);
+    tmp->default_var = NULL;
     return tmp;
 }
 
 VarList *freeVarList(VarList *vl, bool self){
     freeBase(vl, return_);
+    for (PASS; vl->default_var != NULL; vl->default_var = freeDefaultVar(vl->default_var))
+        PASS;
     if (self){
         VarList *next_var = vl->next;
         memFree(vl);
@@ -96,6 +99,43 @@ VarList *freeVarList(VarList *vl, bool self){
     return vl;
 }
 
+DefaultVar *makeDefaultVar(char *name, NUMBER_TYPE times) {
+    DefaultVar *tmp;
+    tmp = memCalloc(1, sizeof(DefaultVar));
+    tmp->name = memStrcpy(name);
+    tmp->times = times;
+    tmp->next = NULL;
+    return tmp;
+}
+
+DefaultVar *freeDefaultVar(DefaultVar *dv) {
+    DefaultVar *next = dv->next;
+    memFree(dv->name);
+    memFree(dv);
+    return next;
+}
+
+DefaultVar *connectDefaultVar(DefaultVar *base, char *name, NUMBER_TYPE times) {
+    for (DefaultVar **tmp = &base; PASS; tmp = &(*tmp)->next){
+        if (*tmp == NULL){
+            *tmp = makeDefaultVar(name, times);
+            break;
+        }
+        if (eqString((*tmp)->name, name)){
+            (*tmp)->times = times;
+            break;
+        }
+    }
+    return base;
+}
+
+NUMBER_TYPE findDefault(DefaultVar *base, char *name) {
+    for (DefaultVar **tmp = &base; *tmp != NULL; tmp = &(*tmp)->next)
+        if (eqString((*tmp)->name, name))
+            return (*tmp)->times;
+    return 0;
+}
+
 /**
  * hashTable使用time33算法
  * @param key
@@ -121,7 +161,6 @@ void addVarCore(Var **base, char *name, LinkValue *value, LinkValue *name_, Inte
     }
 }
 
-
 void addVar(char *name, LinkValue *value, LinkValue *name_, INTER_FUNCTIONSIG_CORE) {
     HASH_INDEX index = time33(name);
     addVarCore(&var_list->hashtable->hashtable[index], name, value, name_, inter);
@@ -155,7 +194,8 @@ LinkValue *findVar(char *name, bool del_var, INTER_FUNCTIONSIG_CORE) {
 
 LinkValue *findFromVarList(char *name, NUMBER_TYPE times, bool del_var, INTER_FUNCTIONSIG_CORE) {
     LinkValue *tmp = NULL;
-    for (NUMBER_TYPE i=0; i < times && var_list->next != NULL; i++)
+    NUMBER_TYPE base = findDefault(var_list->default_var, name) + times;
+    for (NUMBER_TYPE i = 0; i < base && var_list->next != NULL; i++)
         var_list = var_list->next;
     for (PASS; var_list != NULL && tmp == NULL; var_list = var_list->next)
         tmp = findVar(name, del_var, CALL_INTER_FUNCTIONSIG_CORE(var_list));
@@ -163,7 +203,8 @@ LinkValue *findFromVarList(char *name, NUMBER_TYPE times, bool del_var, INTER_FU
 }
 
 void addFromVarList(char *name, LinkValue *name_, NUMBER_TYPE times, LinkValue *value, INTER_FUNCTIONSIG_CORE) {
-    for (NUMBER_TYPE i=0; i < times && var_list->next != NULL; i++)
+    NUMBER_TYPE base = findDefault(var_list->default_var, name) + times;
+    for (NUMBER_TYPE i = 0; i < base && var_list->next != NULL; i++)
         var_list = var_list->next;
     addVar(name, value, name_, CALL_INTER_FUNCTIONSIG_CORE(var_list));
 }