2
0
Эх сурвалжийг харах

refactor & feat: 新增syntactic机制

SongZihuan 3 жил өмнө
parent
commit
250ed680b3

+ 19 - 1
include/core/core-parser.h

@@ -2,6 +2,7 @@
 #define AFUN_CORE_PARSER_H
 #include "aFunToolExport.h"
 #include "reader.h"
+#include "code.h"
 
 namespace aFuncore {
     class AFUN_CORE_EXPORT Parser {
@@ -51,7 +52,7 @@ namespace aFuncore {
         inline explicit Parser(Reader &reader_);
 
         TokenType getTokenFromLexical(std::string &text);
-
+        bool parserCode(Code &code);
     private:
         typedef enum DoneStatus {
             DEL_TOKEN = 0,
@@ -61,6 +62,7 @@ namespace aFuncore {
         } DoneStatus;
 
         Reader &reader;
+
         struct {
             LexicalStatus status;
             TokenType token;  // token类型
@@ -70,6 +72,13 @@ namespace aFuncore {
             bool is_error;
         } lexical;
 
+        struct {
+            bool back;
+            TokenType token;
+            std::string text;
+            bool is_error;
+        } syntactic;
+
         void setLexicalLast(LexicalStatus status, TokenType token);
         DoneStatus doneBegin(char ch);
         DoneStatus donePrefixBlock(char ch);
@@ -81,6 +90,15 @@ namespace aFuncore {
         DoneStatus doneElementLongEnd(char ch);
         DoneStatus doneElementShort(char ch);
         DoneStatus doneSpace(char ch);
+
+        bool getToken();
+        bool goBackToken();
+
+        static const size_t SYNTACTIC_MAX_DEPTH = 218;
+        Code::ByteCode *codeSelf(Code &code, size_t deep, char prefix);
+        Code::ByteCode *codePrefix(Code &code, size_t deep);
+        Code::ByteCode *codeList(Code &code, size_t deep);
+        Code::ByteCode *codeListEnd(Code &code);
     };
 
 }

+ 5 - 0
include/core/core-parser.inline.h

@@ -11,6 +11,11 @@ namespace aFuncore {
         lexical.is_end = false;
         lexical.is_error = false;
 
+        syntactic.back = false;
+        syntactic.token = TK_PREFIX;
+        syntactic.text = "";
+        syntactic.is_error = false;
+
         reader.readFirstWord();
     }
 }

+ 3 - 0
src/core/code.cpp

@@ -341,6 +341,9 @@ RETURN_FALSE:
         while (tmp->next != nullptr)
             tmp = tmp->next;
 
+        if (new_code == nullptr)
+            return tmp;
+
         if (new_code->type == code_start) {
             errorLog(aFunCoreLogger, "Code connect with `start`");
             return tmp;

+ 195 - 0
src/core/syntactic.cpp

@@ -0,0 +1,195 @@
+#include "core-parser.h"
+#include "init.h"
+
+namespace aFuncore {
+    bool Parser::getToken() {
+        if (syntactic.back) {
+            syntactic.back = false;
+            return true;
+        }
+
+        syntactic.token = getTokenFromLexical(syntactic.text);
+        return syntactic.token != TK_ERROR;  // 非错误则返回true, 遇到错误则返回false
+    }
+
+    bool Parser::goBackToken() {
+        if (syntactic.back)
+            return false;  // 已经有一个回退
+        syntactic.back = true;
+        return true;
+    }
+
+    Code::ByteCode *Parser::codeSelf(Code &code, size_t depth, char prefix) {  // NOLINT
+        depth++;
+        getToken();
+        switch (syntactic.token) {
+            case TK_ELEMENT_SHORT:
+            case TK_ELEMENT_LONG:
+                return  new Code::ByteCode(code, syntactic.text, reader.getFileLine(), prefix);
+            case TK_LP: {
+                Code::ByteCode *code_list;
+                if (depth <= SYNTACTIC_MAX_DEPTH)
+                    code_list = codeList(code, depth);
+                else {
+                    // TODO-szh 错误提示
+                    return nullptr;
+                }
+
+                getToken();
+                switch (syntactic.token) {
+                    case TK_RP:
+                        break;
+                    case TK_ERROR:
+                        return nullptr;
+                    default:
+                        goBackToken();
+                        // TODO-szh 错误提示
+                        return nullptr;
+                }
+
+                return new Code::ByteCode(code, Code::ByteCode::block_p, code_list, reader.getFileLine(), prefix);
+            }
+            case TK_LB: {
+                Code::ByteCode *code_list;
+                if (depth <= SYNTACTIC_MAX_DEPTH)
+                    code_list = codeList(code, depth);
+                else {
+                    // TODO-szh 错误提示
+                    return nullptr;
+                }
+
+                getToken();
+                switch (syntactic.token) {
+                    case TK_RB:
+                        break;
+                    case TK_ERROR:
+                        return nullptr;
+                    default:
+                        goBackToken();
+                        // TODO-szh 错误提示
+                        return nullptr;
+                }
+
+                return new Code::ByteCode(code, Code::ByteCode::block_b, code_list, reader.getFileLine(), prefix);
+            }
+            case TK_LC: {
+                Code::ByteCode *code_list;
+                if (depth <= SYNTACTIC_MAX_DEPTH)
+                    code_list = codeList(code, depth);
+                else {
+                    // TODO-szh 错误提示
+                    return nullptr;
+                }
+
+                getToken();
+                switch (syntactic.token) {
+                    case TK_RC:
+                        break;
+                    case TK_ERROR:
+                        return nullptr;
+                    default:
+                        goBackToken();
+                        // TODO-szh 错误提示
+                        return nullptr;
+                }
+
+                return new Code::ByteCode(code, Code::ByteCode::block_c, code_list, reader.getFileLine(), prefix);
+            }
+            case TK_ERROR:
+                return nullptr;
+            default:
+                // TODO-szh 错误提示
+                return nullptr;
+        }
+    }
+
+    Code::ByteCode *Parser::codePrefix(Code &code, size_t depth) {  // NOLINT
+        char ch = aFuntool::NUL;
+        getToken();
+        if (syntactic.token != TK_PREFIX) {
+            goBackToken();
+            // TODO-szh 错误提示
+        } else if (syntactic.text.size() != 1)
+            NULL;  // TODO-szh 错误提示
+        else
+            ch = syntactic.text[0];
+        return codeSelf(code, depth, ch);
+    }
+
+    Code::ByteCode *Parser::codeList(Code &code, size_t depth) {  // NOLINT
+        Code::ByteCode *re = nullptr;
+        Code::ByteCode *new_re = nullptr;
+        Code::ByteCode *code_list;
+
+        while (true) {
+            getToken();
+            switch (syntactic.token) {
+                case TK_PREFIX:
+                    goBackToken();
+                    code_list = codePrefix(code, depth);
+                    if (code_list != nullptr) {
+                        if (new_re == nullptr) {
+                            re = code_list;
+                            new_re = re->connect(nullptr);
+                        } else
+                            new_re = new_re->connect(code_list);
+                    }
+                    break;
+                case TK_ELEMENT_SHORT:
+                case TK_ELEMENT_LONG:
+                case TK_LP:
+                case TK_LB:
+                case TK_LC:
+                    goBackToken();
+                    code_list = codeSelf(code, depth, aFuntool::NUL);
+                    if (code_list != nullptr) {
+                        if (new_re == nullptr) {
+                            re = code_list;
+                            new_re = re->connect(nullptr);
+                        } else
+                            new_re = new_re->connect(code_list);
+                    }
+                    break;
+                case TK_ERROR:
+                    return re;
+                default: /* 结束 */
+                    goBackToken();
+                    return re;
+            }
+        }
+    }
+
+    Code::ByteCode *Parser::codeListEnd(Code &code) {
+        getToken();
+        switch (syntactic.token) {
+            case TK_EOF:
+            case TK_ERROR:
+                return nullptr;  // 结束
+            case TK_PREFIX:
+            case TK_ELEMENT_SHORT:
+            case TK_ELEMENT_LONG:
+            case TK_LP:
+            case TK_LB:
+            case TK_LC: {
+                goBackToken();
+                Code::ByteCode *re = codeList(code, 0);
+                getToken();
+                if (syntactic.token != TK_EOF && syntactic.token != TK_ERROR)
+                    NULL; // TODO-szh 错误提示
+                return re;
+            }
+            default:
+                // TODO-szh 错误提示
+                return nullptr;
+        }
+    }
+
+    bool Parser::parserCode(Code &code) {
+        Code::ByteCode *bytecode = codeListEnd(code);
+        code.getByteCode()->connect(bytecode);
+        
+        if (syntactic.is_error || reader.isError() || lexical.is_error)
+            return false;
+        return true;
+    }
+}

+ 40 - 0
test/src/core-syntactic.cpp

@@ -0,0 +1,40 @@
+#include <cstdio>
+#include "core-parser.h"
+
+const char *str = "{if true [HelloWorld (10)]}\n";
+
+class ReaderString : public aFuncore::Reader {
+    std::string str;
+    size_t index;
+    size_t len;
+public:
+    ReaderString(std::string str_, const aFuntool::FilePath &path_) : Reader{path_, 0}, str{std::move(str_)} {
+        index = 0;
+        len = str.size();
+    }
+
+    size_t readText(char *dest, size_t read_len, ReadMode &mode) override {
+        if (index == len)  // 读取到末尾
+            return 0;
+
+        if (index + read_len > len) {  // 超出长度范围
+            read_len = len - index;
+            mode = read_mode_finished;
+        }
+
+        memcpy(dest, str.c_str() + index, read_len);
+        index += read_len;
+        return read_len;
+    }
+};
+
+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();
+    return 0;
+}