Răsfoiți Sursa

fix: 修复command line模式的bug

修复: command line模式无法很好识别if等分支语句的结尾
新增: if等分支单行语句不需要大括号

修复: command line模式无法读取GC显示时的getc
原因: 对stdin使用了fgetwc就无法再使用getc

link #13
SongZihuan 4 ani în urmă
părinte
comite
2e5e5f6075

+ 3 - 3
src/virtualmath.c

@@ -37,6 +37,7 @@ void runCodeStdin(Inter *inter, char *hello_string) {
     setResultCore(&result);
     if (hello_string != NULL)
         printf("%s", hello_string);
+
     while (!should_break){
         if (ferror(stdin) || feof(stdin))
             clearerr(stdin);
@@ -52,10 +53,9 @@ void runCodeStdin(Inter *inter, char *hello_string) {
 }
 
 bool runParser(char *code_file, Inter *inter, bool is_one, Statement **st) {
-    ParserMessage *pm = makeParserMessageFile(code_file);
+    ParserMessage *pm = makeParserMessageFile(code_file, is_one);
     *st = makeStatement(0, (code_file == NULL) ? "stdin" : code_file);
-    parserCommandList(pm, inter, true, is_one, *st);
-
+    parserCommandList(pm, inter, true, *st);
     if (pm->status == int_error) {
         fprintf(stderr, "KeyInterrupt\n");
     } else if (pm->status != success)

+ 4 - 3
vmcore/include/grammar.h

@@ -13,13 +13,14 @@ struct ParserMessage{
     } status;
     char *status_message;
     char *file;
+    bool short_cm;  // 短匹配
 };
 
 typedef struct ParserMessage ParserMessage;
 
-ParserMessage *makeParserMessageFile(char *file_dir);
-ParserMessage *makeParserMessageStr(wchar_t *str);
+ParserMessage *makeParserMessageFile(char *file_dir, bool short_cm);
+ParserMessage *makeParserMessageStr(wchar_t *str, bool short_cm);
 void freeParserMessage(ParserMessage *pm, bool self);
-void parserCommandList(ParserMessage *pm, Inter *inter, bool global, bool is_one, Statement *st);
+void parserCommandList(ParserMessage *pm, Inter *inter, bool global, Statement *st);
 
 #endif //VIRTUALMATH_GRAMMAR_H

+ 2 - 2
vmcore/ofunc/src/sys.c

@@ -184,9 +184,9 @@ ResultType vm_exec(O_FUNC){
         out = false;
 
     {
-        ParserMessage *pm = makeParserMessageStr(str->value->data.str.str);
+        ParserMessage *pm = makeParserMessageStr(str->value->data.str.str, false);
         new_st = makeStatement(0, "exec");
-        parserCommandList(pm, inter, true, false, new_st);
+        parserCommandList(pm, inter, true, new_st);
 
         if (pm->status == int_error) {
             setResultError(E_KeyInterrupt, KEY_INTERRUPT, LINEFILE, true, CNEXT_NT);

+ 37 - 19
vmcore/parser/grammar.c

@@ -1,23 +1,24 @@
 #include "__grammar.h"
 
-static ParserMessage *makeParserMessageCore() {
+static ParserMessage *makeParserMessageCore(bool short_cm) {
     ParserMessage *tmp = memCalloc(1, sizeof(ParserMessage));
     tmp->file = NULL;
     tmp->tm = NULL;
     tmp->status = success;
     tmp->status_message = NULL;
+    tmp->short_cm = short_cm;
     return tmp;
 }
 
-ParserMessage *makeParserMessageFile(char *file_dir) {
-    ParserMessage *tmp = makeParserMessageCore();
+ParserMessage *makeParserMessageFile(char *file_dir, bool short_cm) {
+    ParserMessage *tmp = makeParserMessageCore(short_cm);
     tmp->file = memStrcpy(file_dir == NULL ? "stdin" : file_dir);
     tmp->tm = makeTokenMessageFile(file_dir);
     return tmp;
 }
 
-ParserMessage *makeParserMessageStr(wchar_t *str) {
-    ParserMessage *tmp = makeParserMessageCore();
+ParserMessage *makeParserMessageStr(wchar_t *str, bool short_cm) {
+    ParserMessage *tmp = makeParserMessageCore(short_cm);
     tmp->file = memStrcpy("exec");
     tmp->tm = makeTokenMessageStr(str);
     return tmp;
@@ -44,7 +45,7 @@ void freeParserMessage(ParserMessage *pm, bool self) {
  * | parserCommand MATHER_SEMICOLON
  * | parserCommand MATHER_EOF
  */
-void parserCommandList(P_FUNC, bool global, bool is_one, Statement *st) {
+void parserCommandList(P_FUNC, bool global, Statement *st) {
     int token_type;
     int save_enter = pm->tm->file->filter_data.enter;
     char *command_message = global ? "ERROR from command list(get parserCommand)" : NULL;
@@ -56,6 +57,7 @@ void parserCommandList(P_FUNC, bool global, bool is_one, Statement *st) {
     pm_KeyInterrupt = signal_reset;
     bak = signal(SIGINT, signalStopPm);
     pm->tm->file->filter_data.enter = 0;
+    bool is_one = pm->short_cm;
 
     while (!should_break){
         token_type = readBackToken(pm);
@@ -82,10 +84,9 @@ void parserCommandList(P_FUNC, bool global, bool is_one, Statement *st) {
                 delToken(pm);
                 if (is_one)
                     should_break = true;
-            }
-            else if (stop == MATHER_SEMICOLON)
+            } else if (stop == MATHER_SEMICOLON)
                 delToken(pm);
-            else  if(stop != MATHER_EOF){
+            else if(stop != MATHER_EOF){
                 if (global) {
                     Token *tk = popNewToken(pm->tm);
                     freeToken(tk, true);
@@ -769,6 +770,8 @@ void parserIf(P_FUNC){
             break;
         }
         case MATHER_ENTER:
+            if (pm->short_cm)
+                goto default_;
             delToken(pm);
             goto again;
         case MATHER_SEMICOLON:
@@ -865,6 +868,8 @@ void parserWhile(P_FUNC){
             break;
         }
         case MATHER_ENTER:
+            if (pm->short_cm)
+                goto default_;
             delToken(pm);
             goto again;
         case MATHER_SEMICOLON:
@@ -959,6 +964,8 @@ void parserTry(P_FUNC){
             break;
         }
         case MATHER_ENTER:
+            if (pm->short_cm)
+                goto default_;
             delToken(pm);
             goto again;
         case MATHER_SEMICOLON:
@@ -1046,25 +1053,36 @@ void parserDef(P_FUNC){
 void parserCode(P_FUNC) {
     long int line = 0;
     Statement *st = makeStatement(line, pm->file);
+    bool backup = pm->short_cm;
+    bool short_cm = false;
     while (true){
-        if (readBackToken(pm) != MATHER_LC)
-            goto again_;
-        line = delToken(pm);
-        break;
-        again_:
-        if (!checkToken(pm, MATHER_ENTER))
-            goto return_;
+        switch (readBackToken(pm)) {
+            case MATHER_LC:
+                line = delToken(pm);
+                goto out;
+            case MATHER_ENTER:
+                delToken(pm);
+                continue;
+            default:
+                short_cm = true;
+                goto out;
+        }
     }
-    parserCommandList(CP_FUNC, false, false, st);
+
+    out:
+    pm->short_cm = short_cm;
+    parserCommandList(CP_FUNC, false, st);
+    pm->short_cm = backup;
     if (!call_success(pm))
         goto error_;
 
-    if (!checkToken(pm, MATHER_RC)) {
+    if (short_cm)
+        addLexToken(pm, MATHER_ENTER);
+    else if (!checkToken(pm, MATHER_RC)) {
         syntaxError(pm, syntax_error, line, 1, "Don't get the }");  // 使用{的行号
         goto error_;
     }
 
-    return_:
     addStatementToken(T_CODE, st, pm);
     return;
 

+ 3 - 2
vmcore/parser/syntax.c

@@ -315,8 +315,8 @@ int getMatherStatus(LexFile *file, LexMathers *mathers) {
         backslashMather(p, mathers->mathers[MATHER_NOTENTER]);
         commentMather(p, mathers->mathers[MATHER_COMMENT]);
         aCharMather(p, mathers->mathers[MATHER_ENTER], '\n');
+        aCharMather(p, mathers->mathers[MATHER_EOF], WEOF);
 
-        charMatherMacro(MATHER_EOF, WEOF);
         strMatherMacro(MATHER_IF, "if");  // 条件判断
         strMatherMacro(MATHER_ELIF, "elif");  // 条件循环
         strMatherMacro(MATHER_WHILE, "while");  // 条件循环
@@ -431,8 +431,9 @@ Token *getToken(LexFile *file, LexMathers *mathers) {
     int status = MATHER_SPACE;
     int filter;
 
-    while ((filter = lexFilter(file, status)) == -1)
+    do
         status = getMatherStatus(file, mathers);
+    while ((filter = lexFilter(file, status)) == -1);
 
     if (status == -2 || status == -3)
         return makeLexToken(status, NULL, NULL, file->line);

+ 3 - 2
vmcore/src/inter.c

@@ -149,9 +149,10 @@ void freeInter(Inter *inter, bool show_gc) {
     freeBaseInterData(inter);
     freePackage(inter->package);
 #if DEBUG
-    if (show_gc && (printf("\nEnter '1' to show gc: "), getc(stdin) == '1')) {
+    wint_t ch;
+    if (show_gc && (printf("\nEnter '1' to show gc: "), (fgetwc(stdin)) == L'1')) {
         printGC(inter);
-        while (getc(stdin) != '\n')
+        while ((ch = fgetwc(stdin)) != '\n' || ch == WEOF)
             PASS;
     }
 #endif

+ 3 - 3
vmcore/src/runfile.c

@@ -2,7 +2,7 @@
 
 bool importRunParser(ParserMessage *pm, fline line, char *file, Statement *run_st, FUNC_NT) {
     setResultCore(result);
-    parserCommandList(pm, inter, true, false, run_st);
+    parserCommandList(pm, inter, true, run_st);
     if (pm->status == int_error)
         setResultError(E_KeyInterrupt, KEY_INTERRUPT, line, file, true, CNEXT_NT);
     else if (pm->status != success) {
@@ -140,7 +140,7 @@ ResultType includeFile(FUNC) {
         goto return_;
 
     new_st = makeStatement(0, file_dir);
-    pm = makeParserMessageFile(file_dir);
+    pm = makeParserMessageFile(file_dir, false);
 
     if (!importRunParser(pm, st->line, st->code_file, new_st, CNEXT_NT))
         goto return_;
@@ -163,7 +163,7 @@ ResultType importVMFileCore(Inter *import_inter, char *path, fline line, char *c
     Statement *run_st = NULL;
     setResultCore(result);
 
-    pm = makeParserMessageFile(path);
+    pm = makeParserMessageFile(path, false);
     run_st = makeStatement(0, path);
 
     if (!importRunParser(pm, line, code_file, run_st, CNEXT_NT))