Subject: [Boost-bugs] [Boost C++ Libraries] #12497: Errors with QI and Karma rules managing 64 bit integers
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-10-02 19:26:25
#12497: Errors with QI and Karma rules managing 64 bit integers
-----------------------------------------+-------------------------
Reporter: Gilles Brunet <gillesb68@â¦> | Owner: djowel
Type: Bugs | Status: new
Milestone: To Be Determined | Component: spirit
Version: Boost 1.61.0 | Severity: Showstopper
Keywords: |
-----------------------------------------+-------------------------
MSVC++ 14 used to build the following source code enclosing a trio of
spirit components (Lex, QI and Karma) performing three steps:
1. Uses âSpirit Lexâ to make tokens from input text;
1. Uses âSpirit QIâ for parsing tokens to generate an AST; and
1. Uses âSpirit Karmaâ for generating back the original text.
The âQIâ and âKarmaâ grammars are compiling and running fine with tokens
enclosing 32 bit integers. However, the compiler generates thousands of
errors with tokens enclosing 64 bit integers.
For reproducing the problem, we move comments in front of the alias type
named âint_lit_typeâ for defining it as a 64-bit integer. The code
compiles and runs fine with 32 bit integers, and do not compile with 64
bit ones. The same result carried out whenever the compiler is configured
for targeting âx86â or âx64â.
Here is the source code:
{{{
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/variant.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/phoenix.hpp>
#include <boost/phoenix/object/construct.hpp>
#include <string>
#include <vector>
namespace spirit = boost::spirit;
namespace phoenix = boost::phoenix;
namespace lex = spirit::lex;
namespace qi = spirit::qi;
namespace karma = spirit::karma;
///////////////////////////////////
// Lexer
using real_lit_type = long double;
//using int_lit_type = long;
using int_lit_type = std::int32_t;
//using int_lit_type = long long;
//using int_lit_type = std::int64_t;
template <typename Lexer>
struct lexer_grammar : lex::lexer<Lexer>
{
lexer_grammar()
: int_lit{"[0-9]+"}
, real_lit{"[0-9]+\\.([0-9]+([Ee][\\-\\+]?[0-9]*)?)?"}
, identifier{"[_a-zA-Z][_a-zA-Z0-9]*"}
{
this->self
= lex::token_def<>("[ \\t\\n\\r]+")[lex::_pass =
lex::pass_flags::pass_ignore]
| real_lit
| int_lit
| identifier
| lex::token_def<>('(') | ')' | '=' | ';';
}
lex::token_def<real_lit_type> real_lit;
lex::token_def<int_lit_type> int_lit;
lex::token_def<std::string> identifier;
};
template <typename Iterator>
struct tokens_factory
{
using iterator_type = Iterator;
using value_type = boost::mpl::vector<int_lit_type, real_lit_type,
std::string>;
using token_type = lex::lexertl::token<iterator_type, value_type,
boost::mpl::true_>;
using lexer_type =
lexer_grammar<lex::lexertl::actor_lexer<token_type>>;
};
///////////////////////////////////
// AST
namespace ast {
using literal_type = boost::variant<int_lit_type, real_lit_type>;
using identifier_type = std::string;
using expr_type = boost::variant<literal_type, identifier_type>;
struct assign_stmt_type
{
assign_stmt_type() {}
template <typename Stmt>
explicit assign_stmt_type(const Stmt& stmt);
identifier_type var_ref;
expr_type expr;
};
using stmt_type = boost::variant<assign_stmt_type>;
using stmt_list_type = std::vector<stmt_type>;
template <>
inline assign_stmt_type::assign_stmt_type(const stmt_type& stmt)
{
*this = boost::get<assign_stmt_type>(stmt);
}
}
BOOST_FUSION_ADAPT_STRUCT(
ast::assign_stmt_type,
var_ref,
expr
)
template <typename Iterator, typename Lexer>
struct parser_grammar : qi::grammar<Iterator, ast::stmt_list_type()>
{
explicit parser_grammar(const Lexer& tokens)
: parser_grammar::base_type{stmt_list}
{
stmt_list = *(stmt >> ';');
stmt = assign_stmt;
assign_stmt = var_ref_expr >> '=' >> expr;
expr
= ('(' >> expr >> ')')
| var_ref_expr
| literal_expr;
var_ref_expr
= tokens.identifier;
literal_expr
= tokens.int_lit
| tokens.real_lit;
}
qi::rule<Iterator, ast::stmt_list_type()> stmt_list;
qi::rule<Iterator, ast::stmt_type()> stmt;
qi::rule<Iterator, ast::assign_stmt_type()> assign_stmt;
qi::rule<Iterator, ast::expr_type()> expr;
qi::rule<Iterator, ast::identifier_type()> var_ref_expr;
qi::rule<Iterator, ast::literal_type()> literal_expr;
};
///////////////////////////////////
// Generator
template <typename Iterator>
struct generator_grammar
: karma::grammar<Iterator, ast::stmt_list_type()>
{
generator_grammar() : generator_grammar::base_type(stmt_list)
{
stmt_list = *(stmt << karma::lit(';') << karma::eol);
stmt = assign_stmt;
assign_stmt = var_ref_expr << karma::lit(" = ") << expr;
expr
= var_ref_expr
| literal_expr;
var_ref_expr = karma::string;
literal_expr
= int_literal_expr
| real_literal_expr;
int_literal_expr
= karma::long_long
| karma::long_;
real_literal_expr
= karma::long_double;
}
karma::rule<Iterator, ast::stmt_list_type()> stmt_list;
karma::rule<Iterator, ast::stmt_type()> stmt;
karma::rule<Iterator, ast::assign_stmt_type()> assign_stmt;
karma::rule<Iterator, ast::expr_type()> expr;
karma::rule<Iterator, ast::identifier_type()> var_ref_expr;
karma::rule<Iterator, ast::literal_type()> literal_expr;
karma::rule<Iterator, int_lit_type()> int_literal_expr;
karma::rule<Iterator, real_lit_type()> real_literal_expr;
};
///////////////////////////////////
// main
int main()
{
static const auto text = std::string{
"var1 = 25.3;\n"
"var2 = 455;\n"
"var3 = var2;"
};
using lexer_type =
tokens_factory<std::string::const_iterator>::lexer_type;
lexer_type lexer{};
auto tokens = std::vector<lexer_type::token_type>{};
parser_grammar<lexer_type::iterator_type, lexer_type>
parser{lexer};
auto it = text.begin();
auto lex_it = lexer.begin(it, text.end());
auto lex_end = lexer.end();
auto stmt_list = ast::stmt_list_type{};
auto parser_success = qi::parse(lex_it, lex_end, parser,
stmt_list);
if (parser_success) {
std::cout << "parser success. Then, generates back the
source." << std::endl << std::endl;
using output_iterator_type =
std::back_insert_iterator<std::string>;
using generator_type =
generator_grammar<output_iterator_type>;
std::string generated;
output_iterator_type outit(generated);
generator_type generator{};
auto generator_success = karma::generate(outit, generator,
stmt_list);
if (generator_success) {
std::cout
<< "generator success:" << std::endl
<< generated << std::endl;
} else
std::cout << "generator failure" << std::endl;
} else
std::cout << "parser failure" << std::endl;
return 0;
}
}}}
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/12497> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:20 UTC