فهرست منبع

feat: 调整了goto和label的语法

SongZihuan 4 سال پیش
والد
کامیت
5bac896db7
3فایلهای تغییر یافته به همراه57 افزوده شده و 89 حذف شده
  1. 21 60
      VirtulMathCore/parser/grammar.c
  2. 32 23
      VirtulMathCore/src/run.c
  3. 4 6
      VirtulMathCore/src/runbranch.c

+ 21 - 60
VirtulMathCore/parser/grammar.c

@@ -249,10 +249,10 @@ void parserDecoration(PASERSSIGNATURE){
 /**
  * label语句匹配
  * parserLabel:
- * | MATHER_LABEL MATHER_COLON MATHER_STRING(MATHER_VAR) stop_token [缺省所有参数]
- * | MATHER_LABEL MATHER_COLON MATHER_STRING(MATHER_VAR) MATHER_AS parserOperation stop_token [缺省command参数]
- * | MATHER_LABEL MATHER_COLON MATHER_STRING(MATHER_VAR) MATHER_COLON parserOperation stop_token
- * | MATHER_LABEL MATHER_COLON MATHER_STRING(MATHER_VAR) MATHER_AS parserOperation MATHER_COLON parserOperation [缺省var参数]
+ * | MATHER_LABEL MATHER_STRING(MATHER_VAR) [缺省所有参数]
+ * | MATHER_LABEL MATHER_STRING(MATHER_VAR) MATHER_AS parserOperation [缺省command参数]
+ * | MATHER_LABEL MATHER_STRING(MATHER_VAR) MATHER_COLON parserOperation [缺省var参数]
+ * | MATHER_LABEL MATHER_STRING(MATHER_VAR) MATHER_AS parserOperation MATHER_COLON parserOperation
  * @param pm
  * @param inter
  */
@@ -260,47 +260,26 @@ void parserLabel(PASERSSIGNATURE){
     Statement *st = NULL;
     Statement *var = NULL;
     Statement *command = NULL;
-    Token *label_tk = NULL;
     int tmp;
     wchar_t *label = NULL;
     long int line = delToken(pm);
 
-    if (!checkToken(pm, MATHER_COLON)){
-        syntaxError(pm, syntax_error, line, 1, "Don't get : after label");
+    if ((tmp = readBackToken(pm)) == MATHER_STRING || tmp == MATHER_VAR) {
+        Token *label_ = popNewToken(pm->tm);
+        label = memWidecpy(label_->data.str);
+        freeToken(label_, false);
+    } else {
+        syntaxError(pm, syntax_error, line, 1, "Don't get a label name");
         goto error_;
     }
-    switch (readBackToken(pm)) {
-        case MATHER_STRING:
-        case MATHER_VAR:
-            label_tk = popNewToken(pm->tm);
-            label = memWidecpy(label_tk->data.str);
-            freeToken(label_tk, false);
-            break;
-        default:
-            syntaxError(pm, syntax_error, line, 1, "Don't get a label name");
-            goto error_;
-    }
-
-    if ((tmp = readBackToken(pm)) == MATHER_ENTER || tmp == MATHER_SEMICOLON || tmp == MATHER_EOF)  // 匹配到stop_token则label后参数缺省
-        goto make;
-    if (tmp != MATHER_COLON) {  // 匹配到 : 则label的times参数缺省
-        if (!checkToken(pm, MATHER_AS)) {
-            syntaxError(pm, syntax_error, line, 1, "Don't get as after goto label");
-            goto error_;
-        } else if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &var, "Don't get a goto var"))
-            goto error_;
-    }
 
-    if ((tmp = readBackToken(pm)) == MATHER_ENTER || tmp == MATHER_SEMICOLON || tmp == MATHER_EOF)  // 如匹配到stop_token则label的command参数缺省
-        goto make;
-    else if (!checkToken(pm, MATHER_COLON)){
-        syntaxError(pm, syntax_error, line, 1, "Don't get : after goto var");
+    if (checkToken(pm, MATHER_AS) && !callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &var, "Don't get a label var"))
         goto error_;
-    }
-    else if (!callChildStatement(CALLPASERSSIGNATURE, parserCommand, COMMAND, &command, "Don't get a label command"))
+
+    if (checkToken(pm, MATHER_COLON) && !callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &command, "Don't get a label command"))
         goto error_;
 
