Finally! Determining import precedence for templates is properly correct.

This commit is contained in:
jez 2008-11-25 12:27:33 +00:00
parent fe40d482f5
commit 38d2783be3
4 changed files with 74 additions and 89 deletions

View file

@ -54,8 +54,8 @@ public:
if(localName == "import")
{
std::string href = validate_href(qName, atts);
check_for_loops(import_stack_, href);
import_stack_.push_back(href);
//check_for_loops(import_stack_, href);
import_stack_.push_back(std::make_pair(href, context_->next_precedence()));
return;
} // if(localName == "import")
if(localName == "include")
@ -87,7 +87,7 @@ public:
no_content_ = false;
if(localName == "include")
{
include_stylesheet(href_.back());
include_stylesheet(href_.back(), context_->precedence());
href_.pop_back();
} // if ...
if(href_.empty())
@ -111,11 +111,9 @@ public:
{
while(!import_stack_.empty())
{
std::vector<std::string>::iterator import = import_stack_.end()-1;
ImportStack::iterator import = import_stack_.end()-1;
size_t index = import_stack_.size() - 1;
context_->push_import_precedence();
include_stylesheet(import_stack_.back());
context_->pop_import_precedence();
include_stylesheet(import_stack_.back().first, import_stack_.back().second);
import_stack_.erase(import_stack_.begin() + index);
} // while ...
} // unwind_imports
@ -130,9 +128,9 @@ private:
return context_->makeAbsolute(href);
} // validate_href
void check_for_loops(const std::vector<std::string>& stack, const std::string& href)
/* void check_for_loops(const ImportStack& stack, const std::string& href)
{
if(std::find(stack.begin(), stack.end(), href) != stack.end())
if(std::find(stack.begin(), stack.end(), candidate) != stack.end())
{
std::string error = "Stylesheet '" + href + "' includes/imports itself ";
for(std::vector<std::string>::const_iterator i = stack.begin(), ie = stack.end(); i != ie; ++i)
@ -140,13 +138,14 @@ private:
throw std::runtime_error(error);
} // if ...
} // check_for_loops
void include_stylesheet(const std::string& href)
*/
void include_stylesheet(const std::string& href, const Precedence& precedence)
{
check_for_loops(current_includes_, href);
//check_for_loops(current_includes_, href);
current_includes_.push_back(href);
std::string prev = context_->setBase(href);
context_->set_precedence(precedence);
SAX::InputSource<std::string> source(href);
SAX::XMLReader<std::string> include_parser;
@ -168,7 +167,9 @@ private:
SAX::DefaultHandler<std::string>* compiler_;
CompilationContext* context_;
bool no_content_;
std::vector<std::string> import_stack_;
typedef std::vector<std::pair<std::string, Precedence> > ImportStack;
ImportStack import_stack_;
std::vector<std::string> current_includes_;
std::vector<std::string> href_;

View file

@ -27,7 +27,8 @@ public:
parser_(parser),
stylesheet_(stylesheet),
autoNs_(1),
current_allowed_(false)
current_allowed_(false),
precedence_(Precedence::InitialPrecedence())
{
xpath_.setNamespaceContext(*this);
xpath_.setFunctionResolver(*this);
@ -139,23 +140,19 @@ public:
return ss.str();
} // autoNamespacePrefix
void push_import_precedence()
void set_precedence(const Precedence& prec)
{
precedenceStack_.push();
} // push_import_precedence
precedence_ = prec;
} // set_precedence
void pop_import_precedence()
Precedence next_precedence()
{
precedenceStack_.pop();
} // pop_import_precedence
// void set_precedence(const Prcedence& prec)
// const Precedence& next_precedence()
return precedence_.next_generation();
} // next_precedence
const Precedence& precedence() const
{
return precedenceStack_.top();
return precedence_;
} // precedence
private:
@ -203,7 +200,7 @@ private:
std::stack<SAX::DefaultHandler<std::string>*> handlerStack_;
std::stack<ItemContainer*> parentStack_;
std::map<std::string, Namespace> namespaceRemap_;
PrecedenceStack precedenceStack_;
Precedence precedence_;
CompilationContext(const CompilationContext&);
mutable int autoNs_;

View file

