使用 boost::regex 解析包含枚举的 *.cpp 文件。
Parsing *.cpp file containing enum using boost::regex.
我已经解析文件并将内容拆分为枚举或枚举 类。
std::string sourceString = readFromFile(typesHDestination);
boost::smatch xResults;
std::string::const_iterator Start = sourceString.cbegin();
std::string::const_iterator End = sourceString.cend();
while (boost::regex_search(Start, End, xResults, boost::regex("(?<data_type>enum|enum\s+class)\s+(?<enum_name>\w+)\s*\{(?<content>[^\}]+?)\s*\}\s*")))
{
std::cout << xResults["data_type"]
<< " " << xResults["enum_name"] << "\n{\n";
std::string::const_iterator ContentStart = xResults["content"].begin();
std::string::const_iterator ContentEnd = xResults["content"].end();
boost::smatch xResultsInner;
while (boost::regex_search(ContentStart, ContentEnd, xResultsInner, boost::regex("(?<name>\w+)(?:(?:\s*=\s*(?<value>[^\,\s]+)(?:(?:,)|(?:\s*)))|(?:(?:\s*)|(?:,)))")))
{
std::cout << xResultsInner["name"] << ": " << xResultsInner["value"] << std::endl;
ContentStart = xResultsInner[0].second;
}
Start = xResults[0].second;
std::cout << "}\n";
}
枚举没有注释也没关系。
我尝试添加命名组 <comment>
以在枚举中保存评论,但每次都失败了。 (\/{2}\s*.+)
- 双斜杠注释示例。
我使用 online regex 和 boost::regex.
进行了测试
- 第一步——从*.cpp文件到
<data_type> <enum_name> <content>
正则表达式:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
- 从
<content>
到 <name> <value> <comment>
正则表达式:
(?'name'\w+)(?:(?:\s*=\s*(?'value'[^\,\s/]+)(?:(?:,)|(?:\s*)))|(?:(?:\s*)|(?:,)))
最后一个有错误。有什么方法可以修复它并添加功能以在群组中存储评论吗?
正如一些评论所说,用 正则表达式 解析源文件可能不是一个好主意,除了一些简单的情况
例如这个源文件,来自:http://en.cppreference.com/w/cpp/language/enum
#include <iostream>
// enum that takes 16 bits
enum smallenum: int16_t
{
a,
b,
c
};
// color may be red (value 0), yellow (value 1), green (value 20), or blue (value 21)
enum color
{
red,
yellow,
green = 20,
blue
};
// altitude may be altitude::high or altitude::low
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
// the constant d is 0, the constant e is 1, the constant f is 3
enum
{
d,
e,
f = e + 2
};
//enumeration types (both scoped and unscoped) can have overloaded operators
std::ostream& operator<<(std::ostream& os, color c)
{
switch(c)
{
case red : os << "red"; break;
case yellow: os << "yellow"; break;
case green : os << "green"; break;
case blue : os << "blue"; break;
default : os.setstate(std::ios_base::failbit);
}
return os;
}
std::ostream& operator<<(std::ostream& os, altitude al)
{
return os << static_cast<char>(al);
}
int main()
{
color col = red;
altitude a;
a = altitude::low;
std::cout << "col = " << col << '\n'
<< "a = " << a << '\n'
<< "f = " << f << '\n';
}
这里的关键模式是:从enum
开始到;
结束,你无法预测enum
和[之间的任何文本=15=] 会有很多的可能!为此,您可以使用 .*?
lazy star
因此,如果我想提取所有 enums
我使用:
注意:这不是有效的方法
boost::regex rx( "^\s*(enum.*?;)" );
boost::match_results< std::string::const_iterator > mr; // or boost::smatch
std::ifstream ifs( "file.cpp" );
const uintmax_t file_size = ifs.seekg( 0, std::ios_base::end ).tellg();
ifs.seekg( 0, std::ios_base::beg ); // rewind
std::string whole_file( file_size, ' ' );
ifs.read( &*whole_file.begin(), file_size );
ifs.close();
while( boost::regex_search( whole_file, mr, rx ) ){
std::cout << mr.str( 1 ) << '\n';
whole_file = mr.suffix().str();
}
输出将是:
enum smallenum: int16_t
{
a,
b,
c
};
enum color
{
red,
yellow,
green = 20,
blue
};
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
enum
{
d,
e,
f = e + 2
};
当然,对于这种简单的事情,我更喜欢使用:
perl -lne '$/=unlef;print while/^\s*(enum.*?;)/smg' file.cpp
具有相同的输出。
如果您想分别匹配每个部分,此模式可能会对您有所帮助
^\s*(enum[^{]*)\s*({)\s*([^}]+)\s*(};)
But again this is not a good idea except for some simple source files. Since C++ Source Code has free style and not all code writers follow the standard rules. For example with the pattern above, I assumed that (};)
the }
comes with ;
and if someone separates them ( which is still a valid code ) the pattern will be failed to match.
我同意使用正则表达式解析复杂数据并不是最佳解决方案这一事实。我省略了几个主要条件。首先,我解析了某种包含 emuns 和枚举 类 的生成源代码。所以代码中没有惊喜,而且代码是有规律的。所以我用正则表达式解析常规代码。
答案:
(第一步是一样的,第二步是固定的)
如何使用正则表达式解析 enums/emun 类:
- 第一步-从*.cpp文件到
<data_type> <enum_name> <content>
正则表达式:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
- 从
<content>
到 <name> <value> <comment>
正则表达式:
^\s*(?'name'\w+)(?:(?:\s*=\s*(?'value'[^,\n/]+))|(?:[^,\s/]))(?:(?:\s$)|(?:\s*,\s*$)|(?:[^/]/{2}\s(?'comment'.*$)))
所有测试都正常,这里用颜色标记了文本。
我已经解析文件并将内容拆分为枚举或枚举 类。
std::string sourceString = readFromFile(typesHDestination);
boost::smatch xResults;
std::string::const_iterator Start = sourceString.cbegin();
std::string::const_iterator End = sourceString.cend();
while (boost::regex_search(Start, End, xResults, boost::regex("(?<data_type>enum|enum\s+class)\s+(?<enum_name>\w+)\s*\{(?<content>[^\}]+?)\s*\}\s*")))
{
std::cout << xResults["data_type"]
<< " " << xResults["enum_name"] << "\n{\n";
std::string::const_iterator ContentStart = xResults["content"].begin();
std::string::const_iterator ContentEnd = xResults["content"].end();
boost::smatch xResultsInner;
while (boost::regex_search(ContentStart, ContentEnd, xResultsInner, boost::regex("(?<name>\w+)(?:(?:\s*=\s*(?<value>[^\,\s]+)(?:(?:,)|(?:\s*)))|(?:(?:\s*)|(?:,)))")))
{
std::cout << xResultsInner["name"] << ": " << xResultsInner["value"] << std::endl;
ContentStart = xResultsInner[0].second;
}
Start = xResults[0].second;
std::cout << "}\n";
}
枚举没有注释也没关系。
我尝试添加命名组 <comment>
以在枚举中保存评论,但每次都失败了。 (\/{2}\s*.+)
- 双斜杠注释示例。
我使用 online regex 和 boost::regex.
进行了测试- 第一步——从*.cpp文件到
<data_type> <enum_name> <content>
正则表达式:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
- 从
<content>
到<name> <value> <comment>
正则表达式:
(?'name'\w+)(?:(?:\s*=\s*(?'value'[^\,\s/]+)(?:(?:,)|(?:\s*)))|(?:(?:\s*)|(?:,)))
最后一个有错误。有什么方法可以修复它并添加功能以在群组中存储评论吗?
正如一些评论所说,用 正则表达式 解析源文件可能不是一个好主意,除了一些简单的情况
例如这个源文件,来自:http://en.cppreference.com/w/cpp/language/enum
#include <iostream>
// enum that takes 16 bits
enum smallenum: int16_t
{
a,
b,
c
};
// color may be red (value 0), yellow (value 1), green (value 20), or blue (value 21)
enum color
{
red,
yellow,
green = 20,
blue
};
// altitude may be altitude::high or altitude::low
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
// the constant d is 0, the constant e is 1, the constant f is 3
enum
{
d,
e,
f = e + 2
};
//enumeration types (both scoped and unscoped) can have overloaded operators
std::ostream& operator<<(std::ostream& os, color c)
{
switch(c)
{
case red : os << "red"; break;
case yellow: os << "yellow"; break;
case green : os << "green"; break;
case blue : os << "blue"; break;
default : os.setstate(std::ios_base::failbit);
}
return os;
}
std::ostream& operator<<(std::ostream& os, altitude al)
{
return os << static_cast<char>(al);
}
int main()
{
color col = red;
altitude a;
a = altitude::low;
std::cout << "col = " << col << '\n'
<< "a = " << a << '\n'
<< "f = " << f << '\n';
}
这里的关键模式是:从enum
开始到;
结束,你无法预测enum
和[之间的任何文本=15=] 会有很多的可能!为此,您可以使用 .*?
lazy star
因此,如果我想提取所有 enums
我使用:
注意:这不是有效的方法
boost::regex rx( "^\s*(enum.*?;)" );
boost::match_results< std::string::const_iterator > mr; // or boost::smatch
std::ifstream ifs( "file.cpp" );
const uintmax_t file_size = ifs.seekg( 0, std::ios_base::end ).tellg();
ifs.seekg( 0, std::ios_base::beg ); // rewind
std::string whole_file( file_size, ' ' );
ifs.read( &*whole_file.begin(), file_size );
ifs.close();
while( boost::regex_search( whole_file, mr, rx ) ){
std::cout << mr.str( 1 ) << '\n';
whole_file = mr.suffix().str();
}
输出将是:
enum smallenum: int16_t
{
a,
b,
c
};
enum color
{
red,
yellow,
green = 20,
blue
};
enum class altitude: char
{
high='h',
low='l', // C++11 allows the extra comma
};
enum
{
d,
e,
f = e + 2
};
当然,对于这种简单的事情,我更喜欢使用:
perl -lne '$/=unlef;print while/^\s*(enum.*?;)/smg' file.cpp
具有相同的输出。
如果您想分别匹配每个部分,此模式可能会对您有所帮助
^\s*(enum[^{]*)\s*({)\s*([^}]+)\s*(};)
But again this is not a good idea except for some simple source files. Since C++ Source Code has free style and not all code writers follow the standard rules. For example with the pattern above, I assumed that
(};)
the}
comes with;
and if someone separates them ( which is still a valid code ) the pattern will be failed to match.
我同意使用正则表达式解析复杂数据并不是最佳解决方案这一事实。我省略了几个主要条件。首先,我解析了某种包含 emuns 和枚举 类 的生成源代码。所以代码中没有惊喜,而且代码是有规律的。所以我用正则表达式解析常规代码。
答案: (第一步是一样的,第二步是固定的) 如何使用正则表达式解析 enums/emun 类:
- 第一步-从*.cpp文件到
<data_type> <enum_name> <content>
正则表达式:
(?'data_type'enum|enum\s+class)\s+(?'enum_name'\w+)\s*{\s*(?'content'[^}]+?)\s*}\s*
- 从
<content>
到<name> <value> <comment>
正则表达式:
^\s*(?'name'\w+)(?:(?:\s*=\s*(?'value'[^,\n/]+))|(?:[^,\s/]))(?:(?:\s$)|(?:\s*,\s*$)|(?:[^/]/{2}\s(?'comment'.*$)))
所有测试都正常,这里用颜色标记了文本。