-    make:
+
     st = makeLabelStatement(var, command, label, line, pm->file);
     addStatementToken(LABEL, st, pm);
     memFree(label);
@@ -315,45 +294,27 @@ void parserLabel(PASERSSIGNATURE){
 /**
  * goto语句匹配
  * parserGoto:
- * | MATHER_GOTO MATHER_AT parserOperation stop_token [缺省所有参数]
- * | MATHER_GOTO MATHER_AT parserOperation MATHER_COLON parserOperation stop_token [缺省return_参数]
- * | MATHER_GOTO MATHER_AT parserOperation MATHER_COLON parserOperation MATHER_COLON parserOperation
- * | MATHER_GOTO MATHER_AT parserOperation MATHER_COLON MATHER_COLON parserOperation [缺省times参数]
+ * | MATHER_GOTO parserOperation [缺省所有参数]
+ * | MATHER_GOTO parserOperation MATHER_COLON parserOperation [缺省times参数]
+ * | MATHER_GOTO parserOperation MATHER_AT parserOperation [缺省return_参数]
+ * | MATHER_GOTO parserOperation MATHER_AT parserOperation MATHER_COLON parserOperation
  */
 void parserGoto(PASERSSIGNATURE){
     Statement *st = NULL;
     Statement *label = NULL;
     Statement *times = NULL;
     Statement *return_ = NULL;
-    int tmp;
     long int line = delToken(pm);
 
-    if (!checkToken(pm, MATHER_AT)){
-        syntaxError(pm, syntax_error, line, 1, "Don't get @ after goto");
-        goto error_;
-    }
-    if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &label, "Don't get a goto times"))
+    if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &label, "Don't get a goto label"))
         goto error_;
 
-    if ((tmp = readBackToken(pm)) == MATHER_ENTER || tmp == MATHER_SEMICOLON || tmp == MATHER_EOF)  // 如匹配到stop_token则goto后面参数缺省
-        goto make;
-    else if (!checkToken(pm, MATHER_COLON)){
-        syntaxError(pm, syntax_error, line, 1, "Don't get : after goto label");
+    if (checkToken(pm, MATHER_AT) && !callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &times, "Don't get a goto times"))
         goto error_;
-    }
-    else if (!checkToken(pm, MATHER_COLON) && !callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &times, "Don't get a goto times"))
-        goto error_;  // 若再次匹配到 MATHER_COLON 则表示goto的times参数缺省
 
-    if ((tmp = readBackToken(pm)) == MATHER_ENTER || tmp == MATHER_SEMICOLON || tmp == MATHER_EOF)  // 如匹配到stop_token则goto的return_参数缺省
-        goto make;
-    else if (times != NULL && !checkToken(pm, MATHER_COLON)){
-        syntaxError(pm, syntax_error, line, 1, "Don't get : after goto times");
-        goto error_;
-    }
-    else if (!callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &return_, "Don't get a goto return"))
+    if (checkToken(pm, MATHER_COLON) && !callChildStatement(CALLPASERSSIGNATURE, parserOperation, OPERATION, &return_, "Don't get a goto return"))
         goto error_;
 
-    make:
     st = makeGotoStatement(return_, times, label, line, pm->file);
     addStatementToken(GOTO, st, pm);
     return;

+ 32 - 23
VirtulMathCore/src/run.c

@@ -115,17 +115,30 @@ ResultType runStatement(INTER_FUNCTIONSIG) {
     return type;
 }
 