@ -195,19 +195,19 @@ private:
void doApplyTemplates(const DOM::Node<std::string>& node,
ExecutionContext& context,
const std::pair<std::string, std::string>& mode,
Precedence generation) const
const Precedence& generation) const
{
StackFrame frame(context);
std::vector<Precedence> higher_precedences;
std::vector<Precedence> lower_precedences;
for(TemplateStack::const_iterator ts = templates_.begin(), tse = templates_.end(); ts != tse; ++ts)
if(ts->first > generation)
higher_precedences.push_back(ts->first);
std::sort(higher_precedences.begin(), higher_precedences.end());
if(generation.is_descendant(ts->first))
lower_precedences.push_back(ts->first);
std::sort(lower_precedences.rbegin(), lower_precedences.rend());
current_mode_ = mode;
for(std::vector<Precedence>::const_iterator p = higher_precedences.begin(), pe = higher_precedences.end(); p != pe; ++p)
for(std::vector<Precedence>::const_iterator p = lower_precedences.begin(), pe = lower_precedences.end(); p != pe; ++p)
{
current_generation_ = *p;
ModeTemplates ts = templates_.find(current_generation_)->second;

View file

@ -12,29 +12,33 @@ public:
static const Precedence& FrozenPrecedence()
{
static Precedence frozen_(-1);
static Precedence frozen_;
return frozen_;
} // Precedence
Precedence() :
precedence_()
precedence_(),
children_(0)
{
//precedence_.push_back(0);
} // Precedence
Precedence(const Precedence& rhs) :
precedence_(rhs.precedence_)
precedence_(rhs.precedence_),
children_(rhs.children_)
{
} // Precedence
private:
Precedence(const std::vector<int> precedence) :
precedence_(precedence)
precedence_(precedence),
children_(0)
{
} // Precedence
Precedence(int precedence) :
precedence_()
precedence_(),
children_(0)
{
precedence_.push_back(precedence);
} // Precedence
@ -47,80 +51,63 @@ public:
return precedence_ == rhs.precedence_;
} // operator==
bool operator>(const Precedence& rhs) const
{
return precedence_ > rhs.precedence_;
} // operator>
Precedence& operator=(const Precedence& rhs)
{
std::vector<int> other(rhs.precedence_);
precedence_.swap(other);
children_ = rhs.children_;
return *this;
} // operator=
Precedence nextGeneration(int p) const
bool is_descendant(const Precedence& other) const
{
if(other.precedence_.size() <= precedence_.size())
return false;
for(int i = 0, ie = precedence_.size(); i != ie; ++i)
if(other.precedence_[i] != precedence_[i])
return false;
return true;
} // is_descendant
Precedence next_generation()
{
Precedence next(precedence_);
next.precedence_.push_back(p);
next.precedence_.push_back(++children_);
return next;
} // nextGeneration
private:
std::vector<int> precedence_;
int children_;
friend bool operator<(const Precedence& lhs, const Precedence& rhs);
friend std::ostream& operator<<(std::ostream& os, const Precedence& prec);
}; // class Precedence
bool operator<(const Precedence& lhs, const Precedence& rhs)
{
return lhs.precedence_.back() < rhs.precedence_.back();
} // PrecedenceCompare
if(lhs.precedence_ == rhs.precedence_)
return false;
std::ostream& operator<<(std::ostream& os, const Precedence& prec)
{
os << "(";
for(std::vector<int>::const_iterator p = prec.precedence_.begin(), pe = prec.precedence_.end(); p != pe; ++p)
int len = std::min(lhs.precedence_.size(), rhs.precedence_.size());
for(int c = 0; c < len; ++c)
{
if(p != prec.precedence_.begin())
os << ",";
os << *p;
} // for ..
os << ")";
} // operator<<
class PrecedenceStack
{
public:
PrecedenceStack() :
stack_(),
count_(1)
{
stack_.push(Precedence::InitialPrecedence());
} // PrecedenceStack
PrecedenceStack(const PrecedenceStack& rhs) :
stack_(rhs.stack_)
{
} // PrecedenceStack
const Precedence& top() const { return stack_.top(); }
void push()
{
stack_.push(top().nextGeneration(count_++));
std::cout << "Pushed " << top() << std::endl;
if(lhs.precedence_[c] < rhs.precedence_[c])
return true;
if(lhs.precedence_[c] > rhs.precedence_[c])
return false;
}
void pop() { stack_.pop(); }
void freeze()
{
while(!stack_.empty())
stack_.pop();
stack_.push(Precedence::FrozenPrecedence());
} // freeze
if(lhs.precedence_.size() < rhs.precedence_.size())
return false;
private:
std::stack<Precedence> stack_;
int count_;
}; // class PrecedenceStack
return true;
} // operator>
bool operator>(const Precedence& lhs, const Precedence& rhs)
{
return !(lhs == rhs) && !(lhs < rhs);
} // operator>
#endif