I am using Boost::Spirit to parse some text into structs. This requires using BOOST_FUSION_ADAPT_STRUCT for parsing text and directly storing into the structure. I know that the macro takes 2 arguments: the structure name as the 1st arg and all the structure members as the 2nd argument. And I am passing just those 2. But I get a compilation error saying,
error: macro "BOOST_FUSION_ADAPT_STRUCT_FILLER_0" passed 3 arguments, but takes just 2
Here is the code snippet. Let me know if you need the entire code.
Thanks.
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
struct Dir_Entry_Pair
{
std::string dir;
std::string value1;
std::pair<std::string, std::string> keyw_value2;
};
}
BOOST_FUSION_ADAPT_STRUCT(
client::Dir_Entry_Pair,
(std::string, dir)
(std::string, value1)
(std::pair< std::string, std::string >, keyw_value2))
This is the rule I am trying to parse,
qi::rule<Iterator, Dir_Entry_Pair()> ppair = dir
>> '/'
>> entry
>> -(keyword >> entry);
Most likely the issue is std::pair<std::string,std::string>.
The problem is that there is a comma in the type, which will play havoc with the macro expansion (when using the last element of your list).
You should try wrapping the type in its own set of parentheses.
Related
According to spirit x3 attribute collapsing rule, the attribute of an anternative parser with 2
alternation having same attribute, should collapse, i.e. a: A, b: A --> (a | b): A, but the code below shows its not, is it a bug or my fault?
Here is the spirit x3 documentation of compound attribute rules https://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/spirit_x3/quick_reference/compound_attribute_rules.html
I've got a code snippet to reproduce this question
Here is the code https://wandbox.org/permlink/7MvN03yiX7ir3esE
And the original code in case the link expired
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using x3::_val;
using x3::_attr;
using x3::_where;
using fusion::at_c;
auto const string_def = x3::lexeme["\"" >> *(x3::symbols<char>({ {"\\\"", '"'} }) | (x3::print - '\"')) > "\""][([](auto& ctx) {
std::cout << typeid(_attr(ctx)).name();
//should _attr(ctx) be a vector<char>, according to attribute collapsing rule?
})];
int main() {
std::string input = R"__("hello\"world")__";
x3::parse(input.begin(), input.end(), string_def);
}
Bascally, the code parse a string literal, which contains a number of chars (*), which is either a character except '"' (x3::print-'"'), or a escape sequence "\\\"" representing the character '"' (x3::symbol<char>...), both of them has a attribute of char, and char | char should be char, not variant<char, char>.
the cout part of the code shows result like St6vectorIN5boost7variantINS0_6detail7variant13over_sequenceINS0_3mpl6l_itemIN4mpl_5long_ILl2EEEcNS6_INS8_ILl1EEEcNS5_5l_endEEEEEEEJEEESaISF_EE, after demangling, it is vector<variant<over_sequence<...>>> and variant<over_sequence<> is basically a workaround of variant<T...> in pre-C++11 times.
So what's wrong with the code, should it be vector<char>, not vector<variant>? And BTW, can I customize attribute collapsing rule myself?
As #IgorR. mentioned in comment, semantic action suppresses attribute propagation, I ignored that point. So problem solved, I might need just parse this into std::string.
For some reason I need parsing this into a unique_ptr object, so I need separate the parser into a rule<StringContent, std::string> and a rule<StringLiteral, std::unique_ptr<ast::StringLiteral>, true>, problem solved
Follow-Up Question
So, I've been playing with the
Boost Mini C Tutorial
What I have done is added a rule to parse string literals. The purpose is so that I can parse and compile programs like (functionality already built-in):
int ret(int x) {
return x;
}
int main() {
int x = 5;
return ret(x)*2;
}
As well as (want to add this functionality),
string print(string s) {
return s;
}
int main() {
string foo = "bar";
print(foo);
return 0;
}
Whether or not the last two examples compile with say gcc, is inconsequential.
So, the gist of what I added is the following:
Within the file expression_def.hpp (production rule 'quoted_string' has been added):
quoted_string = '"' >> *('\\' >> char_ | ~char_('"')) >> '"'; // ADDED THIS
primary_expr =
uint_
| quoted_string // ADDED THIS
| function_call
| identifier
| bool_
| '(' > expr > ')'
;
within ast.hpp, the variant type 'std:string' has been added:
typedef boost::variant<
nil
, bool
, unsigned int
, std::string // ADDED THIS
, identifier
, boost::recursive_wrapper<unary>
, boost::recursive_wrapper<function_call>
, boost::recursive_wrapper<expression>
>
operand;
Here is the rule declaration for the addition, as well as the rule it's colliding with:
qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
qi::rule<Iterator, std::string()> quoted_string; // declaring this without the skipper
// lets us avoid the lexeme[] incantation (thanks #sehe).
The problem now, is that the compiler confuses what should be an 'identifier' for a 'quoted_string' - or actually just a std::string.
My guess is, the fact that they both have a std::string signature return type is the cause of the problem, but I don't know a good workaround here. Additionally, the 'identifier' struct has a data member of type std::string that it is initialized with, so really the compiler cannot tell between the two and the variant std::string ends up being the better match.
Now, if I change std::string to char* like so:
typedef boost::variant<
nil
, bool
, unsigned int
, char* // CHANGED, YET AGAIN
, identifier
, boost::recursive_wrapper<unary>
, boost::recursive_wrapper<function_call>
, boost::recursive_wrapper<expression>
>
operand;
it will compile and work with integers, bet then I am unable to parse strings (in fact, VS will call abort()) It should be noted that because each variant needs an overload, I have something in my code along the lines of:
bool compiler::operator()(std::string const& x)
{
BOOST_ASSERT(current != 0);
current->op(op_string, x);
return true;
}
and
void function::op(int a, std::string const& b)
{
code.push_back(a);
code.push_back(b.size());
for (uintptr_t ch : b)
{
code.push_back(ch);
}
size_ += 2 + b.size();
}
These both work swimmingly when I need to parse strings (of course sacrificing the ability to handle integers).
Their integer equivalents are (and found in compiler.cpp)
bool compiler::operator()(unsigned int x)
{
BOOST_ASSERT(current != 0);
current->op(op_int, x);
return true;
}
and of course:
void function::op(int a, int b)
{
code.push_back(a);
code.push_back(b);
size_ += 2;
}
If I have to change the variant type from std::string to char*, then I have to update the overloads, and because of C legacies, it gets to look a bit ugly.
I understand this might be a bit daunting and not really appealing to comb through the source, but I assure you it really isn't. This compiler tutorial simply pushes bytecode into a vector, which by design only handles integers. I am trying to modify it to handle strings, as well, hence the additions and overloads, as well as the need for unintptr_t. Anyone familiar with the material and/or Boost will likely know exactly what they are looking at (ehem, #sehe, ehem!).
I am writing my first STL program in C++, and I am facing this issue.
This is my program :
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
int n,m;
// n : number of file extenstions
// m : number of filenames to identify
string extension, type, filename;
cin >> n >> m;
unordered_map<string,string> hashmap;
while(n--)
{
cin >> extension >> type;
hashmap.insert(make_pair<string,string>(extension,type));
}
while(m--)
{
cin >> filename;
extension = filename.substr(filename.find_last_of('.')+1);
cout << extension << endl;
}
}
My input file is :
5 6
html text/html
htm text/html
png image/png
svg image/svg+xml
txt text/plain
index.html
this.file.has.lots.of.dots.txt
nodotsatall
virus.exe
dont.let.the.png.fool.you
case.matters.TXT
I am getting error : no matching function for call to ‘make_pair(std::string&, std::string&)’ . I cannot figure out the problem.
The error is in the line
make_pair<string,string>(extension,type)
It should instead be
make_pair(extension, type)
First of all, I'd rather use make_pair(extension, type) and let the compiler to deduce the types in any case, to avoid any risks, as someone else suggested.
Anyway, I see that the details below are interesting from your point of view, thus it's worth to put them in a dedicated response, hoping they are also right.
That said, see the documentation.
As far as I understand (I'm far from being an expert) the deduced types in your case would be T&, U&, thus using the couple T, U (as <string, string>) ends in a function prototype that doesn't accept references as arguments (that's why you got the error and that one specifically).
You can use instead the following pattern in your case:
make_pair<string&,string&>(extension,type)
This one works for you actually use references to initialize the pair and you are going to require the sames as template arguments.
Again, for the make_pair can easily deduce the types of its arguments, you can freely omit them and I strongly suggest to do that.
Basicly I have a text file which i need t read-in the values so the program can manipulate them.
Im using C++ and i have written working code to tell if the file exists or not.
The text file is formatted like this:
1 7
8 10
20 6
3 14
...
The values on the left are X values and the values on the right are Y values. (The space in the middle is a tab)
How do I extract this data? say to pass them into a class like this...
myVector(X,Y);
Also, I guess before I can use it in a class I have to TryParse to change it from a string to int right? can C++ do this?
Thank you!
I would be writing something like this if I were you. Note, this is just prototype code, and it was not even tested.
The fundamental idea is to read twice in a line, but with different delimiters. You would read with the tab delimiter first, and then just the default line end.
You need to make sure to gracefully quit the loop when you do not have anything more to read, hence the breaks, albeit the second could be enough if your file is "correct".
You will also need to make sure to convert to the proper type that your vector class expects. I assumed here that is int, but if it is string, you do not need the conversion I have put in place.
#include <string>
#include <fstream>
using namespace std;
void yourFunction()
{
..
ifstream myfile("myfile.txt");
string xword, yword;
while (1) {
if (!getline(myfile, xword, '\t'))
break;
if (!getline(myfile, yword))
break;
myVector.push_back(stoi(xword), stoi(yword));
}
...
}
This sort of parsing could be done in one line with boost.spirit:
qi::phrase_parse(begin, end, *(qi::int_ > qi::int_ > qi::eol), qi::ascii::blank, v);
The grammar could be read as: "read one int, then one int, then one EOL (end of line) (\n or \r\n, depends on locale), as many time as possible". Between ints and EOL can be found blank characters (e.g. spaces or tabs).
Advantages: rather than std::getline loops, code is more clear/concise. spirit.qi get you more powerful control and you don't need stoi calls.
Drawbacks: build-depends (no depends) to spirit.qi, compilation time.
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace spirit = boost::spirit;
namespace qi = spirit::qi;
int main(int argc, char **argv)
{
std::ifstream in(argv[1], std::ios_base::in);
std::string storage;
in.unsetf(std::ios::skipws);
spirit::istream_iterator begin(in), end;
std::vector<std::pair<int, int> > v;
qi::phrase_parse(begin, end, *(qi::int_ > qi::int_ > qi::eol), qi::ascii::blank, v);
for(const auto& p : v)
std::cout << p.first << "," << p.second << std::endl;
return 0;
}
in this article about boost spirit semantic actions it is mentioned that
There are actually 2 more arguments
being passed: the parser context and a
reference to a boolean ‘hit’
parameter. The parser context is
meaningful only if the semantic action
is attached somewhere to the right
hand side of a rule. We will see more
information about this shortly. The
boolean value can be set to false
inside the semantic action invalidates
the match in retrospective, making the
parser fail.
All fine, but i've been trying to find an example passing a function object as semantic action that uses the other parameters (parser context and hit boolean) but i haven't found any. I would love to see an example using regular functions or function objects, as i barely can grok the phoenix voodoo
This a really good question (and also a can of worms) because it gets at the interface of qi and phoenix. I haven't seen an example either, so I'll extend the article a little in this direction.
As you say, functions for semantic actions can take up to three parameters
Matched attribute - covered in the article
Context - contains the qi-phoenix interface
Match flag - manipulate the match state
Match flag
As the article states, the second parameter is not meaningful unless the expression is part of a rule, so lets start with the third. A placeholder for the second parameter is still needed though and for this use boost::fusion::unused_type. So a modified function from the article to use the third parameter is:
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
void f(int attribute, const boost::fusion::unused_type& it, bool& mFlag){
//output parameters
std::cout << "matched integer: '" << attribute << "'" << std::endl
<< "match flag: " << mFlag << std::endl;
//fiddle with match flag
mFlag = false;
}
namespace qi = boost::spirit::qi;
int main(void){
std::string input("1234 6543");
std::string::const_iterator begin = input.begin(), end = input.end();
bool returnVal = qi::phrase_parse(begin, end, qi::int_[f], qi::space);
std::cout << "return: " << returnVal << std::endl;
return 0;
}
which outputs:
matched integer: '1234'
match flag: 1
return: 0
All this example does is switch the match to a non-match, which is reflected in the parser output. According to hkaiser, in boost 1.44 and up setting the match flag to false will cause the match to fail in the normal way. If alternatives are defined, the parser will backtrack and attempt to match them as one would expect. However, in boost<=1.43 a Spirit bug prevents backtracking, which causes strange behavior. To see this, add phoenix include boost/spirit/include/phoenix.hpp and change the expression to
qi::int_[f] | qi::digit[std::cout << qi::_1 << "\n"]
You'd expect that, when the qi::int parser fails, the alternative qi::digit to match the beginning of the input at "1", but the output is:
matched integer: '1234'
match flag: 1
6
return: 1
The 6 is the first digit of the second int in the input which indicates the alternative is taken using the skipper and without backtracking. Notice also that the match is considered succesful, based on the alternative.
Once boost 1.44 is out, the match flag will be useful for applying match criteria that might be otherwise difficult to express in a parser sequence. Note that the match flag can be manipulated in phoenix expressions using the _pass placeholder.
Context parameter
The more interesting parameter is the second one, which contains the qi-phoenix interface, or in qi parlance, the context of the semantic action. To illustrate this, first examine a rule:
rule<Iterator, Attribute(Arg1,Arg2,...), qi::locals<Loc1,Loc2,...>, Skipper>
The context parameter embodies the Attribute, Arg1, ... ArgN, and qi::locals template paramters, wrapped in a boost::spirit::context template type. This attribute differs from the function parameter: the function parameter attribute is the parsed value, while this attribute is the value of the rule itself. A semantic action must map the former to the latter. Here's an example of a possible context type (phoenix expression equivalents indicated):
using namespace boost;
spirit::context< //context template
fusion::cons<
int&, //return int attribute (phoenix: _val)
fusion::cons<
char&, //char argument1 (phoenix: _r1)
fusion::cons<
float&, //float argument2 (phoenix: _r2)
fusion::nil //end of cons list
>,
>,
>,
fusion::vector2< //locals container
char, //char local (phoenix: _a)
unsigned int //unsigned int local (phoenix: _b)
>
>
Note the return attribute and argument list take the form of a lisp-style list (a cons list). To access these variables within a function, access the attribute or locals members of the context struct template with fusion::at<>(). For example, for a context variable con
//assign return attribute
fusion::at_c<0>(con.attributes) = 1;
//get the second rule argument
float arg2 = fusion::at_c<2>(con.attributes);
//assign the first local
fusion::at_c<1>(con.locals) = 42;
To modify the article example to use the second argument, change the function definition and phrase_parse calls:
...
typedef
boost::spirit::context<
boost::fusion::cons<int&, boost::fusion::nil>,
boost::fusion::vector0<>
> f_context;
void f(int attribute, const f_context& con, bool& mFlag){
std::cout << "matched integer: '" << attribute << "'" << std::endl
<< "match flag: " << mFlag << std::endl;
//assign output attribute from parsed value
boost::fusion::at_c<0>(con.attributes) = attribute;
}
...
int matchedInt;
qi::rule<std::string::const_iterator,int(void),ascii::space_type>
intRule = qi::int_[f];
qi::phrase_parse(begin, end, intRule, ascii::space, matchedInt);
std::cout << "matched: " << matchedInt << std::endl;
....
This is a very simple example that just maps the parsed value to the output attribute value, but extensions should be fairly apparent. Just make the context struct template parameters match the rule output, input, and local types. Note that this type of a direct match between parsed type/value to output type/value can be done automatically using auto rules, with a %= instead of a = when defining the rule:
qi::rule<std::string::const_iterator,int(void),ascii::space_type>
intRule %= qi::int_;
IMHO, writing a function for each action would be rather tedious, compared to the brief and readable phoenix expression equivalents. I sympathize with the voodoo viewpoint, but once you work with phoenix for a little while, the semantics and syntax aren't terribly difficult.
Edit: Accessing rule context w/ Phoenix
The context variable is only defined when the parser is part of a rule. Think of a parser as being any expression that consumes input, where a rule translates the parser values (qi::_1) into a rule value (qi::_val). The difference is often non-trivial, for example when qi::val has a Class type that needs to be constructed from POD parsed values. Below is a simple example.
Let's say part of our input is a sequence of three CSV integers (x1, x2, x3), and we only care out an arithmetic function of these three integers (f = x0 + (x1+x2)*x3 ), where x0 is a value obtained elsewhere. One option is to read in the integers and calculate the function, or alternatively use phoenix to do both.
For this example, use one rule with an output attribute (the function value), and input (x0), and a local (to pass information between individual parsers with the rule). Here's the full example.
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
#include <iostream>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
int main(void){
std::string input("1234, 6543, 42");
std::string::const_iterator begin = input.begin(), end = input.end();
qi::rule<
std::string::const_iterator,
int(int), //output (_val) and input (_r1)
qi::locals<int>, //local int (_a)
ascii::space_type
>
intRule =
qi::int_[qi::_a = qi::_1] //local = x1
>> ","
>> qi::int_[qi::_a += qi::_1] //local = x1 + x2
>> ","
>> qi::int_
[
qi::_val = qi::_a*qi::_1 + qi::_r1 //output = local*x3 + x0
];
int ruleValue, x0 = 10;
qi::phrase_parse(begin, end, intRule(x0), ascii::space, ruleValue);
std::cout << "rule value: " << ruleValue << std::endl;
return 0;
}
Alternatively, all the ints could be parsed as a vector, and the function evaluated with a single semantic action (the % below is the list operator and elements of the vector are accessed with phoenix::at):
namespace ph = boost::phoenix;
...
qi::rule<
std::string::const_iterator,
int(int),
ascii::space_type
>
intRule =
(qi::int_ % ",")
[
qi::_val = (ph::at(qi::_1,0) + ph::at(qi::_1,1))
* ph::at(qi::_1,2) + qi::_r1
];
....
For the above, if the input is incorrect (two ints instead of three), bad thing could happen at run time, so it would be better to specify the number of parsed values explicitly, so parsing will fail for a bad input. The below uses _1, _2, and _3 to reference the first, second, and third match value:
(qi::int_ >> "," >> qi::int_ >> "," >> qi::int_)
[
qi::_val = (qi::_1 + qi::_2) * qi::_3 + qi::_r1
];
This is a contrived example, but should give you the idea. I've found phoenix semantic actions really helpful in constructing complex objects directly from input; this is possible because you can call constructors and member functions within semantic actions.