-bool checkSignal(ResultType *type, fline line, char *file, INTER_FUNCTIONSIG_NOT_ST) {
+static bool checkSignal(fline line, char *file, INTER_FUNCTIONSIG_NOT_ST) {
     if (is_KeyInterrupt == signal_appear){
         is_KeyInterrupt = signal_reset;
-        if (type != NULL)
-            *type = R_error;
         setResultError(E_KeyInterrupt, KEY_INTERRUPT, line, file, true, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
         return true;
     }
     return false;
 }
 
+static bool gotoStatement(Statement **next, INTER_FUNCTIONSIG) {
+    Statement *label_st = checkLabel(st, result->label);
+
+    if (label_st == NULL){
+        setResultErrorSt(E_GotoException, L"Don't find label", true, st, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
+        return false;
+    }
+
+    runLabel(CALL_INTER_FUNCTIONSIG(label_st, var_list, result, belong));
+    if (!CHECK_RESULT(result))
+        return false;
+    *next = label_st->next;
+    return true;
+}
+
 /**
  * 局部程序运行statement
  * @param st
@@ -148,24 +161,22 @@ ResultType iterStatement(INTER_FUNCTIONSIG) {
     bak = signal(SIGINT, signalStopInter);
     do {
         base = st;
-        if (checkSignal(&type, base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong)))
+        if (checkSignal(base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong))) {
+            type = result->type;
             break;
+        }
         while (base != NULL) {
             freeResult(result);
             type = runStatement(CALL_INTER_FUNCTIONSIG(base, var_list, result, belong));
-            if (checkSignal(&type, base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong)))
+            if (checkSignal(base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong))) {
+                type = result->type;
                 break;
+            }
             if (type == R_goto && result->times == 0){
-                Statement *label_st = checkLabel(st, result->label);
-                if (label_st == NULL){
-                    setResultErrorSt(E_GotoException, L"Don't find label", true, st, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
-                    type = R_error;
+                if (!gotoStatement(&base, CALL_INTER_FUNCTIONSIG(st, var_list, result, belong))) {
+                    type = result->type;
                     break;
                 }
-                type = runLabel(CALL_INTER_FUNCTIONSIG(label_st, var_list, result, belong));
-                if (!RUN_TYPE(type))
-                    break;
-                base = label_st->next;
             }
             else if (!RUN_TYPE(type))
                 break;
@@ -208,24 +219,22 @@ ResultType globalIterStatement(Result *result, Inter *inter, Statement *st) {
     do {
         base = st;
         var_list = inter->var_list;
-        if (checkSignal(&type, base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong)))
+        if (checkSignal(base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong))) {
+            type = result->type;
             break;
+        }
         while (base != NULL) {
             freeResult(result);
             type = runStatement(CALL_INTER_FUNCTIONSIG(base, var_list, result, belong));
-            if (checkSignal(&type, base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong)))
+            if (checkSignal(base->line, base->code_file, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong))) {
+                type = result->type;
                 break;
+            }
             if (type == R_goto){
-                Statement *label_st = checkLabel(st, result->label);
-                if (label_st == NULL){
-                    setResultErrorSt(E_GotoException, L"Don't find label", true, st, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
-                    type = R_error;
+                if (!gotoStatement(&base, CALL_INTER_FUNCTIONSIG(st, var_list, result, belong))) {
+                    type = result->type;
                     break;
                 }
-                type = runLabel(CALL_INTER_FUNCTIONSIG(label_st, var_list, result, belong));
-                if (!RUN_TYPE(type))
-                    break;
-                base = label_st->next;
             }
             else if (!RUN_TYPE(type))
                 break;

+ 4 - 6
VirtulMathCore/src/runbranch.c

@@ -1028,16 +1028,16 @@ ResultType gotoLabel(INTER_FUNCTIONSIG){
 }
 
 ResultType runLabel(INTER_FUNCTIONSIG) {
-    // goto的值通过result传入
-    LinkValue *goto_value = result->value;
+    LinkValue *goto_value = result->value;  // goto的值通过result传入, 因此不能进行setResultCore
     result->value = NULL;
     freeResult(result);
-    var_list = pushVarList(var_list, inter);
+
     if (st->u.label_.as != NULL)
         assCore(st->u.label_.as, goto_value, false, false, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
+
     gc_freeTmpLink(&goto_value->gc_status);
     if (st->u.label_.as != NULL && !CHECK_RESULT(result))
-        goto return_;
+        return result->type;
 
     freeResult(result);
     if (st->u.label_.command != NULL)
@@ -1045,7 +1045,5 @@ ResultType runLabel(INTER_FUNCTIONSIG) {
     else
         setResult(result, inter);
 
-    return_:
-    popVarList(var_list);
     return result->type;
 }