【发布时间】:2016-08-25 15:34:15
【问题描述】:
我正在尝试在 C++ 中标记脚本语言,目前正在努力将更多的分隔符作为标记。
#ifndef TOKENIZER_H
#define TOKENIZER_H
#include <regex>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <cctype>
using namespace std;
regex re("[\\s]+");
vector<string> deconstructDelimit(const string &input) {
string trimmed = input.substr(input.find_first_not_of(" \t\f\v\n\r"));
vector<string> decons;
sregex_token_iterator it(trimmed.begin(), trimmed.end(), re, -1);
sregex_token_iterator reg_end;
for (; it != reg_end; ++it) {
decons.push_back(it->str());
}
return decons;
}
vector<string> tokenize(const string &input) {
vector<string> whitespace;
string currToken;
for (auto it = input.begin(); it != input.end(); ++it) {
if (*it == '\'') {
if (currToken.length()) {
vector<string> decons = deconstructDelimit(currToken);
whitespace.insert(whitespace.end(), decons.begin(), decons.end());
currToken.clear();
}
whitespace.push_back("\'");
++it;
while (*it != '\'' && it != input.end()) {
currToken += *it;
++it;
}
if (currToken.length()) whitespace.push_back(currToken);
whitespace.push_back("\'");
currToken.clear();
} else if (*it == '\"') {
if (currToken.length()) {
vector<string> decons = deconstructDelimit(currToken);
whitespace.insert(whitespace.end(), decons.begin(), decons.end());
currToken.clear();
}
whitespace.push_back("\"");
++it;
while (*it != '\"' && it != input.end()) {
currToken += *it;
++it;
}
if (currToken.length()) whitespace.push_back(currToken);
whitespace.push_back("\"");
currToken.clear();
} else {
currToken += *it;
}
}
if (currToken.length()) {
vector<string> decons = deconstructDelimit(currToken);
whitespace.insert(whitespace.end(), decons.begin(), decons.end());
}
return whitespace;
}
#endif
到目前为止,它能够转换此代码:
i = 1
while(i <= 10) {
print i + " " then i++
}
到这些令牌中:
i
=
1
while(i
<=
10)
{
print
i
+
"
"
then
i++
}
但是,我想用其他分隔符分割这个字符串向量,例如运算符(++、=、
编辑:
例如,进一步标记化的结果是:
i
=
1
while(i -> while, (, i
<=
10) -> 10, )
{
print
i
+
"
"
then
i++ -> i, ++
}
展开后会是:
i
=
1
while
(
i
<=
10
)
{
print
i
+
"
"
then
i
++
}
【问题讨论】:
-
不确定正则表达式是否可行。您可能需要一个真正的解析器。您可以查看
boost::spirit::qi -
字符串拆分的问题是您需要一种方法来确定要拆分的哪里。可能您必须遍历每个字符串的内容并检测您提到的运算符并使用它们的位置将字符串分成更小的部分。
-
@JoelTrauger 那是我的恐惧。将这个词法分析步骤设为 O(n * m) 似乎对时间复杂度造成了可怕的打击,其中 n 是空格分割后的标记数,m 是要分割的符号数
-
正常的字符串拆分发生在 O(n) 时间内,其中 n 是字符串的长度。由于字符串的每个字符都与分隔符进行比较,因此您可以重载拆分函数或添加到它,以便它也正确地中断您的运算符。只是一个想法。
-
我觉得奇怪的是,您正在重写 C 中包含的字符串标记化函数
strtok()(您可以使用标头将其嵌入到 c++ 中)。看看这个xstrtok function,它是对原始函数的修改,看看它在你的字符串拆分中如何使你受益。我以前从未标记过整个文件,因此可以对其进行调整。
标签: c++ token delimiter interpreter lexer