Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ANSIC解析器-C编译器-查找开关语句_C++_Parsing_Reverse Engineering - Fatal编程技术网

C++ ANSIC解析器-C编译器-查找开关语句

C++ ANSIC解析器-C编译器-查找开关语句,c++,parsing,reverse-engineering,C++,Parsing,Reverse Engineering,上下文 我正在写一个ANSIC代码解析器。目标是在c代码中找到有限状态机实现,并通过逆向工程创建关于现有状态和事件传输的文档 我们需要寻找c代码中有限状态机的3种常见实现:使用嵌套的switch语句(状态上的外部级别开关事件上的内部级别开关),2D结构数组,每个结构数组包含一个函数指针和下一个状态(执行转换函数后),函数指针的一维数组和状态的二维数组 主要目标是有限状态机检测 在嵌套开关语句中检测状态机,我在C++中编写了一个C解析器,从C源代码中提取所有的切换语句,并将它们存储在我的代码中存在

上下文

我正在写一个ANSIC代码解析器。目标是在c代码中找到有限状态机实现,并通过逆向工程创建关于现有状态和事件传输的文档

我们需要寻找c代码中有限状态机的3种常见实现:使用嵌套的switch语句(状态上的外部级别开关事件上的内部级别开关),2D结构数组,每个结构数组包含一个函数指针和下一个状态(执行转换函数后),函数指针的一维数组和状态的二维数组

主要目标是有限状态机检测

在嵌套开关语句中检测状态机,我在C++中编写了一个C解析器,从C源代码中提取所有的切换语句,并将它们存储在我的代码中存在的父-子-兄弟关系。 问题

问题在于我的c解析器中有一个模块,该模块假定从c源代码中提取switch语句,并将其存储在代码中存在的父子兄弟关系中

程序输出

当在89个c源代码文件的列表上运行时,我的程序可以很好地工作并提取许多switch语句,但它似乎会随机中断

debug_output.txt

该文件包含从89个c源代码文件列表中提取的每个switch语句的输出

您将看到,它从一个未知错误中断了大约一半

我的ANSI C开关语句解析器

存在具有此签名的模拟重载函数

std::istream&operator>>(std::istream&SwitchStatements&)

std::istream&operator>>(std::istream&is,SwitchStatements*ss)
{
断言(ss!=nullptr);
使用名称空间std;
is.setstate(ios::goodbit);
字符串str;
while(is>>str)
{
if(str.find(“开关”)!=string::npos){
ss->appendBuffer(str);
int括号_计数器=0;
字符c='0';
而((c=is.get())!=EOF){
ss->附加缓冲区(c);
/*错误处理*/
试一试{
如果(括号中的计数器<0)
抛出std::异常{“括号计数器不能小于0”};
如果(c=='}'&&U计数器==0)
抛出std::异常{“错误无法在打开“}之前满足关闭括号要求”;
如果(c==EOF&&U计数器!=0)
抛出std::exception{“error not meeting eof before all closing方括号”};
}
捕获(标准::异常_e){
cerr buffer.substr(这个->buffer.find_first_of('{');
ss_子项>ss_开关)
{
开关语句ss\U开关\U子级(
使_唯一(字符串{ss_switch.buffer})
);
if(!ss_switch_child.buffer.empty()||
!ss\u开关\u子项.getSibling().empty())
儿童。推回(开关儿童);
孩子们,明白了吗;
ss_switch_child.clearAll();
}
兄弟姐妹。推回(开关语句)(
使_唯一(字符串{(*).substr(偏移量)})
));
}
}

…如果你是认真的,你至少需要一个合适的C lexer。显而易见的问题是:你没有正确地跳过字符串文本和注释,它们都可能包含
开关
{
}
并且会破坏你的解析器。file.io链接似乎被破坏了。你为什么要为一个28年历史的过时版本的标准编写解析器?最好为标准C编写一个解析器。而使用状态机来解析C并不是一个好主意。@Olaf,这与使旧代码库现代化所需要做的工作相对应。make我觉得很有道理。
std::istream& operator >> (std::istream& is, SwitchStatements * ss)
{
    assert(ss != nullptr);
    using namespace std;
    is.setstate(ios::goodbit);
    string str;
    while (is >> str)
    {
        if (str.find("switch") != string::npos) {
            ss->appendBuffer(str);
            int bracket_counter = 0;
            char c = '0';
            while ((c = is.get()) != EOF) {
                ss->appendBuffer(c);
                /* error handling */
                try {
                    if (bracket_counter < 0)
                        throw std::exception{ "bracket counter cannot be less than 0" };
                    if (c == '}' && bracket_counter == 0)
                        throw std::exception{ "error cannot meet closing bracket before opening" };
                    if (c == EOF && bracket_counter != 0)
                        throw std::exception{ "error cannot meet eof before all closing brackets" };
                }
                catch (std::exception _e) {
                    cerr << "exception: ";
                    Beep(750, 1000);
                    cerr << _e.what() << endl;
                    cin.get();
                    cin.clear();
                    cin.ignore(INT_MAX, '\n');
                }
                /* end error handling */
                if (c == '{')bracket_counter++;
                if (c == '}')bracket_counter--;
                if (c == '}' && !bracket_counter) {
                    ss->setOffset(is.tellg());
                    assert(bracket_counter == 0);
                    return is;
                }
            }
        }
    }
    is.setstate(ios::badbit);
    return is;
}
SwitchStatements::SwitchStatements(std::unique_ptr<std::string> _considering)
{
    using namespace std;
    stringstream ss;
    ss << *_considering;
    ss >> this;
    if (ss.good())
    {
        stringstream ss_child;
        string buf_sub = this->buffer.substr(this->buffer.find_first_of('{'));
        ss_child << buf_sub;
        SwitchStatements ss_switch;
        while (ss_child >> ss_switch)
        {
            SwitchStatements ss_switch_child(
                make_unique<string>(string{ ss_switch.buffer })
            );
            if (!ss_switch_child.buffer.empty() || 
                !ss_switch_child.getSibling().empty())
                children.push_back(ss_switch_child);
            ss_child.clear();
            ss_switch_child.clearAll();
        }
        siblings.push_back(SwitchStatements(
            make_unique<string>(string{ (*_considering).substr(offset) })
        ));
    }
}