【问题标题】:How to test if a string is a valid C++(ish) expression?如何测试字符串是否是有效的 C++(ish) 表达式?
【发布时间】:2017-05-23 09:12:30
【问题描述】:

我正在用 C++ 编写一个程序,它需要能够测试一个字符串(可能是std::string)是否是一个有效的 C++ 表达式。可以检查变量是否已声明(bool variableDeclared(std::string identifier)),也可以检查其类型(std::string variableType(std::string identifier))。 variableType 函数根据在 C++ 中的声明方式("bool""double""char" 等)返回一个字符串。

表达式不需要计算,只需要测试它是否有效。该函数只需要支持字符文字、字符串文字、数字文字、括号、简单运算符(+-*/!(逻辑不)、&&、@987654334 @、><==) 以及 doublestd::string(不需要函数调用)、boolchar 类型的变量。也不需要支持字符串连接。

所需的结果将是一个类似于bool validExpression(std::string expression) 的函数。最好它允许我修改操作(例如我可以将"==" 更改为"equal-to")。

我将如何实现这一点?是否有一个库可以做这样的事情,一个正则表达式语句,还是只是一个包含大量 if 语句的长函数?

【问题讨论】:

  • 编译它。如果它编译,那么 也许 它是有效的代码。这个练习的目的是什么?您是否正在尝试编写脚本语言?这可能是一条漫长而丑陋的道路,但也很有趣。请记住,除非您绝对信任提供代码的人,否则编译和执行任意代码是一个非常非常糟糕的主意。
  • 如果您以前从未做过类似的事情,我建议您编写一个简单的表达式求值器来开始。允许的部分应该是整数(例如123)、括号(())、+*。那么calc("1+2*3") 应该返回 7。
  • @tadman 你确实意识到问题在于 OP 的问题比常规语言可以解决的问题更难,对吧?
  • @tadman 该页面上的第一句话:“Ragel 从常规语言编译可执行的有限状态机。”这意味着它不能做 OP 想要的。那为什么要推荐呢?
  • @tadman 不,这是我第一次听说 Ragel。但其描述的第一句话指出,它不能用于为包含可嵌套括号的语言生成解析器。如果您仅将它用作标记器(参见 Flex)并自己构建解析器,那很好。但是标记 OP 的输入是微不足道的。它需要一些工作的解析。

标签: c++ string parsing c++11 expression


【解决方案1】:

形式上,您的情况是:您有一个语法,它描述了您想要验证的表达式的语言,以及一个您想要确定它是否属于该语言的单词。这是该语言的解析器的工作。

您可以手工制作诸如递归下降 LL(1) 解析器之类的东西,或者使用工具生成解析器。这种工具的一个著名示例是Bison,用于生成 LALR(1) 解析器。维基百科有很长的parser generator list


上面使用的技术术语主要是为谷歌搜索提供入口点。

【讨论】:

  • 可能最简单的手写方式是作为一组相互递归的函数(查找递归下降)。
  • @melpomene:最简单的编写方法是使用 bison,正如这个答案所暗示的那样。它不会超过几行语法,特别是如果您不需要区分运算符。添加十几行 flex 来构建词法分析器,你就完成了。
  • @rici 好的,但野牛不是“手工”,这就是我的评论。我不同意这通常是最简单的方法:如果您以前从未编写过解析器,那么仅仅为了一个简单的语法检查器而学习两个全新的工具(bison、flex)可能是一个非常高的障碍。
【解决方案2】:

您将从或多或少正式地定义您的语言开始。 (语言是一组字符串)。定义语言的一个好方法是指定它的上下文无关文法。在散文中非正式地描述附加条件(如必须声明变量和正确类型的要求)。

下一步将为您在上一步中指定的语法构建解析器。有几种工具可以自动从语法构建解析器,从 yacc/bison 到 boost::spirit。

在构建和检查解析器之后,实施非正式指定的规则并将它们插入到您的解析器代码/数据中。

通常下一步,构建一个评估器,可能是编写一个简单解释器最简单的部分,但你说你不需要。

将您的语言描述为“就像 C++ 一样,只是去掉了某些位”可能是上述序列的初步步骤。但是,如果您能提供帮助,不建议从 C++ 开始。 C++ 是一种很难正式指定的语言,由于其复杂的声明语法,它的解析器往往相当复杂。

【讨论】:

    【解决方案3】:

    您可以将编译器作为应用程序的子进程运行。您所要做的就是正确传递参数并解析响应

    【讨论】:

    • 这 1) 相当重量级,2) 需要与 OP 的程序一起安装编译器,以及 3) 会接受 OP 不想要的东西(函数、条件运算符等)
    • 而且它不允许 OP 想要的东西(例如,将 == 更改为 equal-to)。
    • @Angew,你可以运行带有语法检查标志的编译器
    • @melpomene,您可以将定义添加为编译器参数
    • 宏名必须是有效的标识符。 ==equal-to 没有也不能重新定义。
    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 2013-06-19
    • 2011-01-13
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多