我刚刚阅读了Boost :: Spirit LL Parser框架的介绍.前言表明作者和创作者喜欢使用这种解析技术来阅读程序选项.Boost没有自己的程序选项库吗?
我想知道,Boost委员会是否会审查所有图书馆笔记的共同主题和风格?看起来每个图书馆的文档都有自己的风格.
对于其他令人惊奇的软件的小抱怨,我发现它很好奇.
我正在使用Spirit 2.4,我想要解析这样的结构:
文字{text_field};
关键是text_field是一个带有符号'{','}'和'\'的转义字符串.我想使用qi为此创建一个解析器.我一直在尝试这个:
using boost::spirit::standard::char_;
using boost::spirit::standard::string;
using qi::lexeme;
using qi::lit;
qi::rule< IteratorT, std::string(), ascii::space_type > text;
qi::rule< IteratorT, std::string(), ascii::space_type > content;
qi::rule< IteratorT, std::string(), ascii::space_type > escChar;
text %=
lit( "Text" ) >> '{' >>
content >>
"};"
;
content %= lexeme[ +( +(char_ - ( lit( '\\' ) | '}' ) ) >> escChar ) ];
escChar %= string( "\\\\" )
| string( "\\{" )
| string( "\\}" );
Run Code Online (Sandbox Code Playgroud)
但是甚至没有编译.任何的想法?
基本上我正在做一个表达式解析器.因为我需要尽可能好的性能,并且根据语法的文档构造可能相当慢,我想在解析之前重用语法并绑定符号表.由于语法的客户端可能有一个在解析之前构造和维护的符号表,我理想地希望避免复制实际的表,这导致我转换以下代码(简化)来翻译术语:
qi::symbols< char, double >* m_Symbols;
qi::rule< Iterator, double(), ascii::space_type > m_Val;
m_Val = qi::int_[ _val = boost::phoenix::static_cast_< double >( boost::spirit::_1 ) ] | qi::double_ | m_Symbols;
Run Code Online (Sandbox Code Playgroud)
这里的问题是m_Symbols.我想要的是m_Val通过引用来保存m_Symbols,因为当我们绑定符号表时我自然会修改指针,我认为可以通过使用boost :: phoenix :: ref来解决这个问题.但更大的问题是,在合成新的解析器时,我似乎无法使用指向解析器的指针.在表达式中使用dereference立即取消引用m_Symbols,这是不需要的,我想延迟解除引用到解析时间.
我正在分析一些格式类似的科学文本
Keyword
{ 1.0 22.2 59.6 'cm' 'yes' }
Run Code Online (Sandbox Code Playgroud)
我是精神新手,在研究了文档后,我可以用精神来解决fixed-format关键字.
但是对于以下格式,我不知道如何构建语法.我的问题是:在我遇到的科学关键字中,某些数据项可以默认为内置默认值.关键字说明指示何时可以应用默认值.将数量设置为默认值有两种方法.首先,通过斜杠'}'提前结束数据记录,将未指定的数量设置为其默认值.其次,通过输入n*可以默认位于'}'之前的选定数量,其中n是要默认的连续数量的数量.例如,3*会使关键字数据中的后三个数量被赋予其默认值.
例如,
Person
{ 'Tom' 188 80 'male' 32 }
Run Code Online (Sandbox Code Playgroud)
说'男'和'32'是默认值,它的等价物可以是:
Person
{ 'Tom' 188 88 2* }
Run Code Online (Sandbox Code Playgroud)
要么
Person
{ 'Tom' 188 88 'male' 1* }
Run Code Online (Sandbox Code Playgroud)
要么
Person
{ 'Tom' 188 88 }
Run Code Online (Sandbox Code Playgroud)
我搜索过去的帖子,这给了我一些想法,但我怎么能写出n*的规则?
我正在解析一个文本文件,可能有几GB大小,由以下行组成:
11 0.1
14 0.78
532 -3.5
Run Code Online (Sandbox Code Playgroud)
基本上,每行一个int和一个float.整数应该是有序的而且是非负的.我想验证数据是否如描述,并返回给我范围内的最小和最大int.这就是我想出来的:
#include <iostream>
#include <string>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace px = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace my_parsers
{
using namespace qi;
using px::at_c;
using px::val;
template <typename Iterator>
struct verify_data : grammar<Iterator, locals<int>, std::pair<int, int>()>
{
verify_data() : verify_data::base_type(section)
{
section
= line(val(0)) [ at_c<0>(_val) = _1]
>> +line(_a) [ _a = _1]
>> eps [ at_c<1>(_val) = _a]
;
line
%= (int_ >> other) [
if_(_r1 >= _1) …Run Code Online (Sandbox Code Playgroud) 这个问题的接受答案引导我进入这个示例,但编译它会给出一个很长的错误列表.这里是示例代码,我只添加了includes和一个虚拟main():
#include <boost/spirit/include/qi.hpp>
#include <vector>
#include <map>
#include <string>
#include <iostream>
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct keys_and_values
: qi::grammar<Iterator, std::map<std::string, std::string>()>
{
keys_and_values()
: keys_and_values::base_type(query)
{
query = pair >> *((qi::lit(';') | '&') >> pair);
pair = key >> -('=' >> value);
key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
value = +qi::char_("a-zA-Z_0-9");
}
qi::rule<Iterator, std::map<std::string, std::string>()> query;
qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
qi::rule<Iterator, std::string()> key, value;
};
int main(int argc, char **argv)
{
std::string input("key1=value1;key2;key3=value3"); // input …Run Code Online (Sandbox Code Playgroud) 我正在寻找实现variadic函数的最简单方法,它采用boost :: spirit :: qi规则列表并将列表扩展为格式表达式:rule1 | rule2 | rule3 | ....让我们假设规则不合成任何属性.非常感谢您的帮助.
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::ascii::space;
using boost::spirit::iso8859_1::char_;
typedef qi::rule<std::string::const_iterator,ascii::space_type> mrule_t;
typedef qi::rule< std::string::const_iterator,std::string() > wrule_t;
Run Code Online (Sandbox Code Playgroud)
//How to deduce expandBitwise() return type ?
template<typename T>
T expandBitwise(T& t)
{
return t.rule_;
}
template<typename T,typename ...Tail>
T expandBitwise(T& t,Tail& ...tail)
{
return t.rule_ | expandBitwise(tail...);
}
struct TStruct
{
mrule_t …Run Code Online (Sandbox Code Playgroud) 我已经看过一些与qi语法中关键字/标识符使用细微差别相关的帖子,但是我无法理解在boost示例中演示的方法应该如何工作......
关键词声明:
qi::symbols<char> keywords;
Run Code Online (Sandbox Code Playgroud)
示例关键字集:
keywords.add
("foo")
("bar")
;
Run Code Online (Sandbox Code Playgroud)
标识符规则声明:
qi::rule<std::string::const_iterator, std::string(), ascii::space_type> identifier;
Run Code Online (Sandbox Code Playgroud)
以下是qi calc和编译器示例中定义标识符规则的方法:
identifier = !keywords >> qi::raw[ qi::lexeme[ ( qi::alpha | '_' ) >> *( qi::alnum | '_' ) ] ];
Run Code Online (Sandbox Code Playgroud)
也许我正在阅读qi语法错误,但在我看来,这不会接受任何匹配或以关键字开头的文字.拒绝完整关键字匹配是所需的行为.但是,我想接受"食物"作为标识符,即使它以关键字"foo"开头.这似乎是一个非常标准的用例,但无法找到真正指出这一点的文档.
任何人都可以提供仅拒绝与关键字完全匹配的标识符规则吗?
谢谢!
我无法使用Boost :: Spirit编写我认为应该是简单解析器的内容.(我使用的是Spirit而不仅仅是使用字符串函数,因为这对我来说是一个学习练习).
要解析的数据采用键值对的形式,其中值本身可以是键值对.键是字母数字(带下划线,没有数字作为第一个字符); 值是字母数字加.-_- 值可以是格式的日期,DD-MMM-YYYY例如01-Jan-2015浮点数,例如3.1415普通的旧字母数字字符串.键和值分开=; 对分开;; 结构化值用{... 分隔}.目前我正在从用户输入中删除所有空格,然后将其传递给Spirit.
输入示例:
Key1 = Value1; Key2 = { NestedKey1=Alan; NestedKey2 = 43.1232; }; Key3 = 15-Jul-1974 ;
然后我会删除所有空格
Key1=Value1;Key2={NestedKey1=Alan;NestedKey2=43.1232;};Key3=15-Jul-1974;
然后我实际将它传递给Spirit.
当价值只是价值时,我现在所拥有的只是花花公子.当我开始在输入中编码结构化值时,Spirit会在第一个结构化值之后停止.如果只有一个结构化值,则解决方法是将其放在输入的末尾...但有时我需要两个或更多结构化值.
以下编译VS2013并说明错误:
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/pair.hpp>
#include <boost/fusion/adapted.hpp>
#include <map>
#include <string>
#include <iostream>
typedef std::map<std::string, std::string> ARGTYPE;
#define BOOST_SPIRIT_DEBUG
namespace qi = boost::spirit::qi;
namespace fusion = boost::fusion;
template < typename It, typename …Run Code Online (Sandbox Code Playgroud) 我需要解析一个相当简单的基于堆栈的语言,例如
1 2 add
3 1 sub
Run Code Online (Sandbox Code Playgroud)
我在这里面临两个选择:
我从来没有使用过提升精神,但从我所读到的内容(文档和示例)我仍然无法决定是否使用提升精神来解释和解析这种简单的语言或是否会使感觉使用它而不是推出我自己的词法分析器和解析器(我认为不应该太难).
使用boost精神来实现像上面那样简单的基于堆栈的语言能够获得回报(因为我需要先学习它才能使用它)?