Prechádzať zdrojové kódy

feat: 允许使用;操作形式参数

形式参数名后通过分号分割表示:
该形参之前(包括该形参)的参数赋值,
不允许使用key-value的形式

link #6
SongZihuan 4 rokov pred
rodič
commit
5afdad5dc9

+ 4 - 2
VirtulMathCore/include/parameter.h

@@ -2,6 +2,7 @@
 #define VIRTUALMATH_PARAMETER_H
 
 #include "__macro.h"
+#include "inter.h"
 
 struct Parameter{
     enum ParameterType{
@@ -13,6 +14,7 @@ struct Parameter{
     struct ParameterData{
         struct Statement *value;
         struct Statement *name;  // 仅在name-value模式生效
+        bool is_sep;  // 是否为分割符
     } data;
     struct Parameter *next;
 };
@@ -70,9 +72,9 @@ Parameter *makeNameParameter(struct Statement *value, struct Statement *name);
 Parameter *makeArgsParameter(struct Statement *st);
 Parameter *makeKwrgsParameter(struct Statement *st);
 Parameter *connectParameter(Parameter *new, Parameter *base);
-Parameter *connectValueParameter(struct Statement *st, Parameter *base);
+Parameter *connectValueParameter(Statement *st, Parameter *base, bool is_sep);
 Parameter *connectNameParameter(struct Statement *value, struct Statement *name, Parameter *base);
-Parameter *connectArgsParameter(struct Statement *st, Parameter *base);
+Parameter *connectArgsParameter(Statement *st, Parameter *base, bool is_sep);
 Parameter *connectKwargsParameter(struct Statement *st, Parameter *base);
 void freeParameter(Parameter *pt, bool free_st);
 Argument *listToArgument(LinkValue *list_value, long line, char *file, INTER_FUNCTIONSIG_NOT_ST);

+ 11 - 5
VirtulMathCore/parser/__grammar.c

@@ -241,11 +241,12 @@ bool callChildStatement(PASERSSIGNATURE, PasersFunction callBack, int type, Stat
  * @param ass 设定赋值符号
  * @return
  */
-bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal, bool is_list, bool is_dict, int sep,
-                     int ass) {
+bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal, bool is_list, bool is_dict,
+                int sep, int ass, int n_sep) {
     Parameter *new_pt = NULL;
     Token *tmp;
     bool last_pt = false;
+    int is_sep = 0;  // 0: 不需要处理 1: 是is_sep 2: 处理过is_sep
     enum {
         s_1,  // only_value模式
         s_2,  // name_value模式
@@ -262,10 +263,13 @@ bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal
 
     while (!last_pt){
         tmp = NULL;
+        if (is_sep == 1)
+            is_sep = 2;
         if (!is_dict && status != s_2 && checkToken(pm, MATHER_MUL))  // is_formal关闭对*args的支持
             status = s_3;
         else if (!is_list && checkToken(pm, MATHER_POW))  // is_formal关闭对*args的支持
             status = s_4;
+
         parserPolynomial(CALLPASERSSIGNATURE);
         if (!call_success(pm))
             goto error_;
@@ -281,7 +285,9 @@ bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal
         int pt_type = value_par;
         if (status == s_1){
             if (!checkToken(pm, sep)){
-                if (is_list || !checkToken(pm, ass))  // // is_list关闭对name_value的支持
+                if (is_sep == 0 && n_sep != -1 && checkToken(pm, n_sep))
+                    is_sep = 1;
+                else if (is_list || !checkToken(pm, ass))  // // is_list关闭对name_value的支持
                     last_pt = true;
                 else {
                     pt_type = name_par;
@@ -306,7 +312,7 @@ bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal
         }
 
         if (pt_type == value_par)
-            new_pt = connectValueParameter(tmp->data.st, new_pt);
+            new_pt = connectValueParameter(tmp->data.st, new_pt, is_sep == 1);
         else if (pt_type == name_par){
             Statement *tmp_value;
             if (!callChildStatement(CALLPASERSSIGNATURE, parserPolynomial, POLYNOMIAL, &tmp_value, "Don't get a parameter value"))
@@ -316,7 +322,7 @@ bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal
                 last_pt = true;
         }
         else if (pt_type == args_par){
-            new_pt = connectArgsParameter(tmp->data.st, new_pt);
+            new_pt = connectArgsParameter(tmp->data.st, new_pt, is_sep == 1);
             if (is_formal)
                 status = s_2;  // 是否规定*args只出现一次
             else

+ 12 - 9
VirtulMathCore/parser/grammar.c

@@ -414,12 +414,14 @@ void parserImport(PASERSSIGNATURE) {
         }
         if (checkToken(pm, MATHER_MUL))  // 导入所有
             goto mul_;
-        if (!parserParameter(CALLPASERSSIGNATURE, &pt, false, false, false, false, MATHER_COMMA, MATHER_ASSIGNMENT) || pt == NULL) {
+        if (!parserParameter(CALLPASERSSIGNATURE, &pt, false, false, false, false, MATHER_COMMA, MATHER_ASSIGNMENT,
+                             -1) || pt == NULL) {
             syntaxError(pm, syntax_error, line, 1, "Don't get any value to import");
             freeStatement(opt);
             goto return_;
         }
-        if (checkToken(pm, MATHER_AS) && (!parserParameter(CALLPASERSSIGNATURE, &as, false, true, false, false, MATHER_COMMA, MATHER_ASSIGNMENT) || as == NULL)) {
+        if (checkToken(pm, MATHER_AS) && (!parserParameter(CALLPASERSSIGNATURE, &as, false, true, false, false,
+                                                           MATHER_COMMA, MATHER_ASSIGNMENT, -1) || as == NULL)) {
             freeParameter(pt, true);
             syntaxError(pm, syntax_error, opt->line, 1, "Don't get any value after import");
             freeStatement(opt);
@@ -457,7 +459,7 @@ void parserVarControl(PASERSSIGNATURE) {
     Token *tmp = NULL;
     int token_type = readBackToken(pm);
     long int line = delToken(pm);
-    if (!parserParameter(CALLPASERSSIGNATURE, &var, false, true, true, true, MATHER_COMMA, MATHER_ASSIGNMENT) || var == NULL) {
+    if (!parserParameter(CALLPASERSSIGNATURE, &var, false, true, true, true, MATHER_COMMA, MATHER_ASSIGNMENT, -1) || var == NULL) {
         syntaxError(pm, syntax_error, line, 1, "Don't get any var");
         goto return_;
     }
@@ -1028,7 +1030,7 @@ void parserDef(PASERSSIGNATURE){
 
     if (!checkToken(pm, MATHER_LP))
         goto get_code;
-    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, true, false, false, MATHER_COMMA, MATHER_ASSIGNMENT)) {
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, true, false, false, MATHER_COMMA, MATHER_ASSIGNMENT, type==MATHER_DEF ? MATHER_SEMICOLON : -1)) {
         lexEnter(pm, false);
         syntaxError(pm, syntax_error, line, 1, "Don't get a function/class parameter");
         goto error_;
@@ -1168,7 +1170,7 @@ void parserTuple(PASERSSIGNATURE){
     addToken_(pm ,tmp);
 
     parserPt:
-    if (!parserParameter(CALLPASERSSIGNATURE, &pt, false, false, true, false, MATHER_COMMA, MATHER_ASSIGNMENT)) {
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt, false, false, true, false, MATHER_COMMA, MATHER_ASSIGNMENT, -1)) {
         syntaxError(pm, syntax_error, line, 1, "Don't get tuple element");
         goto return_;
     }
@@ -1241,7 +1243,7 @@ bool tailCall(PASERSSIGNATURE, Token *left_token, Statement **st){
 
     if (checkToken(pm, MATHER_RP))
         goto not_pt;
-    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, false, false, false, MATHER_COMMA, MATHER_ASSIGNMENT)) {
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, false, false, false, MATHER_COMMA, MATHER_ASSIGNMENT, -1)) {
         syntaxError(pm, syntax_error, line, 1, "Don't get call parameter");
         return false;
     }
@@ -1271,7 +1273,8 @@ bool tailSlice(PASERSSIGNATURE, Token *left_token, Statement **st){
     line = tmp->line;
     addToken_(pm ,tmp);
 
-    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, true, true, true, (type == SliceType_down_ ? MATHER_COMMA : MATHER_COLON), MATHER_ASSIGNMENT)) {
+    if (!parserParameter(CALLPASERSSIGNATURE, &pt, true, true, true, true,
+                         (type == SliceType_down_ ? MATHER_COMMA : MATHER_COLON), MATHER_ASSIGNMENT, -1)) {
         syntaxError(pm, syntax_error, line, 1, "Don't get slice element");
         return false;
     }
@@ -1408,7 +1411,7 @@ void parserBaseValue(PASERSSIGNATURE){
             Parameter *pt = NULL;
             Statement *lambda_st = NULL;
             if (!parserParameter(CALLPASERSSIGNATURE, &pt, false, true, false, false, MATHER_COMMA,
-                                 MATHER_ASSIGNMENT)) {
+                                 MATHER_ASSIGNMENT, -1)) {
                 freeToken(value_token, true);
                 syntaxError(pm, syntax_error, value_token->line, 1, "Don't get a lambda parameter");
                 goto return_;
@@ -1490,7 +1493,7 @@ void parserBaseValue(PASERSSIGNATURE){
             Parameter *pt = NULL;
             int parser_status;
             parser_status = parserParameter(CALLPASERSSIGNATURE, &pt, true, false, false, true, MATHER_COMMA,
-                                            MATHER_COLON);
+                                            MATHER_COLON, -1);
             if (!parser_status) {
                 freeToken(value_token, true);
                 syntaxError(pm, syntax_error, value_token->line, 1, "Don't get a dict parameter");

+ 2 - 1
VirtulMathCore/parser/include/__grammar.h

@@ -53,8 +53,9 @@ bool callParserAs(PASERSSIGNATURE, Statement **st,char *message);
 bool callChildStatement(PASERSSIGNATURE, PasersFunction callBack, int type, Statement **st, char *message);
 bool callChildToken(PASERSSIGNATURE, PasersFunction callBack, int type, Token **tmp, char *message,
                     int error_type);
+
 bool parserParameter(PASERSSIGNATURE, Parameter **pt, bool enter, bool is_formal, bool is_list, bool is_dict,
-                     int sep,int ass);
+                int sep, int ass, int n_sep);
 
 void twoOperation(PASERSSIGNATURE, PasersFunction callBack, GetSymbolFunction getSymbol, ChecktLeftToken checkleft,
                   int call_type, int self_type, char *call_name, char *self_name, bool is_right);

+ 26 - 5
VirtulMathCore/src/parameter.c

@@ -92,6 +92,7 @@ Parameter *makeParameter(void){
     tmp->type = value_par;
     tmp->data.value = NULL;
     tmp->data.name = NULL;
+    tmp->data.is_sep = false;
     tmp->next = NULL;
     return tmp;
 }
@@ -100,6 +101,7 @@ Parameter *copyenOneParameter(Parameter *base){
     Parameter *tmp = makeParameter();
     tmp->data.value = copyStatement(base->data.value);
     tmp->data.name = copyStatement(base->data.name);
+    tmp->data.is_sep = base->data.is_sep;
     tmp->type = base->type;
     return tmp;
 }
@@ -150,8 +152,9 @@ Parameter *connectParameter(Parameter *new, Parameter *base){
     return tmp;
 }
 
-Parameter *connectValueParameter(Statement *st, Parameter *base){
+Parameter *connectValueParameter(Statement *st, Parameter *base, bool is_sep) {
     Parameter *new = makeValueParameter(st);
+    new->data.is_sep = is_sep;
     return connectParameter(new, base);
 }
 
@@ -160,8 +163,9 @@ Parameter *connectNameParameter(Statement *value, Statement *name, Parameter *ba
     return connectParameter(new, base);
 }
 
-Parameter *connectArgsParameter(Statement *st, Parameter *base){
+Parameter *connectArgsParameter(Statement *st, Parameter *base, bool is_sep) {
     Parameter *new = makeArgsParameter(st);
+    new->data.is_sep = is_sep;
     return connectParameter(new, base);
 }
 
@@ -502,6 +506,14 @@ Argument * getArgument(Parameter *call, bool is_dict, INTER_FUNCTIONSIG_NOT_ST)
     return new_arg;
 }
 
+bool checkIsSep(Parameter *pt) {
+    for (PASS; pt != NULL; pt = pt->next) {
+        if (pt->data.is_sep == true)
+            return true;
+    }
+    return false;
+}
+
 /**
  * 参数表:
  |实参 \ 形参| name | value | arg | kwarg | null |
@@ -531,8 +543,9 @@ ResultType setParameterCore(fline line, char *file, Argument *call, Parameter *f
         error_to_less = -1,
         error_to_more = -2,
         error_kw = -3,
+        error_unknown = -4,
         finished = 0,
-    } status = match_status;
+    } status;
     function = copyParameter(function_base);
     tmp_function = function;
     setResultCore(result);
@@ -556,8 +569,13 @@ ResultType setParameterCore(fline line, char *file, Argument *call, Parameter *f
             status = mul_par;
         else if (call->type == value_arg)
             status = match_status;
-        else if (call->type == name_arg)
-            status = self_ass;
+        else if (call->type == name_arg) {
+            if (checkIsSep(function))
+                status = error_to_less;
+            else
+                status = self_ass;
+        } else
+            status = error_unknown;
 
         freeResult(result);
         switch (status) {
@@ -642,6 +660,9 @@ ResultType setParameterCore(fline line, char *file, Argument *call, Parameter *f
             case error_kw:
                 setResultError(E_ArgumentException, OBJ_NOTSUPPORT(**), line, file, true, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
                 goto return_;
+            case error_unknown:
+                setResultError(E_ArgumentException, "Argument Unknown Exception", line, file, true, CALL_INTER_FUNCTIONSIG_NOT_ST(var_list, result, belong));
+                goto return_;
             default:
                 goto break_;
         }