在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
之前正好刚用python写了一个简单的scheme解释器,出于对于python中模式匹配和字符串处理的顺手,用python做了之前的那个转换引擎。 但代码结构自己是很不满意的,但对于python的了解程度导致我动手之后可以完成功能,但实现的方式不太自然。 所有的问题最后都归结于一处,最开始的时候将字符串按照空格进行了分割,变为list,这一步其实是没有道理的,而且将字符串的很多信息给缩减了,当前也带来了一些方便,但是实在是不可取,导致对于一些上下文相关的结构必须反复的在前后挑选一个合适的时机来来回处理。 所以近来用C++重构了一下上面的引擎,比之前的看起来要结构清晰一些。
有几点体会:
首先先介绍几个辅助性的函数,前几个都是谓词函数,判断当前行是否是某个语法结构,最后的regex函数实际上是用regex来完成字符串中比较复杂的词法单元的替换: 链接、图片、上标 bool isUnorderedList(std::string &input){ if ((input[0] == '*' || input[0] == '+' || input[0] == '-') && input[1] == ' ') { return true; } else { return false; } } bool isQuote(std::string &input) { if (input[0] == '>' && input[1] == ' ') { return true; } else { return false; } } bool isOrderedList(std::string &input) { if (isdigit(input[0]) && input[1] == '.' && input[2] == ' ') { return true; } else { return false; } } bool isHerLine(std::string &input) { std::string::iterator i; for (i = input.begin(); i != input.end(); i++) { if (*i != '-') { break; } } if (i == input.end() && input.size() >= 3) { return true; } else { return false; } } codeType isCodeBlock(std::string &input){ codeType codeSym; if (input == "```python") { codeSym = codeType::PYTHON; } else if (input == "```c++") { codeSym = codeType::CPP; } else { codeSym = codeType::WRONG; } return codeSym; } // handle with link sup img std::string regex(std::string &input) { // \[*](*),link std::regex re_link("/\\[(.*)\\]\\((.*)\\)"); input=std::regex_replace(input, re_link, "<a href=\"$2\" target=\"_blank\">$1</a>"); std::regex re_sup("\\[(.*)\\]\\[(.*)\\]"); input = std::regex_replace(input, re_sup, "$1<sup>$2</sup>"); std::regex re_img("!\\[(.*)\\]\\((.*)\\)"); input = std::regex_replace(input, re_img, " <img src=\"$2\" align=\"middle\">"); return input; } 其中的codeType 定义在辅助头文件中 enum class stateBlock{ BEGIN, IN, END, }; enum class codeType { PYTHON, CPP, WRONG }; extern codeType code; 这两个enum class变量用于控制块结构和代码块结构的当前状态,解释一下,块结构是影响上下文的,如果进入块结构之后,那么词法层面的处理是不做的,并且所有的空白字符需要保留,针对代码块还需要做一些特殊的单词的着色处理。
下面是整个程序的核心部分,输入是一行的markdown文件,输出的是HTML文件 std::string parse(std::string &input) { std::string temp= input; if (input.empty()) { return ""; } if (state == stateBlock::IN) { std::regex re_blank("\\s"); std::regex re_lt("<"); temp = std::regex_replace(temp, re_blank, " "); temp = std::regex_replace(temp, re_lt, "<"); } // 块内 if (preHandle(temp) == 0) { temp = setColor(temp); temp.insert(0, "<p>"); temp+="</p>"; return temp; } currentLineOrder = false; temp = token(temp); temp = regex(temp); if (input[0] == '#'&& input[1] == ' ') { temp=handleTitle(input, 1); } else if (input[0] == '#'&& input[1] == '#' &&input[2]==' ') { temp=handleTitle(input, 2); } else if (input[0] == '#'&& input[1] == '#' &&input[2] == '#' && input[3]==' ') { temp=handleTitle(input, 3); } else if (isUnorderedList(input) ){ temp = handleUnorderedList(temp); } else if (isQuote(input)) { temp = handleQuote(temp); } else if (isOrderedList(input)) { temp = handleOrderedList(temp); } else if (isHerLine(input)) { temp = handleHerLine(); } else { temp += "</br>"; } closeOrderList(temp); return temp; } 其中每一个handle函数需要写一个单独的处理函数,其中某一些处理函数是调用某一个公共的函数,也就是根据类型进行具体的分派。
这段时间搞得比较琐碎,顺便也做了一个可视化的界面,算是放松了,接下来有空的话会把之前的scheme解释的函数应用和尾递归优化补起来。 顺便推荐一本书,《python 源码剖析》,可以对着python2.7的源码看,源码里面注释很多,还是比较好懂的,加上书中给你理清的大的框架,对理解一些数据结构的内存模型什么的有很大的帮助。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论