Ver Fonte

refactor & feat: 添加ConsoleReader测试代码

SongZihuan há 3 anos atrás
pai
commit
31d274b502

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

@@ -61,6 +61,7 @@ namespace aFuncore {
                 syntactic_error_block_b_end = -6,
                 syntactic_error_block_c_end = -7,
                 syntactic_error_prefix = -8,
+                reader_error = -9,
 
                 lexical_warning_comment_end = 1,  // 注释未结束
             } EventType;

+ 6 - 4
include/runtime/rt-reader.h

@@ -1,11 +1,12 @@
 #ifndef AFUN_RT_READER_H
 #define AFUN_RT_READER_H
+#include <functional>
 #include "aFuncore.h"
 
 namespace aFunrt {
-    class ReaderString : public aFuncore::Reader {
+    class StringReader : public aFuncore::Reader {
     public:
-        inline ReaderString(std::string str_, const aFuntool::FilePath &path_);
+        inline StringReader(std::string str_, const aFuntool::FilePath &path_);
         size_t readText(char *dest, size_t read_len, ReadMode &mode) override;
     private:
         std::string str;
@@ -13,14 +14,15 @@ namespace aFunrt {
         size_t len;
     };
 
-    class ReaderFile : public aFuncore::Reader {
+    class FileReader : public aFuncore::Reader {
     public:
-        inline explicit ReaderFile(const aFuntool::FilePath &path_) noexcept(false);
+        inline explicit FileReader(const aFuntool::FilePath &path_) noexcept(false);
         size_t readText(char *dest, size_t read_len, ReadMode &mode) override;
     private:
         FILE *file;
         bool no_first;
     };
+
 }
 
 #include "rt-reader.inline.h"

+ 2 - 2
include/runtime/rt-reader.inline.h

@@ -4,13 +4,13 @@
 #include "rt-exception.h"
 
 namespace aFunrt {
-    inline ReaderString::ReaderString(std::string str_, const aFuntool::FilePath &path_)
+    inline StringReader::StringReader(std::string str_, const aFuntool::FilePath &path_)
         : Reader{path_, 0}, str{std::move(str_)} {
         index = 0;
         len = str.size();
     }
 
-    ReaderFile::ReaderFile(const aFuntool::FilePath &path_)
+    inline FileReader::FileReader(const aFuntool::FilePath &path_)
         : Reader{path_, 0} {
         file = aFuntool::fileOpen(path_, "rb");
         if (file == nullptr)

+ 1 - 1
src/core/code.cpp

@@ -375,7 +375,7 @@ RETURN_FALSE:
         if (type == code_element)
             aFuntool::cout << " element: " << data.element << "\n";
         else if (type == code_block)
-            aFuntool::cout << " block: '" << data.block_type << "' son: " << data.son << "\n";
+            aFuntool::cout << " block: '" << (char)(data.block_type) << "' son: " << data.son << "\n";
         else
             aFuntool::cout << "\n";
     }

+ 3 - 1
src/core/lexical.cpp

@@ -331,8 +331,10 @@ namespace aFuncore {
 
         while (true) {
             char ch = reader.getChar();
-            if (reader.isError())
+            if (reader.isError()) {
+                pushEvent({ParserEvent::reader_error, reader.getFileLine(), ""});
                 return TK_ERROR;
+            }
 
             if (isascii(ch) && iscntrl(ch) && !isspace(ch) && ch != aFuntool::NUL)  // ascii 控制字符
                 pushEvent({ParserEvent::lexical_error_char, reader.getFileLine(), ""});

+ 2 - 2
src/runtime/rt-reader.cpp

@@ -1,7 +1,7 @@
 #include "rt-reader.h"
 
 namespace aFunrt {
-    size_t ReaderString::readText(char *dest, size_t read_len, ReadMode &mode) {
+    size_t StringReader::readText(char *dest, size_t read_len, ReadMode &mode) {
         if (index == len)  // 读取到末尾
             return 0;
 
@@ -15,7 +15,7 @@ namespace aFunrt {
         return read_len;
     }
 
-    size_t ReaderFile::readText(char *dest, size_t read_len, aFuncore::Reader::ReadMode &mode) {
+    size_t FileReader::readText(char *dest, size_t read_len, aFuncore::Reader::ReadMode &mode) {
         if (!no_first) {
             no_first = true;
             char ch;

+ 104 - 4
test/src/core-syntactic.cpp

@@ -4,12 +4,92 @@
 const char *str = "{if true [HelloWorld (10)]}\n";
 const char *str2 = "{if true [HelloWorld (10)\n";
 
-int main() {
+class ConsoleReader : public aFuncore::Reader {
+public:
+    size_t STDIN_MAX_SIZE = 1024;
+    ConsoleReader(std::function<bool()> interrupt_, const aFuntool::FilePath &path_="console.aun");
+    size_t readText(char *dest, size_t read_len, ReadMode &mode) override;
+private:
+    char *data;
+    size_t index;
+    size_t len;
+    bool no_first;
+    std::function<bool()> interrupt;  // 中断函数
+};
+
+inline ConsoleReader::ConsoleReader(std::function<bool()> interrupt_, const aFuntool::FilePath &path_)
+    : Reader{path_, 0}, interrupt{std::move(interrupt_)} {
+    data = nullptr;
+    index = 0;
+    len = 0;
+    no_first = false;
+}
+
+
+size_t ConsoleReader::readText(char *dest, size_t read_len, aFuncore::Reader::ReadMode &mode) {
+    if (index == len) {  // 读取内容
+        if (aFuntool::clear_stdin()) {
+            mode = read_mode_error;
+            return 0;
+        }
+
+        if (no_first)
+            aFuntool::cout << "\r.... ";
+        else {
+            aFuntool::clear_stdin();
+            aFuntool::cout <<  "\r>>>> ";
+        }
+
+        fflush(stdout);
+        no_first = true;
+        aFuntool::safeFree(data);
+
+        /* 在Linux平台, 只用当数据写入stdin缓冲行时checkStdin才true */
+        /* 在Windows平台则是根据读取的最后一个字符是否为\n或者是否有按键按下来确定缓冲区是否有内容 */
+        while (!aFuntool::checkStdin()) {  // 无内容则一直循环等到
+            if (interrupt()) {  // 设置了中断函数, 并且该函数返回0
+                std::cout << "Interrupt\n";
+                mode = read_mode_error;
+                return 0;
+            }
+        }
+
+        int ch = aFuntool::fgetc_stdin();
+        if (ch == '\n' || ch == EOF) {
+            /* 读取结束 */
+            mode = read_mode_finished;
+            return 0;
+        }
+
+        aFuntool::fungetc_stdin(ch);
+
+        /* 读取内容的长度不得少于STDIN_MAX_SZIE, 否则可能导致编码转换错误 */
+        if (aFuntool::fgets_stdin(&data, (int)STDIN_MAX_SIZE) == 0) {
+            mode = read_mode_error;
+            return 0;
+        }
+
+        index = 0;
+        len = std::strlen(data);
+    }
+
+    if (index + read_len > len)  // 超出长度范围
+        read_len = len - index;
+    memcpy(dest, data + index, read_len);
+    index += read_len;
+    return read_len;
+}
+
+bool nothing() {
+    return false;
+}
+
+int main(int argc, char **) {
     std::string md5_1;
     std::string md5_2;
 
     {
-        auto reader = aFunrt::ReaderString(str, "str");
+        auto reader = aFunrt::StringReader(str, "str");
         auto parser = aFuncore::Parser(reader);
         auto code = aFuncore::Code("test.aun");
         bool ret = parser.parserCode(code);
@@ -21,7 +101,7 @@ int main() {
     }
 
     {
-        auto reader = aFunrt::ReaderString(str2, "str2");
+        auto reader = aFunrt::StringReader(str2, "str2");
         auto parser = aFuncore::Parser(reader);
         auto code = aFuncore::Code("test2.aun");
         parser.parserCode(code);
@@ -41,7 +121,7 @@ int main() {
         fprintf(file, "%s", str);
         aFuntool::fileClose(file);
 
-        auto reader = aFunrt::ReaderFile("test.aun");
+        auto reader = aFunrt::FileReader("test.aun");
         auto parser = aFuncore::Parser(reader);
         auto code = aFuncore::Code("test.aun");
         bool ret = parser.parserCode(code);
@@ -53,5 +133,25 @@ int main() {
     }
 
     std::cout << "Is md5_1 == md5_2? " << (md5_1 == md5_2) << "\n";
+
+    if (argc == 1)
+        return 0;
+
+    {
+        auto reader = ConsoleReader(nothing, "stdin.aun");
+        auto parser = aFuncore::Parser(reader);
+        auto code = aFuncore::Code("stdin.aun");
+        bool ret = parser.parserCode(code);
+
+        if (ret) {
+            code.display();
+        } else {
+            while (parser.countEvent() != 0) {
+                auto event = parser.popEvent();
+                printf("Event %d, %d\n", event.type, event.line);
+            }
+        }
+    }
+
     return 0;
 }