Przeglądaj źródła

refactor & feat: 新增parser错误传递机制

SongZihuan 3 lat temu
rodzic
commit
e2162fc645

+ 31 - 2
include/core/core-parser.h

@@ -3,6 +3,7 @@
 #include "aFunToolExport.h"
 #include "reader.h"
 #include "code.h"
+#include <list>
 
 namespace aFuncore {
     class AFUN_CORE_EXPORT Parser {
@@ -49,10 +50,16 @@ namespace aFuncore {
             TK_EOF = 11,
         } TokenType;
 
+        struct ParserEvent;
+
         inline explicit Parser(Reader &reader_);
 
         TokenType getTokenFromLexical(std::string &text);
         bool parserCode(Code &code);
+
+        [[nodiscard]] inline size_t countEvent() const;
+        inline ParserEvent popEvent();
+        [[nodiscard]] inline const ParserEvent &checkEvent() const;
     private:
         typedef enum DoneStatus {
             DEL_TOKEN = 0,
@@ -61,8 +68,8 @@ namespace aFuncore {
             ERROR_TOKEN = -2
         } DoneStatus;
 
+        std::list<ParserEvent> event;
         Reader &reader;
-
         struct {
             LexicalStatus status;
             TokenType token;  // token类型
@@ -71,7 +78,6 @@ namespace aFuncore {
             bool is_end;
             bool is_error;
         } lexical;
-
         struct {
             bool back;
             TokenType token;
@@ -99,6 +105,29 @@ namespace aFuncore {
         Code::ByteCode *codePrefix(Code &code, size_t deep);
         Code::ByteCode *codeList(Code &code, size_t deep);
         Code::ByteCode *codeListEnd(Code &code);
+
+        inline void pushEvent(const ParserEvent &new_event);
+        inline void pushEvent(ParserEvent &&new_event);
+    };
+
+    struct Parser::ParserEvent {
+        typedef enum EventType {
+            parser_error_unknown = -1,  // 遇到未知错误
+
+            lexical_error_char = -2,  // 遇到非正常符号
+            lexical_error_element_end = -3,  // 注释未结束
+            syntactic_error_nested_too_deep = -4,
+            syntactic_error_block_p_end = -5,
+            syntactic_error_block_b_end = -6,
+            syntactic_error_block_c_end = -7,
+            syntactic_error_prefix = -8,
+
+            lexical_warning_comment_end = 1,  // 注释未结束
+        } EventType;
+
+        EventType type;
+        aFuntool::FileLine line;
+        std::string info;
     };
 
 }

+ 26 - 12
include/core/core-parser.inline.h

@@ -3,21 +3,35 @@
 #include "core-parser.h"
 
 namespace aFuncore {
-    Parser::Parser(Reader &reader_) : reader{reader_} {
-        lexical.status = lex_begin;
-        lexical.token = TK_PREFIX;
-        lexical.last = 0;
-        lexical.mutli_comment = 0;
-        lexical.is_end = false;
-        lexical.is_error = false;
-
-        syntactic.back = false;
-        syntactic.token = TK_PREFIX;
-        syntactic.text = "";
-        syntactic.is_error = false;
+    inline Parser::Parser(Reader &reader_)
+        : reader{reader_},
+          lexical{lex_begin, TK_PREFIX, 0, 0, false, false},
+          syntactic{false, TK_PREFIX, "", false}{
 
         reader.readFirstWord();
     }
+
+    inline Parser::ParserEvent Parser::popEvent() {
+        ParserEvent pop = event.front();
+        event.pop_front();
+        return pop;
+    }
+
+    inline size_t Parser::countEvent() const {
+        return event.size();
+    }
+
+    inline void Parser::pushEvent(const ParserEvent &new_event) {
+        event.push_back(new_event);
+    }
+
+    inline void Parser::pushEvent(ParserEvent &&new_event) {
+        event.push_back(new_event);
+    }
+
+    inline const Parser::ParserEvent &Parser::checkEvent() const {
+            return event.front();
+    }
 }
 
 #endif //AFUN_CORE_PARSER_INLINE_H

+ 11 - 6
src/core/lexical.cpp

@@ -70,6 +70,7 @@ namespace aFuncore {
                     return CONTINUE_TOKEN;
                 default:
                     fatalErrorLog(aFunCoreLogger, EXIT_FAILURE, "Switch illegal characters");
+                    pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
                     return ERROR_TOKEN;
             }
         } else if (strchr("([{)]}", ch)) { /* 括号 */
@@ -94,6 +95,7 @@ namespace aFuncore {
                     return FINISH_TOKEN;
                 default:
                     fatalErrorLog(aFunCoreLogger, EXIT_FAILURE, "Switch illegal characters");
+                    pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
                     return ERROR_TOKEN;
             }
         } else if (ch == ';') {
@@ -109,7 +111,7 @@ namespace aFuncore {
             setLexicalLast(lex_element_short, TK_ELEMENT_SHORT);
             return CONTINUE_TOKEN;
         }
-        // TODO-szh 给出警告
+        pushEvent({ParserEvent::lexical_error_char, reader.getFileLine(), ""});
         return DEL_TOKEN;
     }
 
@@ -136,6 +138,7 @@ namespace aFuncore {
                     return FINISH_TOKEN;
                 default:
                     fatalErrorLog(aFunCoreLogger, EXIT_FAILURE, "Switch illegal characters");
+                    pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
                     return ERROR_TOKEN;
             }
         } else if (ch == ')') {
@@ -151,10 +154,11 @@ namespace aFuncore {
                     return FINISH_TOKEN;
                 default:
                     fatalErrorLog(aFunCoreLogger, EXIT_FAILURE, "Switch illegal characters");
+                    pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
                     return ERROR_TOKEN;
             }
         }
-        // TODO-szh 给出警告
+        pushEvent({ParserEvent::lexical_error_char, reader.getFileLine(), ""});
         return DEL_TOKEN;
     }
 
@@ -203,7 +207,7 @@ namespace aFuncore {
     Parser::DoneStatus Parser::doneMutliComment(char ch) {
         if (ch == aFuntool::NUL) {
             lexical.status = lex_mutli_comment_end;
-            // TODO-szh 给出警告
+            pushEvent({ParserEvent::lexical_warning_comment_end, reader.getFileLine(), ""});
             return FINISH_TOKEN;
         } else if (ch == ';')
             lexical.status = lex_mutli_comment_end_before;
@@ -224,7 +228,7 @@ namespace aFuncore {
     Parser::DoneStatus Parser::doneMutliCommentBeforeEnd(char ch) {
         if (ch == aFuntool::NUL) {
             setLexicalLast(lex_mutli_comment_end, TK_COMMENT);
-            // TODO-szh 给出警告
+            pushEvent({ParserEvent::lexical_warning_comment_end, reader.getFileLine(), ""});
             return FINISH_TOKEN;
         } else if (ch == ';') {
             /* 嵌套注释 */
@@ -257,7 +261,7 @@ namespace aFuncore {
             setLexicalLast(lex_element_long_end, TK_ELEMENT_LONG);
             return CONTINUE_TOKEN;
         } else if (ch == aFuntool::NUL) {
-            // TODO-szh 添加警告
+            pushEvent({ParserEvent::lexical_error_element_end, reader.getFileLine(), ""});
             return ERROR_TOKEN;
         }
         lexical.status = lex_element_long;
@@ -331,7 +335,7 @@ namespace aFuncore {
                 return TK_ERROR;
 
             if (isascii(ch) && iscntrl(ch) && !isspace(ch) && ch != aFuntool::NUL)  // ascii 控制字符
-                NULL;  // TODO-szh 给出警告
+                pushEvent({ParserEvent::lexical_error_char, reader.getFileLine(), ""});
 
             switch (lexical.status) {
                 case lex_begin:
@@ -374,6 +378,7 @@ namespace aFuncore {
 
             if (re == ERROR_TOKEN) {
                 tt = TK_ERROR;
+                lexical.is_error = true;
                 break;
             } else if (re == DEL_TOKEN) {  // 删除该token, 继续执行
                 char *word = reader.readWord(lexical.last);

+ 45 - 48
src/core/syntactic.cpp

@@ -25,80 +25,72 @@ namespace aFuncore {
         switch (syntactic.token) {
             case TK_ELEMENT_SHORT:
             case TK_ELEMENT_LONG:
-                return  new Code::ByteCode(code, syntactic.text, reader.getFileLine(), prefix);
+                return new Code::ByteCode(code, syntactic.text, reader.getFileLine(), prefix);
             case TK_LP: {
                 Code::ByteCode *code_list;
-                if (depth <= SYNTACTIC_MAX_DEPTH)
+                if (depth <= SYNTACTIC_MAX_DEPTH) {
                     code_list = codeList(code, depth);
-                else {
-                    // TODO-szh 错误提示
+                    code_list = new Code::ByteCode(code, Code::ByteCode::block_p, code_list, reader.getFileLine(), prefix);
+                } else {
+                    pushEvent({ParserEvent::syntactic_error_nested_too_deep, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                     return nullptr;
                 }
 
                 getToken();
-                switch (syntactic.token) {
-                    case TK_RP:
-                        break;
-                    case TK_ERROR:
-                        return nullptr;
-                    default:
-                        goBackToken();
-                        // TODO-szh 错误提示
-                        return nullptr;
+                if (syntactic.token != TK_RP && syntactic.token != TK_ERROR) {
+                    goBackToken();
+                    pushEvent({ParserEvent::syntactic_error_block_p_end, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                 }
 
-                return new Code::ByteCode(code, Code::ByteCode::block_p, code_list, reader.getFileLine(), prefix);
+                return code_list;
             }
             case TK_LB: {
                 Code::ByteCode *code_list;
-                if (depth <= SYNTACTIC_MAX_DEPTH)
+                if (depth <= SYNTACTIC_MAX_DEPTH) {
                     code_list = codeList(code, depth);
-                else {
-                    // TODO-szh 错误提示
+                    code_list = new Code::ByteCode(code, Code::ByteCode::block_b, code_list, reader.getFileLine(), prefix);
+                } else {
+                    pushEvent({ParserEvent::syntactic_error_nested_too_deep, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                     return nullptr;
                 }
 
                 getToken();
-                switch (syntactic.token) {
-                    case TK_RB:
-                        break;
-                    case TK_ERROR:
-                        return nullptr;
-                    default:
-                        goBackToken();
-                        // TODO-szh 错误提示
-                        return nullptr;
+                if (syntactic.token != TK_RB && syntactic.token != TK_ERROR) {
+                    goBackToken();
+                    pushEvent({ParserEvent::syntactic_error_block_b_end, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                 }
 
-                return new Code::ByteCode(code, Code::ByteCode::block_b, code_list, reader.getFileLine(), prefix);
+                return code_list;
             }
             case TK_LC: {
                 Code::ByteCode *code_list;
-                if (depth <= SYNTACTIC_MAX_DEPTH)
+                if (depth <= SYNTACTIC_MAX_DEPTH) {
                     code_list = codeList(code, depth);
-                else {
-                    // TODO-szh 错误提示
+                    code_list = new Code::ByteCode(code, Code::ByteCode::block_c, code_list, reader.getFileLine(), prefix);
+                } else {
+                    pushEvent({ParserEvent::syntactic_error_nested_too_deep, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                     return nullptr;
                 }
 
                 getToken();
-                switch (syntactic.token) {
-                    case TK_RC:
-                        break;
-                    case TK_ERROR:
-                        return nullptr;
-                    default:
-                        goBackToken();
-                        // TODO-szh 错误提示
-                        return nullptr;
+                if (syntactic.token != TK_RC && syntactic.token != TK_ERROR) {
+                    goBackToken();
+                    pushEvent({ParserEvent::syntactic_error_block_c_end, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
                 }
 
-                return new Code::ByteCode(code, Code::ByteCode::block_c, code_list, reader.getFileLine(), prefix);
+                return code_list;
             }
             case TK_ERROR:
                 return nullptr;
             default:
-                // TODO-szh 错误提示
+                pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
+                syntactic.is_error = true;
                 return nullptr;
         }
     }
@@ -108,10 +100,12 @@ namespace aFuncore {
         getToken();
         if (syntactic.token != TK_PREFIX) {
             goBackToken();
-            // TODO-szh 错误提示
-        } else if (syntactic.text.size() != 1)
-            NULL;  // TODO-szh 错误提示
-        else
+            pushEvent({ParserEvent::syntactic_error_prefix, reader.getFileLine(), ""});
+            syntactic.is_error = true;
+        } else if (syntactic.text.size() != 1) {
+            pushEvent({ParserEvent::syntactic_error_prefix, reader.getFileLine(), ""});
+            syntactic.is_error = true;
+        } else
             ch = syntactic.text[0];
         return codeSelf(code, depth, ch);
     }
@@ -174,12 +168,15 @@ namespace aFuncore {
                 goBackToken();
                 Code::ByteCode *re = codeList(code, 0);
                 getToken();
-                if (syntactic.token != TK_EOF && syntactic.token != TK_ERROR)
-                    NULL; // TODO-szh 错误提示
+                if (syntactic.token != TK_EOF && syntactic.token != TK_ERROR) {
+                    pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
+                    syntactic.is_error = true;
+                }
                 return re;
             }
             default:
-                // TODO-szh 错误提示
+                pushEvent({ParserEvent::parser_error_unknown, reader.getFileLine(), ""});
+                syntactic.is_error = true;
                 return nullptr;
         }
     }

+ 22 - 7
test/src/core-syntactic.cpp

@@ -2,6 +2,7 @@
 #include "core-parser.h"
 
 const char *str = "{if true [HelloWorld (10)]}\n";
+const char *str2 = "{if true [HelloWorld (10)\n";
 
 class ReaderString : public aFuncore::Reader {
     std::string str;
@@ -29,12 +30,26 @@ public:
 };
 
 int main() {
-    auto reader = ReaderString(str, "str");
-    auto parser = aFuncore::Parser(reader);
-    auto code = aFuncore::Code("test.aun");
-    bool ret = parser.parserCode(code);
-    if (!ret)
-        return 1;
-    code.display();
+    {
+        auto reader = ReaderString(str, "str");
+        auto parser = aFuncore::Parser(reader);
+        auto code = aFuncore::Code("test.aun");
+        bool ret = parser.parserCode(code);
+        if (!ret)
+            return 1;
+        code.display();
+    }
+
+    {
+        auto reader = ReaderString(str2, "str2");
+        auto parser = aFuncore::Parser(reader);
+        auto code = aFuncore::Code("test2.aun");
+        parser.parserCode(code);
+
+        while (parser.countEvent() != 0) {
+            auto event = parser.popEvent();
+            printf("Event %d, %d\n", event.type, event.line);
+        }
+    }
     return 0;
 }