diff --git a/src/actions.cpp b/src/actions.cpp index 9db679f..a8ddda5 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -49,18 +49,19 @@ namespace quickbook { if(!actions.output_pre(phrase)) return; - position const pos = first.get_position(); - detail::outwarn(pos.file,pos.line) << "in column:" << pos.column << ", " + file_position const pos = first.get_position(); + detail::outwarn(actions.filename, pos.line) + << "in column:" << pos.column << ", " << "[br] and \\n are deprecated" << ".\n"; phrase << break_mark; } void error_action::operator()(iterator first, iterator /*last*/) const { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Syntax Error near column " << pos.column << ".\n"; - ++error_count; + ++actions.error_count; } void tagged_action::operator()(std::string const& str) const @@ -308,10 +309,10 @@ namespace quickbook if (mark != list_marks.top().first) // new_indent == list_indent { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Illegal change of list style near column " << pos.column << ".\n"; - detail::outwarn(pos.file,pos.line) + detail::outwarn(actions.filename, pos.line) << "Ignoring change of list style" << std::endl; ++error_count; } @@ -329,9 +330,9 @@ namespace quickbook void unexpected_char::operator()(iterator first, iterator last) const { - position const pos = first.get_position(); + file_position const pos = first.get_position(); - detail::outwarn(pos.file, pos.line) + detail::outwarn(actions.filename, pos.line) << "in column:" << pos.column << ", unexpected character: " << std::string(first, last) << "\n"; @@ -404,9 +405,8 @@ namespace quickbook if (program.size() == 0) return; // Nothing left to do here. The program is empty. - iterator first_(program.begin(), program.end()); - iterator last_(program.end(), program.end()); - first_.set_position(first.get_position()); + iterator first_(program.begin(), first.get_position()); + iterator last_(program.end()); // TODO: Shouldn't phrase be empty here? Why would it be output // after the code block? @@ -491,13 +491,13 @@ namespace quickbook void attribute_action::operator()(iterator first, iterator last) const { - position const pos = first.get_position(); + file_position const pos = first.get_position(); if (!attributes.insert( attribute_map::value_type(attribute_name, std::string(first, last)) ).second) { - detail::outwarn(pos.file,pos.line) + detail::outwarn(actions.filename, pos.line) << "Repeated attribute: " << attribute_name << ".\n"; } } @@ -632,12 +632,17 @@ namespace quickbook { if(actions.suppress) return; if (!actions.templates.add( - template_symbol(actions.template_identifier, actions.template_info, - std::string(first, last), first.get_position(), - actions.template_block, &actions.templates.top_scope()))) + template_symbol( + actions.template_identifier, + actions.template_info, + std::string(first, last), + actions.filename, + first.get_position(), + actions.template_block, + &actions.templates.top_scope()))) { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Template Redefinition: " << actions.template_identifier << std::endl; ++actions.error_count; } @@ -706,7 +711,8 @@ namespace quickbook bool break_arguments( std::vector& args , std::vector const& params - , position const& pos + , fs::path const& filename + , file_position const& pos ) { // Quickbook 1.4-: If there aren't enough parameters seperated by @@ -727,9 +733,8 @@ namespace quickbook // arguments, or if there are no more spaces left. template_body& body = args.back(); - iterator begin(body.content.begin(), body.content.end(), - position(body.position.file.c_str(), body.position.line, body.position.column)); - iterator end(body.content.end(), body.content.end()); + iterator begin(body.content.begin(), body.position); + iterator end(body.content.end()); iterator l_pos = find_first_seperator(begin, end); if (l_pos == end) @@ -740,7 +745,7 @@ namespace quickbook while(r_pos != end && std::find(whitespace, whitespace_end, *r_pos) != whitespace_end) ++r_pos; if (r_pos == end) break; - template_body second(std::string(r_pos, end), r_pos.get_position(), false); + template_body second(std::string(r_pos, end), body.filename, r_pos.get_position(), false); body.content = std::string(begin, l_pos); args.push_back(second); } @@ -748,7 +753,7 @@ namespace quickbook if (args.size() != params.size()) { - detail::outerr(pos.file, pos.line) + detail::outerr(filename, pos.line) << "Invalid number of arguments passed. Expecting: " << params.size() << " argument(s), got: " @@ -765,7 +770,7 @@ namespace quickbook std::vector& args , std::vector const& params , template_scope const& scope - , position const& pos + , file_position const& pos , quickbook::actions& actions ) { @@ -779,9 +784,9 @@ namespace quickbook { if (!actions.templates.add( template_symbol(*tpl, empty_params, arg->content, - arg->position, arg->is_block, &scope))) + arg->filename, arg->position, arg->is_block, &scope))) { - detail::outerr(pos.file,pos.line) + detail::outerr(actions.filename, pos.line) << "Duplicate Symbol Found" << std::endl; ++actions.error_count; return std::make_pair(false, tpl); @@ -816,9 +821,10 @@ namespace quickbook if (!body.is_block) { // do a phrase level parse - iterator first(body.content.begin(), body.content.end(), - position(body.position.file.c_str(), body.position.line, body.position.column)); - iterator last(body.content.end(), body.content.end()); + actions.filename = body.filename; + iterator first(body.content.begin(), body.position); + iterator last(body.content.end()); + return cl::parse(first, last, actions.grammar().simple_phrase).full; } else @@ -827,10 +833,11 @@ namespace quickbook // ensure that we have enough trailing newlines to eliminate // the need to check for end of file in the grammar. + actions.filename = body.filename; std::string content = body.content + "\n\n"; - iterator first(content.begin(), content.end(), - position(body.position.file.c_str(), body.position.line, body.position.column)); - iterator last(content.end(), content.end()); + iterator first(content.begin(), body.position); + iterator last(content.end()); + return cl::parse(first, last, actions.grammar().block).full; } } @@ -849,6 +856,7 @@ namespace quickbook actions.template_args.push_back( template_body( std::string(first, last), + actions.filename, first.get_position(), actions.template_block)); } @@ -863,12 +871,12 @@ namespace quickbook std::string identifier; std::swap(args, actions.template_args); std::swap(identifier, actions.template_identifier); - position const pos = first.get_position(); + file_position const pos = first.get_position(); ++actions.template_depth; if (actions.template_depth > actions.max_template_depth) { - detail::outerr(pos.file,pos.line) + detail::outerr(actions.filename, pos.line) << "Infinite loop detected" << std::endl; --actions.template_depth; ++actions.error_count; @@ -908,7 +916,7 @@ namespace quickbook { // Break the arguments for a template - if (!break_arguments(args, symbol->params, pos)) + if (!break_arguments(args, symbol->params, actions.filename, pos)) { actions.pop(); // restore the actions' states --actions.template_depth; @@ -920,7 +928,7 @@ namespace quickbook { if (!args.empty()) { - detail::outerr(pos.file, pos.line) + detail::outerr(actions.filename, pos.line) << "Arguments for code snippet." <"; code += "'''"; - args.push_back(template_body(code, first.get_position(), false)); + args.push_back(template_body(code, actions.filename, pos, false)); } } @@ -965,8 +973,8 @@ namespace quickbook if (!parse_template(symbol->body, actions.template_escape, actions)) { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Expanding " << (symbol->body.is_block ? "block" : "phrase") << " template: " << symbol->identifier << std::endl @@ -983,8 +991,8 @@ namespace quickbook if (actions.section_level != actions.min_section_level) { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Mismatched sections in template " << identifier << std::endl; actions.pop(); // restore the actions' states --actions.template_depth; @@ -1014,7 +1022,7 @@ namespace quickbook if(!r) { - detail::outerr(c.position.file, c.position.line) + detail::outerr(c.filename, c.position.line) << "Expanding callout." << std::endl << "------------------begin------------------" << std::endl << c.content @@ -1241,8 +1249,8 @@ namespace quickbook if (section_level <= min_section_level) { - position const pos = first.get_position(); - detail::outerr(pos.file,pos.line) + file_position const pos = first.get_position(); + detail::outerr(actions.filename, pos.line) << "Mismatched [endsect] near column " << pos.column << ".\n"; ++error_count; @@ -1266,8 +1274,8 @@ namespace quickbook void element_id_warning_action::operator()(iterator first, iterator) const { - position const pos = first.get_position(); - detail::outwarn(pos.file,pos.line) << "Empty id.\n"; + file_position const pos = first.get_position(); + detail::outwarn(actions.filename, pos.line) << "Empty id.\n"; } fs::path path_difference(fs::path const& outdir, fs::path const& path) @@ -1361,8 +1369,7 @@ namespace quickbook ts.parent = &actions.templates.top_scope(); if (!actions.templates.add(ts)) { - cl::file_position const pos = ts.body.position; - detail::outerr(pos.file, pos.line) + detail::outerr(ts.body.filename, ts.body.position.line) << "Template Redefinition: " << tname << std::endl; ++actions.error_count; } diff --git a/src/actions.hpp b/src/actions.hpp index d8b2f4e..342322c 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -117,13 +117,12 @@ namespace quickbook { // Prints an error message to std::cerr - error_action( - int& error_count) - : error_count(error_count) {} + error_action(quickbook::actions& actions) + : actions(actions) {} void operator()(iterator first, iterator /*last*/) const; - int& error_count; + quickbook::actions& actions; }; struct tagged_action @@ -392,12 +391,16 @@ namespace quickbook { // Handles unexpected chars in c++ syntax - unexpected_char(collector& out) - : out(out) {} + unexpected_char( + collector& out + , quickbook::actions& actions) + : out(out) + , actions(actions) {} void operator()(iterator first, iterator last) const; collector& out; + quickbook::actions& actions; }; struct anchor_action @@ -518,16 +521,16 @@ namespace quickbook attribute_action( attribute_map& attributes , std::string& attribute_name - , int& error_count) + , quickbook::actions& actions) : attributes(attributes) , attribute_name(attribute_name) - , error_count(error_count) {} + , actions(actions) {} void operator()(iterator first, iterator last) const; attribute_map& attributes; std::string& attribute_name; - int& error_count; + quickbook::actions& actions; }; struct image_action @@ -821,7 +824,12 @@ namespace quickbook struct element_id_warning_action { - void operator()(iterator first, iterator last) const; + element_id_warning_action(quickbook::actions& actions_) + : actions(actions_) {} + + void operator()(iterator first, iterator last) const; + + quickbook::actions& actions; }; struct xinclude_action diff --git a/src/actions_class.cpp b/src/actions_class.cpp index cb7183a..8695db1 100644 --- a/src/actions_class.cpp +++ b/src/actions_class.cpp @@ -77,7 +77,7 @@ namespace quickbook , suppress(false) // actions - , error(error_count) + , error(*this) , extract_doc_title(doc_title, phrase, *this) , extract_doc_license(doc_license, phrase, *this) , extract_doc_purpose(doc_purpose, phrase, *this) @@ -117,7 +117,7 @@ namespace quickbook , plain_char(phrase, *this) , raw_char(phrase, *this) , escape_unicode(phrase, *this) - , attribute(attributes, attribute_name, error_count) + , attribute(attributes, attribute_name, *this) , image(phrase, attributes, image_fileref, *this) , cond_phrase_pre(condition, macro) , scoped_cond_phrase(*this) @@ -192,6 +192,7 @@ namespace quickbook , begin_section(out, phrase, doc_id, section_id, section_level, qualified_section_id, element_id, *this) , end_section(out, section_level, min_section_level, qualified_section_id, error_count, *this) + , element_id_warning(*this) , xinclude(out, *this) , include(*this) , import(out, *this) diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp index 01091ce..0314ef7 100644 --- a/src/code_snippet.cpp +++ b/src/code_snippet.cpp @@ -22,10 +22,12 @@ namespace quickbook struct code_snippet_actions { code_snippet_actions(std::vector& storage, + std::string const& filename, std::string const& doc_id, char const* source_type) : callout_id(0) , storage(storage) + , filename(filename) , doc_id(doc_id) , source_type(source_type) {} @@ -63,6 +65,7 @@ namespace quickbook std::string code; std::string id; std::vector& storage; + boost::filesystem::path filename; std::string const doc_id; char const* const source_type; }; @@ -271,13 +274,13 @@ namespace quickbook if (err != 0) return err; // return early on error - iterator first(code.begin(), code.end(), file.c_str()); - iterator last(code.end(), code.end()); + iterator first(code.begin()); + iterator last(code.end()); size_t fname_len = file.size(); bool is_python = fname_len >= 3 && file[--fname_len]=='y' && file[--fname_len]=='p' && file[--fname_len]=='.'; - code_snippet_actions a(storage, doc_id, is_python ? "[python]" : "[c++]"); + code_snippet_actions a(storage, file, doc_id, is_python ? "[python]" : "[c++]"); // TODO: Should I check that parse succeeded? if(is_python) { boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a)); @@ -346,7 +349,7 @@ namespace quickbook code += "``[[callout" + boost::lexical_cast(callout_id) + "]]``"; snippet_stack.top().callouts.push_back( - template_body(std::string(first, last), first.get_position(), true)); + template_body(std::string(first, last), filename, first.get_position(), true)); ++callout_id; } @@ -400,7 +403,7 @@ namespace quickbook } // TODO: Save position in start_snippet - template_symbol symbol(snippet.id, params, body, first.get_position(), true); + template_symbol symbol(snippet.id, params, body, filename, first.get_position(), true); symbol.callout = true; symbol.callouts = snippet.callouts; storage.push_back(symbol); diff --git a/src/fwd.hpp b/src/fwd.hpp index e98e15d..1e0926e 100644 --- a/src/fwd.hpp +++ b/src/fwd.hpp @@ -11,18 +11,14 @@ #if !defined(BOOST_SPIRIT_FWD_HPP) #define BOOST_SPIRIT_FWD_HPP -#include -#include -#include +#include "iterator.hpp" namespace quickbook { struct actions; struct quickbook_grammar; - typedef boost::spirit::classic::file_position_base position; - typedef boost::spirit::classic::position_iterator< - std::string::const_iterator, position> iterator; + typedef position_iterator iterator; } #endif diff --git a/src/iterator.hpp b/src/iterator.hpp new file mode 100644 index 0000000..09290e8 --- /dev/null +++ b/src/iterator.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2010 Daniel James + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#if !defined(BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP) +#define BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP + +#include +#include + +namespace quickbook +{ + struct file_position + { + file_position() : line(0), column(0) {} + file_position(int l, int c) : line(l), column(c) {} + + int line; + int column; + }; + + template + struct position_iterator + : boost::forward_iterator_helper< + position_iterator, + typename boost::iterator_value::type, + typename boost::iterator_difference::type, + typename boost::iterator_pointer::type, + typename boost::iterator_reference::type + > + { + position_iterator() {} + explicit position_iterator(Iterator base) + : base_(base), previous_('\0'), position_() {} + explicit position_iterator(Iterator base, file_position const& position) + : base_(base), previous_('\0'), position_(position) {} + + friend bool operator==( + position_iterator const& x, + position_iterator const& y) + { + return x.base_ == y.base_; + } + + position_iterator& operator++() + { + char val = *base_; + + if (val == '\r') { + ++position_.line; + position_.column = 0; + } + else if (val == '\n') { + if (previous_ != '\r') { + ++position_.line; + position_.column = 0; + } + } + else { + ++position_.column; + } + + previous_ = val; + ++base_; + + return *this; + } + + typename boost::iterator_reference::type operator*() const + { + return *base_; + } + + file_position const& get_position() const { + return position_; + } + + Iterator base() const { + return base_; + } + + private: + Iterator base_; + char previous_; + file_position position_; + }; +} + +#endif diff --git a/src/post_process.cpp b/src/post_process.cpp index 9c98aa2..fbbc79d 100644 --- a/src/post_process.cpp +++ b/src/post_process.cpp @@ -444,7 +444,7 @@ namespace quickbook else { // fallback! - ::quickbook::detail::outerr("") + ::quickbook::detail::outerr() << "Warning: Post Processing Failed." << std::endl; out << in; @@ -455,7 +455,7 @@ namespace quickbook catch(...) { // fallback! - ::quickbook::detail::outerr("") + ::quickbook::detail::outerr() << "Post Processing Failed." << std::endl; out << in; diff --git a/src/quickbook.cpp b/src/quickbook.cpp index 7ea4002..436e820 100644 --- a/src/quickbook.cpp +++ b/src/quickbook.cpp @@ -13,7 +13,6 @@ #include "post_process.hpp" #include "utils.hpp" #include "input_path.hpp" -#include #include #include #include @@ -49,8 +48,9 @@ namespace quickbook end = preset_defines.end(); it != end; ++it) { - iterator first(it->begin(), it->end(), "command line parameter"); - iterator last(it->end(), it->end()); + // TODO: Set filename in actor??? + iterator first(it->begin()); + iterator last(it->end()); cl::parse(first, last, actor.grammar().command_line_macro); // TODO: Check result? @@ -76,8 +76,8 @@ namespace quickbook return err; } - iterator first(storage.begin(), storage.end(), filein_); - iterator last(storage.end(), storage.end()); + iterator first(storage.begin()); + iterator last(storage.end()); cl::parse_info info = cl::parse(first, last, actor.grammar().doc_info); @@ -94,8 +94,8 @@ namespace quickbook if (!info.full) { - position const pos = info.stop.get_position(); - detail::outerr(pos.file,pos.line) + file_position const& pos = info.stop.get_position(); + detail::outerr(actor.filename, pos.line) << "Syntax Error near column " << pos.column << ".\n"; ++actor.error_count; } @@ -117,7 +117,7 @@ namespace quickbook if(actor.error_count) { - detail::outerr(filein_) + detail::outerr() << "Error count: " << actor.error_count << ".\n"; } @@ -291,7 +291,7 @@ main(int argc, char* argv[]) } else { - quickbook::detail::outerr("") << "Error: No filename given\n\n" + quickbook::detail::outerr() << "No filename given\n\n" << desc << std::endl; return 1; } @@ -299,13 +299,13 @@ main(int argc, char* argv[]) catch(std::exception& e) { - quickbook::detail::outerr("") << "Error: " << e.what() << "\n"; + quickbook::detail::outerr() << e.what() << "\n"; return 1; } catch(...) { - quickbook::detail::outerr("") << "Error: Exception of unknown type caught\n"; + quickbook::detail::outerr() << "Exception of unknown type caught\n"; return 1; } diff --git a/src/syntax_highlight.hpp b/src/syntax_highlight.hpp index 96aa425..264f886 100644 --- a/src/syntax_highlight.hpp +++ b/src/syntax_highlight.hpp @@ -57,7 +57,7 @@ namespace quickbook | char_ [Process("char", self.out)] | number [Process("number", self.out)] | cl::repeat_p(1)[cl::anychar_p] - [Unexpected(self.out)] + [Unexpected(self.out, self.escape_actions)] ) ; @@ -206,7 +206,7 @@ namespace quickbook | string_ [Process("string", self.out)] | number [Process("number", self.out)] | cl::repeat_p(1)[cl::anychar_p] - [Unexpected(self.out)] + [Unexpected(self.out, self.escape_actions)] ) ; diff --git a/src/template_stack.hpp b/src/template_stack.hpp index a343fe9..a1110cd 100644 --- a/src/template_stack.hpp +++ b/src/template_stack.hpp @@ -14,10 +14,11 @@ #include #include #include -#include #include #include #include +#include +#include "fwd.hpp" namespace quickbook { @@ -25,30 +26,20 @@ namespace quickbook { template_body( std::string const& content, - boost::spirit::classic::file_position const& position, + boost::filesystem::path const& filename, + file_position const& position, bool is_block ) : content(content) + , filename(filename) , position(position) , is_block(is_block) { } - template_body( - std::string const& content, - boost::spirit::classic::file_position_base const& position, - bool is_block - ) - : content(content) - , position(position.file, position.line, position.column) - , is_block(is_block) - { - } - std::string content; - // Note: Using file_position to store the filename after the file - // has been closed. - boost::spirit::classic::file_position position; + boost::filesystem::path filename; + file_position position; bool is_block; }; @@ -60,26 +51,13 @@ namespace quickbook std::string const& identifier, std::vector const& params, std::string const& body, - boost::spirit::classic::file_position const& position, + boost::filesystem::path const& filename, + file_position const& position, bool is_block, template_scope const* parent = 0) : identifier(identifier) , params(params) - , body(body, position, is_block) - , parent(parent) - , callout(false) - , callouts() {} - - template_symbol( - std::string const& identifier, - std::vector const& params, - std::string const& body, - boost::spirit::classic::file_position_base const& position, - bool is_block, - template_scope const* parent = 0) - : identifier(identifier) - , params(params) - , body(body, position, is_block) + , body(body, filename, position, is_block) , parent(parent) , callout(false) , callouts() {} diff --git a/src/utils.cpp b/src/utils.cpp index f78e054..9fd589a 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -151,33 +151,38 @@ namespace quickbook { namespace detail return uri; } - std::ostream& outerr(std::string const& file, int line) + std::ostream& outerr() + { + return std::clog << "Error: "; + } + + std::ostream& outerr(boost::filesystem::path const& file, int line) { if (line >= 0) { if (ms_errors) - return std::clog << file << "(" << line << "): error: "; + return std::clog << file.string() << "(" << line << "): error: "; else - return std::clog << file << ":" << line << ": error: "; + return std::clog << file.string() << ":" << line << ": error: "; } else { - return std::clog << file << ": error: "; + return std::clog << file.string() << ": error: "; } } - std::ostream& outwarn(std::string const& file, int line) + std::ostream& outwarn(boost::filesystem::path const& file, int line) { if (line >= 0) { if (ms_errors) - return std::clog << file << "(" << line << "): warning: "; + return std::clog << file.string() << "(" << line << "): warning: "; else - return std::clog << file << ":" << line << ": warning: "; + return std::clog << file.string() << ":" << line << ": warning: "; } else { - return std::clog << file << ": warning: "; + return std::clog << file.string() << ": warning: "; } } diff --git a/src/utils.hpp b/src/utils.hpp index e48a94f..9a18cc4 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace quickbook { namespace detail { @@ -63,8 +64,9 @@ namespace quickbook { namespace detail // common IDEs. Uses the ms_errors global to determine if VS format // or GCC format. Returns the stream to continue ouput of the verbose // error message. - std::ostream & outerr(std::string const& file, int line = -1); - std::ostream & outwarn(std::string const& file, int line = -1); + std::ostream & outerr(); + std::ostream & outerr(boost::filesystem::path const& file, int line = -1); + std::ostream & outwarn(boost::filesystem::path const& file, int line = -1); // load file into memory with extra trailing newlines to eliminate // the need to check for end of file in the grammar.