代码之家  ›  专栏  ›  技术社区  ›  Sam12

对结构使用%union

  •  0
  • Sam12  · 技术社区  · 6 年前

    我搜索了很多,但似乎找不到关于如何使用我的解析器文件%union的清晰示例。 例如,我想将以下令牌保存在名为classID的结构中:

    [a-zA-Z][a-zA-Z0-9]*            { yylval=new IDClass(yytext); return ID; }
    

    这是我生活中的结构 .hpp 我包括的文件夹:

    class Node {
        public:
           Node(){}
        };
    
    
        class IDClass : public Node {
        public:
            string name;
            IDClass(string name):
            Node(),name(name)
            {}
        };
    

    &然后在我的 .ypp 文件,我想使用它进行某些检查:

    Define: Type ID { if(doesIDexists(***$2->name***)){errorDef(yylineno, ID_ptr->name);exit(1);}}
    

    但很明显,2美元->name不会返回它。%union在结构中的正确用法是什么?我怎样才能正确地理解name的价值呢?

    提前谢谢你。

    0 回复  |  直到 6 年前
        1
  •  1
  •   rici    6 年前

    没有“正确使用 %union %联合会 用于声明 union (当然,你可以申报 协会 只有一名成员,但这几乎毫无意义。)

    声明非 协会 是:

    %define api.value.type { Node* }
    

    但这不会得到你想要的,因为你想要的既不是 协会 也不是固定类型,而是隐式动态转换,或类似的东西。这不是野牛的菜单上的选项。(不难看出原因。动态演员阵容不会是左值,因此野牛必须知道何时应用它,何时不应用。)

    所以你可以用上面的 %define api.value.type 然后写出语法动作:

    Define: Type ID { if (doesIDexist(dynamic_cast<IDClass>($2)->name)) {
                            errorDef(@2.first_line,
                                     dynamic_cast<IDClass>($2)->name);
                            exit(1);
                          }
                    }
    

    如果生成一个C++解析器,而不是碰巧在C++中工作的C解析器,那么您还有一些其他选项,这些选项可能对您的应用程序来说是更好的修复方法,也可能不是更好的修复方法。C解析器的选项在 Language Semantics 野牛手册的第章,以及C++选项 their own chapter ,但如果要使用C++接口,则需要阅读整个C++部分。

    注意:我变了 yylineno @2.first_line 因为 yylineno 通常是不准确的; yylineno 通常是与先行标记关联的行号,它通常与错误不在同一行。但你不能只是做出改变;你还必须确保你的lexer填写 yylloc 正确地看到了吗 Tracking Locations 《野牛手册》中的章节。