|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
Semantic actionsHello,
I'm attempting to write a some simple Spirit rules to parse a valid IP address. I want to place the (string) result of the parse into a variable, however I've been unable to do so. Why doesn't parse(...) fill the string "Ip" with the parsed text? When I run the program, Ip is always empty at the end. #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <iostream> #include <string> int main() { using namespace boost::spirit::qi; rule<std::string::const_iterator, std::string()> octet = int_[_pass = (_1 >= 0 && _1 <= 255)]; rule<std::string::const_iterator, std::string()> ip_address = octet >> '.' >> octet >> '.' >> octet >> '.' >> octet; std::string Line, Ip; std::getline(std::cin, Line); bool Result = parse(Line.begin(), Line.end(), ip_address, Ip); std::cout << Ip << std::endl; return 0; } ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Spirit-general mailing list Spirit-general@... https://lists.sourceforge.net/lists/listinfo/spirit-general |
|
|
Re: Semantic actionsOn Mon, Nov 2, 2009 at 3:25 PM, Dylan Klomparens
<dylan.klomparens@...> wrote: > Hello, > > I'm attempting to write a some simple Spirit rules to parse a valid IP > address. I want to place the (string) result of the parse into a variable, > however I've been unable to do so. Why doesn't parse(...) fill the string > "Ip" with the parsed text? When I run the program, Ip is always empty at the > end. > > #include <boost/spirit/include/qi.hpp> > #include <boost/spirit/include/phoenix_core.hpp> > #include <boost/spirit/include/phoenix_operator.hpp> > #include <iostream> > #include <string> > > int main() > { > using namespace boost::spirit::qi; > rule<std::string::const_iterator, std::string()> octet = int_[_pass = > (_1 >= 0 && _1 <= 255)]; > rule<std::string::const_iterator, std::string()> ip_address = octet >> > '.' >> octet >> '.' >> octet >> '.' >> octet; > std::string Line, Ip; > std::getline(std::cin, Line); > bool Result = parse(Line.begin(), Line.end(), ip_address, Ip); > std::cout << Ip << std::endl; > return 0; > } There are a couple of problems in this code, first: int_[_pass = (_1 >= 0 && _1 <= 255)]; Instead you should do something like this: uint_parser<unsigned char,10,1,3> uchar_; // not sure the template is correct, close if not. Then use uchar_ in place of that entire mess above as it will do the proper 0<=x<=255 checking and will be all around a lot faster to execute. Second, your int_ pass= stuff returns an integer (or if you use my uchar_ version it returns an unsigned char), and yet you are trying to return an std::string, that does not work for obvious reasons. You either need to change your return type to int/unsigned char, or you need to wrapp the int_/uchar_ with a raw (raw returns an iterator range). Third, same thing with ip_address, it returns a string, but your rule returns a tuple<std::string,std::string,std::string,std::string>. Again, wrap the whole thing in raw[]. Are you sure you want the IP return as a string directly? Do you not want it parsed into an integer like how it is often represented? You can also check the iterators you pass in, if begin==end then it parsed the whole thing successfully without you needing to return anything. ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Spirit-general mailing list Spirit-general@... https://lists.sourceforge.net/lists/listinfo/spirit-general |
|
|
Re: Semantic actions> I'm attempting to write a some simple Spirit rules to parse a valid IP
> address. I want to place the (string) result of the parse into a > variable, however I've been unable to do so. Why doesn't parse(...) > fill the string "Ip" with the parsed text? When I run the program, Ip > is always empty at the end. > > #include <boost/spirit/include/qi.hpp> > #include <boost/spirit/include/phoenix_core.hpp> > #include <boost/spirit/include/phoenix_operator.hpp> > #include <iostream> > #include <string> > > int main() > { > using namespace boost::spirit::qi; > rule<std::string::const_iterator, std::string()> octet = int_[_pass > = (_1 >= 0 && _1 <= 255)]; > rule<std::string::const_iterator, std::string()> ip_address = octet > >> '.' >> octet >> '.' >> octet >> '.' >> octet; > std::string Line, Ip; > std::getline(std::cin, Line); > bool Result = parse(Line.begin(), Line.end(), ip_address, Ip); > std::cout << Ip << std::endl; > return 0; > } Simple code, tricky answer. Your problem is that the rule definition octet = int_[_pass = (_1 >= 0 && _1 <= 255)]; doesn't 'return' any attribute value. Even more, if it returned an attribute, you would have gotten a compilation error as the rhs' attribute is int, while the octet's attribute is string. Generally, rule initialization auto-propagates the attribute value only if no semantic actions are attached to any of the rhs code. If you have semantic actions you either need to propagate your rhs attribute yourself, or you need to enforce auto-propagation by using the operator%= for the initialization of the rule: rule<std::string::const_iterator, int()> octet; octet %= int_[_pass = (_1 >= 0 && _1 <= 255)]; This would return the parsed int if the semantic action doesn't reject the integer value. But now you need to change the attribute type of your other rule as well: rule<std::string::const_iterator, std::vector<int>()> ip_address; where any other (STL-) container type holding int's would do the trick as well (such as boost::array<4, int>). HTH Regards Hartmut ------------------- Meet me at BoostCon http://boostcon.com ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Spirit-general mailing list Spirit-general@... https://lists.sourceforge.net/lists/listinfo/spirit-general |
|
|
Re: Semantic actionsHartmut and Overmind,
Thank you for the responses! Your suggestions formed a very nice solution. For anyone who might search/read this in the future, here's the final version of my code to parse an IP address: #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <iostream> #include <string> int main() { using namespace boost::spirit::qi; uint_parser<unsigned char,10,1,3> uchar_; rule<std::string::const_iterator, std::string()> ip_address = raw[uchar_ >> '.' >> uchar_ >> '.' >> uchar_ >> '.' >> uchar_]; std::string Line, Ip; std::getline(std::cin, Line); std::string::iterator It = Line.begin(); bool Result = parse(It, Line.end(), ip_address, Ip); bool Full = It == Line.end(); std::cout << "Result = " << Result << ", full parse = " << Full << ", Ip = " << Ip << std::endl; return 0; } -- Dylan
On Mon, Nov 2, 2009 at 9:14 PM, Hartmut Kaiser <hartmut.kaiser@...> wrote:
------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Spirit-general mailing list Spirit-general@... https://lists.sourceforge.net/lists/listinfo/spirit-general |
|
|
Re: Semantic actionsOn Tue, Nov 3, 2009 at 12:05 PM, Dylan Klomparens
<dylan.klomparens@...> wrote: > Hartmut and Overmind, > > Thank you for the responses! Your suggestions formed a very nice solution. > > For anyone who might search/read this in the future, here's the final > version of my code to parse an IP address: > > #include <boost/config/warning_disable.hpp> > #include <boost/spirit/include/qi.hpp> > #include <boost/spirit/include/phoenix_core.hpp> > #include <boost/spirit/include/phoenix_operator.hpp> > #include <iostream> > #include <string> > > int main() > { > using namespace boost::spirit::qi; > uint_parser<unsigned char,10,1,3> uchar_; > rule<std::string::const_iterator, std::string()> ip_address = raw[uchar_ >>> '.' >> uchar_ >> '.' >> uchar_ >> '.' >> uchar_]; > std::string Line, Ip; > std::getline(std::cin, Line); > std::string::iterator It = Line.begin(); > bool Result = parse(It, Line.end(), ip_address, Ip); > bool Full = It == Line.end(); > std::cout << "Result = " << Result << ", full parse = " << Full << ", Ip > = " << Ip << std::endl; > return 0; > } Most of us probably already have one that parses an IP address into its proper unsigned form, a string is too heavyweight for that. :) ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Spirit-general mailing list Spirit-general@... https://lists.sourceforge.net/lists/listinfo/spirit-general |
| Free embeddable forum powered by Nabble | Forum Help |