【问题标题】:Boost Semantic Actions causing parsing issues提升语义操作导致解析问题
【发布时间】:2015-11-02 17:11:00
【问题描述】:

我一直在使用 Boost 迷你编译器示例。这里是源码的根:http://www.boost.org/doc/libs/1_59_0/libs/spirit/example/qi/compiler_tutorial/mini_c/

我感兴趣的sn-p在statement_def.hpp

我遇到的问题是,如果您附加语义操作,例如这样,

statement_ =
                variable_declaration[print_this_declaration]
            |   assignment
            |   compound_statement
            |   if_statement
            |   while_statement
            |   return_statement
            ;

随后在示例程序上运行mini_c 编译器,例如:

int foo(n) {
    if (n == 3) { }
    return a;
}

int main() {
    return foo(10);
}

它会触发“compile.cpp”文件中的“重复函数错误”(使用上面的链接找到)。这是用于快速参考的 sn-p:

    if (functions.find(x.function_name.name) != functions.end())
    {
        error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
        return false;
    }

对于我的一生,我不知道为什么。

我不太确定如何描述这个问题,但似乎以某种方式发送到标准输出的任何内容都被解析器作为有效代码进行解析(但在这种情况下这似乎是不可能的)。

另一种可能性是语义操作以某种方式将外部数据绑定到符号表,在那里它再次被认为是最初解析的输入文件的一部分(当它不应该是时)。

最后一个也是可能的选择是,我可能不完全理解这个例子的细节(或者 Boost),并且指针/引用/迭代器在它应该被转移到另一个内存位置的地方' t(作为 SA 的结果),使整个迷你编译器陷入混乱。

【问题讨论】:

  • boost 标记您的问题相当于ping @sehe。
  • 开始研究这个:livecoding.tv/sehe
  • 哦,快。我会在 5 分钟后回到家立即登录。
  • 什么是print_this_declaration?我暂时不做任何操作,但是……看起来它可能是相关的
  • 类似 "void print_this_declaration { std::cout

标签: c++ templates boost header boost-spirit-qi


【解决方案1】:

[...] 似乎以某种方式发送到标准输出的任何内容都被解析器作为有效代码进行解析

看起来不太可能……确实如此 :) 没有魔法发生。

另一种可能性是语义操作以某种方式将外部数据绑定到符号表,它再次被认为是最初解析的输入文件的一部分(当它不应该是)。

其实你离这里并不远。不过,它并不是那么多的“外部”数据。它将未初始化数据绑定到符号表。它实际上会尝试这样做两次。

一步一步:

  1. 默认情况下,具有语义操作的 Qi 规则不会进行自动属性传播。 假设语义动作将负责为暴露的属性分配一个值。

    这是根本原因。见documentation: Rule/Expression Semantics

    还有:How Do Rules Propagate Attributes

  2. 因此,statement_ 规则暴露的实际属性将是ast::statement 类型的默认构造对象:

    qi::rule<Iterator, ast::statement(), skipper<Iterator> > statement_;
    
  3. 这个类型ast::statement是一个变体,一个默认构造的变体持有一个默认构造的第一个元素类型的对象:

    typedef boost::variant<
            variable_declaration
        , assignment
        , boost::recursive_wrapper<if_statement>
        , boost::recursive_wrapper<while_statement>
        , boost::recursive_wrapper<return_statement>
        , boost::recursive_wrapper<statement_list>
        >
    statement;
    
  4. 你瞧,那个对象的类型是variable_declaration

    struct variable_declaration {
        identifier lhs;
        boost::optional<expression> rhs;
    };
    

    因此,每次statement_ 规则匹配时,AST 将被解释为“声明一个具有 identifier 名称 "" 的变量”。 (不用说,初始化器 (rhs) 也是空的)。

    第二次遇到此声明违反了“符号表”中不能存在重复名称的规则。

如何解决?

即使在存在语义操作的情况下,您也可以明确指出您想要自动属性传播。

使用operator%= 而不是operator= 来_assign 规则定义:

    statement_ %=
            variable_declaration [print_this_declaration]
        |   assignment
        |   compound_statement
        |   if_statement
        |   while_statement
        |   return_statement
        ;

现在,一切都会恢复正常。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-09-06
  • 1970-01-01
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 2014-06-25
  • 1970-01-01
相关资源
最近更新 更多