【发布时间】:2011-03-05 22:10:34
【问题描述】:
我正在尝试解析类似于树表达式的 C 函数,如下所示(使用 Spirit Parser Framework):
F( A() , B( GREAT( SOME , NOT ) ) , C( YES ) )
为此,我尝试在以下语法中使用三个规则:
template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {
InputGrammar() : InputGrammar::base_type( ) {
tag = ( qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") )[ push_back( at_c<0>(qi::_val) , qi::_1 ) ];
command = tag [ at_c<0>(qi::_val) = at_c<0>(qi::_1) ] >> "(" >> (*instruction >> ",")
[ push_back( at_c<1>(qi::_val) , qi::_1 ) ] >> ")";
instruction = ( command | tag ) [qi::_val = qi::_1];
}
qi::rule< Iterator , ExpressionAST() , space_type > tag;
qi::rule< Iterator , ExpressionAST() , space_type > command;
qi::rule< Iterator , ExpressionAST() , space_type > instruction;
};
请注意,我的标记规则只是试图捕获表达式中使用的标识符(“函数”名称)。另请注意,标记规则的签名返回 ExpressionAST 而不是 std::string,就像在大多数示例中一样。我想这样做的原因实际上很简单:我讨厌使用变体,如果可能的话我会避免使用它们。我想,把蛋糕留着吃也不错。
命令应该以标签(当前节点的名称,AST 节点的第一个字符串字段)和括号括起来的可变数量的参数开头,每个参数可以是标签本身或另一个命令。
但是,这个例子根本不起作用。它编译和一切,但在运行时它无法解析我所有的测试字符串。真正让我烦恼的是我不知道如何修复它,因为我无法真正调试上面的代码,至少在这个词的传统含义上是这样。基本上我看到我可以修复上述代码的唯一方法是知道我做错了什么。
所以,问题是我不知道上面的代码有什么问题。你会如何定义上面的语法?
我使用的ExpressionAST 类型是:
struct MockExpressionNode {
std::string name;
std::vector< MockExpressionNode > operands;
typedef std::vector< MockExpressionNode >::iterator iterator;
typedef std::vector< MockExpressionNode >::const_iterator const_iterator;
iterator begin() { return operands.begin(); }
const_iterator begin() const { return operands.begin(); }
iterator end() { return operands.end(); }
const_iterator end() const { return operands.end(); }
bool is_leaf() const {
return ( operands.begin() == operands.end() );
}
};
BOOST_FUSION_ADAPT_STRUCT(
MockExpressionNode,
(std::string, name)
(std::vector<MockExpressionNode>, operands)
)
【问题讨论】:
-
最近我发现 C 和 C++ 标识符的名称中可以包含“$”字符。因此 a-z、A-Z、0-9(第一个字符除外)、_ 和 $ 在 C/C++ 标识符中有效。
-
@Cthutu MSVC 允许在标识符中使用重音字符。并不意味着它符合标准。
-
更重要的是,你试图让@Cthutu 有什么意义?标识符是否短缺?您的编译器是否不正确支持命名空间?
标签: c++ parsing boost-spirit boost-spirit-qi