c++ - 难以解析后面的评论;在一条线上

标签 c++ parsing

我正在解析一个包含函数定义的文件。由于函数可能写成多行,我一直在解析直到遇到 ;:

#include <iostream>
#include <string>

void removeLineBreaks(std::string &str)
{
    auto pos = str.find('\n');
    while (pos != std::string::npos)
    {
        str.replace(pos, 1, "");
        pos = str.find('\n', pos);
    }
}

int main()
{
    std::ifstream ifStream("a.pr");
    std::string sLine;
    const char sDelim(';');

    while (std::getline(ifStream, sLine, sDelim))
    {
        sLine += sDelim;
        removeLineBreaks(sLine);
        // process further
    }
}

文本可以是这样的:

a=f(b,c); // comment
d=f(e,f);

因为我一直读到 ;,这里我得到两部分:

a=f(b,c);

//注释 \n d=f(e,f);.

如果我在第二部分调用 removeLineBreaks,它会变成 //comment d=f(e,f); 所以它会被视为注释通过我的解析器。

我需要哪些选项才能使其正常工作?我能想到的是——在调用removeLineBreaks之前,获取字符串直到\n,如果以//开头,则截断该部分从行中删除,然后才调用 removeLineBreaks

还有其他想法吗?

最佳答案

您首先需要从输入中删除 // 注释,然后才能在分号处拆分。

考虑以下输入:

a=f(b,c); // Functions comments are not functions; a=F(b,c);

如果您首先拆分分号,然后删除注释,那么您将得到两个函数:

a=f(b,c);
a=F(b,c);

但你只想拥有第一个。

解决方案是:

  1. 逐行读取文件(行由 LF 分隔)。
  2. 同时删除基于行的 // 注释以及所有换行符。
  3. 将所有输入组合回一个字符串。
  4. 用分号分隔字符串以提取注释之外的所有函数。

这些步骤不必按顺序进行。您可以对输入的字符流同时执行所有这些步骤,最后发出函数流。事实上,这就是真正的解析器会做的事情。

您实际上是在编写一个简单的解析器。随着您的语言变得越来越复杂,您会发现以这种方式解析文件越来越困难。例如,使用上述方法将很难发出带有行号信息的错误消息。

如果您想编写一个合适的解析器,我会推荐一个递归下降 解析器和一个 PEG(解析器表达式语法)。这种方法很容易学习,比其他方法有更少的缺陷,而且对于计算机语言来说非常强大。看这里:https://en.wikipedia.org/wiki/Parsing_expression_grammar

警告:如果您听到有人建议使用 flexbison(或 lex 和 yacc),我强烈建议您不要使用它们。它们使用起来很复杂,并且在它们可以解析的内容以及需要指定的方式方面非常有限。我宁愿建议使用像 PEGTL 这样的轻量级现代解析框架:https://github.com/taocpp/PEGTL .

关于c++ - 难以解析后面的评论;在一条线上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54522371/

相关文章:

iphone - iOS 中的原生 JSON 支持?

java - 在 Java 应用程序服务器上缓存 CSV 文件

使用 CodeSynthesis XSD 树映射的 C++ 类型

c++ - VS2013 c++ 连接 mysql --- Libmysql.dll 中的错误

c++ - 在 openssl 中为 pkcs7 选择摘要和加密算法

c++ - 如何让 C++ 编译器在/usr/local/lib 中搜索库?

c++ - 将嵌套类导入命名空间 - C++

php - Jquery 解析 XML 文件

java - 我需要什么 Java 正则表达式来匹配此文本?

ruby - 在 ruby​​ 中处理大型 CSV 文件(20G)