diff options
Diffstat (limited to 'src/template.cpp')
-rw-r--r-- | src/template.cpp | 534 |
1 files changed, 376 insertions, 158 deletions
diff --git a/src/template.cpp b/src/template.cpp index 3c60304..bc564cc 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -36,7 +36,7 @@ static QValueList<QCString> split(const QCString &str,const QCString &sep,bool a int j = 0; int i = str.find( sep, j ); - while (i!=-1) + while (i!=-1) { if ( str.mid(j,i-j).length() > 0 ) { @@ -109,58 +109,60 @@ class TemplateVariant::Private bool raw; }; -TemplateVariant::TemplateVariant() -{ +TemplateVariant::TemplateVariant() +{ p = new Private; p->type=None; } TemplateVariant::TemplateVariant(bool b) -{ +{ p = new Private; - p->type = Bool; - p->boolVal = b; + p->type = Bool; + p->boolVal = b; } -TemplateVariant::TemplateVariant(int v) -{ +TemplateVariant::TemplateVariant(int v) +{ p = new Private; - p->type = Integer; - p->intVal = v; + p->type = Integer; + p->intVal = v; } -TemplateVariant::TemplateVariant(const char *s) -{ +TemplateVariant::TemplateVariant(const char *s,bool raw) +{ p = new Private; - p->type = String; - p->strVal = s; + p->type = String; + p->strVal = s; + p->raw = raw; } -TemplateVariant::TemplateVariant(const QCString &s) -{ +TemplateVariant::TemplateVariant(const QCString &s,bool raw) +{ p = new Private; - p->type = String; - p->strVal = s; + p->type = String; + p->strVal = s; + p->raw = raw; } TemplateVariant::TemplateVariant(const TemplateStructIntf *s) -{ +{ p = new Private; - p->type = Struct; + p->type = Struct; p->strukt = s; } TemplateVariant::TemplateVariant(const TemplateListIntf *l) -{ +{ p = new Private; - p->type = List; - p->list = l; + p->type = List; + p->list = l; } TemplateVariant::TemplateVariant(const void *obj,FuncType f) -{ +{ p = new Private; - p->type = Function; - p->func = f; + p->type = Function; + p->func = f; p->obj = obj; } @@ -169,7 +171,7 @@ TemplateVariant::~TemplateVariant() delete p; } -TemplateVariant::TemplateVariant(const TemplateVariant &v) +TemplateVariant::TemplateVariant(const TemplateVariant &v) { p = new Private; p->type = v.p->type; @@ -182,13 +184,13 @@ TemplateVariant::TemplateVariant(const TemplateVariant &v) case String: p->strVal = v.p->strVal; break; case Struct: p->strukt = v.p->strukt; break; case List: p->list = v.p->list; break; - case Function: p->func = v.p->func; + case Function: p->func = v.p->func; p->obj = v.p->obj; break; } } -TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v) -{ +TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v) +{ p->type = v.p->type; p->raw = v.p->raw; switch (p->type) @@ -199,10 +201,10 @@ TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v) case String: p->strVal = v.p->strVal; break; case Struct: p->strukt = v.p->strukt; break; case List: p->list = v.p->list; break; - case Function: p->func = v.p->func; + case Function: p->func = v.p->func; p->obj = v.p->obj; break; } - return *this; + return *this; } QCString TemplateVariant::toString() const @@ -301,17 +303,17 @@ const TemplateListIntf *TemplateVariant::toList() const return p->type==List ? p->list : 0; } -QCString TemplateVariant::call(const QValueList<TemplateVariant> &args) +TemplateVariant TemplateVariant::call(const QValueList<TemplateVariant> &args) { if (p->type==Function) return p->func(p->obj,args); - return QCString(); + return TemplateVariant(); } bool TemplateVariant::operator==(TemplateVariant &other) { - if (p->type==None) + if (p->type==None) { - return FALSE; + return FALSE; } if (p->type==TemplateVariant::List && other.p->type==TemplateVariant::List) { @@ -327,14 +329,14 @@ bool TemplateVariant::operator==(TemplateVariant &other) } } -TemplateVariant::Type TemplateVariant::type() const -{ - return p->type; +TemplateVariant::Type TemplateVariant::type() const +{ + return p->type; } -bool TemplateVariant::isValid() const -{ - return p->type!=None; +bool TemplateVariant::isValid() const +{ + return p->type!=None; } void TemplateVariant::setRaw(bool b) @@ -427,7 +429,7 @@ class TemplateListConstIterator : public TemplateListIntf::ConstIterator public: TemplateListConstIterator(const TemplateList &l) : m_list(l) { m_index=-1; } virtual ~TemplateListConstIterator() {} - virtual void toFirst() + virtual void toFirst() { m_it = m_list.p->elems.begin(); m_index=0; @@ -507,11 +509,12 @@ class Operator ==, !=, <, >, <=, >= | : + , */ enum Type { - Or, And, Not, In, Equal, NotEqual, Less, Greater, LessEqual, - GreaterEqual, Filter, Colon, Last + Or, And, Not, In, Equal, NotEqual, Less, Greater, LessEqual, + GreaterEqual, Filter, Colon, Comma, Last }; static const char *toString(Type op) @@ -530,6 +533,7 @@ class Operator case GreaterEqual: return ">="; case Filter: return "|"; case Colon: return ":"; + case Comma: return ","; case Last: return "?"; } return "?"; @@ -556,24 +560,26 @@ class TemplateBlockContext }; -/** @brief Internal class representing the implementation of a template +/** @brief Internal class representing the implementation of a template * context */ class TemplateContextImpl : public TemplateContext { public: TemplateContextImpl(); virtual ~TemplateContextImpl(); - + // TemplateContext methods void push(); void pop(); void set(const char *name,const TemplateVariant &v); TemplateVariant get(const QCString &name) const; const TemplateVariant *getRef(const QCString &name) const; - void setOutputDirectory(const QCString &dir) + void setOutputDirectory(const QCString &dir) { m_outputDir = dir; } void setEscapeIntf(TemplateEscapeIntf *intf) { m_escapeIntf = intf; } + void setSpacelessIntf(TemplateSpacelessIntf *intf) + { m_spacelessIntf = intf; } // internal methods TemplateBlockContext *blockContext(); @@ -584,6 +590,9 @@ class TemplateContextImpl : public TemplateContext int line() const { return m_line; } QCString outputDirectory() const { return m_outputDir; } TemplateEscapeIntf *escapeIntf() const { return m_escapeIntf; } + TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; } + void enableSpaceless(bool b) { m_spacelessEnabled=b; } + bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; } private: QCString m_templateName; @@ -592,6 +601,8 @@ class TemplateContextImpl : public TemplateContext QList< QDict<TemplateVariant> > m_contextStack; TemplateBlockContext m_blockContext; TemplateEscapeIntf *m_escapeIntf; + TemplateSpacelessIntf *m_spacelessIntf; + bool m_spacelessEnabled; }; //----------------------------------------------------------------------------- @@ -802,15 +813,15 @@ static TemplateFilterFactory::AutoRegister<FilterAdd> fAdd("add"); static TemplateFilterFactory::AutoRegister<FilterPrepend> fPrepend("prepend"); static TemplateFilterFactory::AutoRegister<FilterLength> fLength("length"); static TemplateFilterFactory::AutoRegister<FilterDefault> fDefault("default"); -static TemplateFilterFactory::AutoRegister<FilterStripPath> fStripPath("strippath"); +static TemplateFilterFactory::AutoRegister<FilterStripPath> fStripPath("stripPath"); static TemplateFilterFactory::AutoRegister<FilterNoWrap> fNoWrap("nowrap"); //-------------------------------------------------------------------- -/** @brief Base class for all nodes in the abstract syntax tree of an - * expression. +/** @brief Base class for all nodes in the abstract syntax tree of an + * expression. */ -class ExprAst +class ExprAst { public: virtual ~ExprAst() {} @@ -821,7 +832,7 @@ class ExprAst class ExprAstNumber : public ExprAst { public: - ExprAstNumber(int num) : m_number(num) + ExprAstNumber(int num) : m_number(num) { TRACE(("ExprAstNumber(%d)\n",num)); } int number() const { return m_number; } virtual TemplateVariant resolve(TemplateContext *) { return TemplateVariant(m_number); } @@ -833,13 +844,13 @@ class ExprAstNumber : public ExprAst class ExprAstVariable : public ExprAst { public: - ExprAstVariable(const char *name) : m_name(name) + ExprAstVariable(const char *name) : m_name(name) { TRACE(("ExprAstVariable(%s)\n",name)); } const QCString &name() const { return m_name; } - virtual TemplateVariant resolve(TemplateContext *c) - { + virtual TemplateVariant resolve(TemplateContext *c) + { TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); - TemplateVariant v = c->get(m_name); + TemplateVariant v = c->get(m_name); if (!v.isValid()) { warn(ci->templateName(),ci->line(),"undefined variable '%s' in expression",m_name.data()); @@ -850,6 +861,34 @@ class ExprAstVariable : public ExprAst QCString m_name; }; +class ExprAstFunctionVariable : public ExprAst +{ + public: + ExprAstFunctionVariable(ExprAst *var,const QList<ExprAst> &args) + : m_var(var), m_args(args) + { TRACE(("ExprAstFunctionVariable(%s)\n",var->name().data())); + m_args.setAutoDelete(TRUE); + } + virtual TemplateVariant resolve(TemplateContext *c) + { + QValueList<TemplateVariant> args; + for (uint i=0;i<m_args.count();i++) + { + TemplateVariant v = m_args.at(i)->resolve(c); + args.append(v); + } + TemplateVariant v = m_var->resolve(c); + if (v.type()==TemplateVariant::Function) + { + v = v.call(args); + } + return v; + } + private: + ExprAst *m_var; + QList<ExprAst> m_args; +}; + /** @brief Class representing a filter in the AST */ class ExprAstFilter : public ExprAst { @@ -882,11 +921,11 @@ class ExprAstFilterAppl : public ExprAst { public: ExprAstFilterAppl(ExprAst *expr,ExprAstFilter *filter) - : m_expr(expr), m_filter(filter) + : m_expr(expr), m_filter(filter) { TRACE(("ExprAstFilterAppl\n")); } ~ExprAstFilterAppl() { delete m_expr; delete m_filter; } - virtual TemplateVariant resolve(TemplateContext *c) - { + virtual TemplateVariant resolve(TemplateContext *c) + { return m_filter->apply(m_expr->resolve(c),c); } private: @@ -898,7 +937,7 @@ class ExprAstFilterAppl : public ExprAst class ExprAstLiteral : public ExprAst { public: - ExprAstLiteral(const char *lit) : m_literal(lit) + ExprAstLiteral(const char *lit) : m_literal(lit) { TRACE(("ExprAstLiteral(%s)\n",lit)); } const QCString &literal() const { return m_literal; } virtual TemplateVariant resolve(TemplateContext *) { return TemplateVariant(m_literal); } @@ -910,10 +949,10 @@ class ExprAstLiteral : public ExprAst class ExprAstNegate : public ExprAst { public: - ExprAstNegate(ExprAst *expr) : m_expr(expr) + ExprAstNegate(ExprAst *expr) : m_expr(expr) { TRACE(("ExprAstNegate\n")); } ~ExprAstNegate() { delete m_expr; } - virtual TemplateVariant resolve(TemplateContext *c) + virtual TemplateVariant resolve(TemplateContext *c) { return TemplateVariant(!m_expr->resolve(c).toBool()); } private: ExprAst *m_expr; @@ -924,10 +963,10 @@ class ExprAstBinary : public ExprAst { public: ExprAstBinary(Operator::Type op,ExprAst *lhs,ExprAst *rhs) - : m_operator(op), m_lhs(lhs), m_rhs(rhs) + : m_operator(op), m_lhs(lhs), m_rhs(rhs) { TRACE(("ExprAstBinary %s\n",Operator::toString(op))); } ~ExprAstBinary() { delete m_lhs; delete m_rhs; } - virtual TemplateVariant resolve(TemplateContext *c) + virtual TemplateVariant resolve(TemplateContext *c) { TemplateVariant lhs = m_lhs->resolve(c); TemplateVariant rhs = m_rhs ? m_rhs->resolve(c) : TemplateVariant(); @@ -994,11 +1033,11 @@ class ExprAstBinary : public ExprAst class ExpressionParser { public: - ExpressionParser(const QCString &templateName,int line) - : m_templateName(templateName), m_line(line), m_tokenStream(0) + ExpressionParser(const QCString &templateName,int line) + : m_templateName(templateName), m_line(line), m_tokenStream(0) { } - virtual ~ExpressionParser() + virtual ~ExpressionParser() { } @@ -1050,7 +1089,7 @@ class ExpressionParser { TRACE(("{parseOrExpression(%s)\n",m_tokenStream)); ExprAst *lhs = parseAndExpression(); - if (lhs) + if (lhs) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Or) @@ -1068,7 +1107,7 @@ class ExpressionParser { TRACE(("{parseAndExpression(%s)\n",m_tokenStream)); ExprAst *lhs = parseNotExpression(); - if (lhs) + if (lhs) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::And) @@ -1189,11 +1228,38 @@ class ExpressionParser return lit; } + ExprAst *parseIdentifierOptionalArgs() + { + TRACE(("{parseIdentifierOptionalArgs(%s)\n",m_curToken.id.data())); + ExprAst *expr = parseIdentifier(); + if (expr) + { + if (m_curToken.type==ExprToken::Operator && + m_curToken.op==Operator::Colon) + { + getNextToken(); + ExprAst *argExpr = parsePrimaryExpression(); + QList<ExprAst> args; + args.append(argExpr); + while (m_curToken.type==ExprToken::Operator && + m_curToken.op==Operator::Comma) + { + getNextToken(); + argExpr = parsePrimaryExpression(); + args.append(argExpr); + } + expr = new ExprAstFunctionVariable(expr,args); + } + } + TRACE(("}parseIdentifierOptionalArgs()\n")); + return expr; + } + ExprAst *parseFilteredVariable() { TRACE(("{parseFilteredVariable()\n")); - ExprAst *expr = parseIdentifier(); - if (expr) + ExprAst *expr = parseIdentifierOptionalArgs(); + if (expr) { while (m_curToken.type==ExprToken::Operator && m_curToken.op==Operator::Filter) @@ -1300,6 +1366,12 @@ class ExpressionParser m_curToken.op = Operator::Colon; p++; } + else if (c==',') + { + m_curToken.type = ExprToken::Operator; + m_curToken.op = Operator::Comma; + p++; + } else if ((c=='-' && *(p+1)>='0' && *(p+1)<='9') || (c>='0' && c<='9')) { m_curToken.type = ExprToken::Number; @@ -1321,17 +1393,17 @@ class ExpressionParser s[0]=c; m_curToken.id = s; p++; - while ((c=*p) && + while ((c=*p) && (c=='_' || c=='.' || - (c>='a' && c<='z') || - (c>='A' && c<='Z') || + (c>='a' && c<='z') || + (c>='A' && c<='Z') || (c>='0' && c<='9')) ) { s[0]=c; m_curToken.id+=s; p++; - } + } } else if (c=='"' || c=='\'') { @@ -1470,9 +1542,10 @@ class TemplateImpl : public TemplateNode, public Template //---------------------------------------------------------- -TemplateContextImpl::TemplateContextImpl() - : m_templateName("<unknown>"), m_line(1), m_escapeIntf(0) -{ +TemplateContextImpl::TemplateContextImpl() + : m_templateName("<unknown>"), m_line(1), m_escapeIntf(0), + m_spacelessIntf(0), m_spacelessEnabled(FALSE) +{ m_contextStack.setAutoDelete(TRUE); push(); } @@ -1497,7 +1570,7 @@ TemplateVariant TemplateContextImpl::get(const QCString &name) const int i=name.find('.'); if (i==-1) // simple name { - return getPrimary(name); + return getPrimary(name); } else // obj.prop { @@ -1576,7 +1649,7 @@ const TemplateVariant *TemplateContextImpl::getRef(const QCString &name) const TemplateVariant TemplateContextImpl::getPrimary(const QCString &name) const { const TemplateVariant *v = getRef(name); - return v ? *v : TemplateVariant(); + return v ? *v : TemplateVariant(); } void TemplateContextImpl::push() @@ -1605,16 +1678,24 @@ TemplateBlockContext *TemplateContextImpl::blockContext() class TemplateNodeText : public TemplateNode { public: - TemplateNodeText(TemplateParser *,TemplateNode *parent,int,const QCString &data) - : TemplateNode(parent), m_data(data) + TemplateNodeText(TemplateParser *,TemplateNode *parent,int,const QCString &data) + : TemplateNode(parent), m_data(data) { TRACE(("TemplateNodeText('%s')\n",replace(data,'\n',' ').data())); } - void render(FTextStream &ts, TemplateContext *) + void render(FTextStream &ts, TemplateContext *c) { //printf("TemplateNodeText::render(%s)\n",m_data.data()); - ts << m_data; + TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); + if (ci->spacelessEnabled()) + { + ts << ci->spacelessIntf()->remove(m_data); + } + else + { + ts << m_data; + } } private: QCString m_data; @@ -1626,30 +1707,12 @@ class TemplateNodeText : public TemplateNode class TemplateNodeVariable : public TemplateNode { public: - TemplateNodeVariable(TemplateParser *parser,TemplateNode *parent,int line,const QCString &var) + TemplateNodeVariable(TemplateParser *parser,TemplateNode *parent,int line,const QCString &var) : TemplateNode(parent), m_templateName(parser->templateName()), m_line(line) { TRACE(("TemplateNodeVariable(%s)\n",var.data())); ExpressionParser expParser(m_templateName,line); - int i=var.find(':'); - int j=var.find('|'); - if (i==-1 || (j!=-1 && j<i)) // no arguments or arg belongs to filter - { - m_var = expParser.parseVariable(var); - } - else - { - QValueList<QCString> args = split(var.mid(i+1),","); - for (uint j=0;j<args.count();j++) - { - ExprAst *expr = expParser.parsePrimary(args[j]); - if (expr) - { - m_args.append(expr); - } - } - m_var = expParser.parseVariable(var.left(i)); - } + m_var = expParser.parseVariable(var); } ~TemplateNodeVariable() { @@ -1660,30 +1723,19 @@ class TemplateNodeVariable : public TemplateNode { TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); ci->setLocation(m_templateName,m_line); - QValueList<TemplateVariant> args; - for (uint i=0;i<m_args.count();i++) - { - TemplateVariant v = m_args.at(i)->resolve(c); - args.append(v); - } TemplateVariant v = m_var->resolve(c); - QCString value; if (v.type()==TemplateVariant::Function) { - value = v.call(args); - } - else - { - value = v.toString(); + v = v.call(QValueList<TemplateVariant>()); } //printf("TemplateNodeVariable::render(%s) raw=%d\n",value.data(),v.raw()); if (ci->escapeIntf() && !v.raw()) { - ts << ci->escapeIntf()->escape(value); + ts << ci->escapeIntf()->escape(v.toString()); } else { - ts << value; + ts << v.toString(); } } @@ -1696,13 +1748,13 @@ class TemplateNodeVariable : public TemplateNode //---------------------------------------------------------- -/** @brief Helper class for creating template AST tag nodes and returning +/** @brief Helper class for creating template AST tag nodes and returning * the template for a given node. */ template<class T> class TemplateNodeCreator : public TemplateNode { public: - TemplateNodeCreator(TemplateParser *parser,TemplateNode *parent,int line) + TemplateNodeCreator(TemplateParser *parser,TemplateNode *parent,int line) : TemplateNode(parent), m_templateName(parser->templateName()), m_line(line) {} static TemplateNode *createInstance(TemplateParser *parser, TemplateNode *parent, @@ -1790,7 +1842,7 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf> class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> { public: - TemplateNodeFor(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeFor(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeFor>(parser,parent,line) { TRACE(("{TemplateNodeFor(%s)\n",data.data())); @@ -1899,7 +1951,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> { c->set(m_vars[vi++],v); } - else if (m_vars.count()>1 && v.type()==TemplateVariant::Struct) + else if (m_vars.count()>1 && v.type()==TemplateVariant::Struct) // loop variables represent elements in a list item { for (uint i=0;i<m_vars.count();i++,vi++) @@ -1937,11 +1989,42 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor> //---------------------------------------------------------- +/** @brief Class representing an 'markers' tag in a template */ +class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg> +{ + public: + TemplateNodeMsg(TemplateParser *parser,TemplateNode *parent,int line,const QCString &) + : TemplateNodeCreator<TemplateNodeMsg>(parser,parent,line) + { + TRACE(("{TemplateNodeMsg()\n")); + QStrList stopAt; + stopAt.append("endmsg"); + parser->parse(this,line,stopAt,m_nodes); + parser->removeNextToken(); // skip over endmarkers + TRACE(("}TemplateNodeMsg()\n")); + } + void render(FTextStream &, TemplateContext *c) + { + TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c); + TemplateEscapeIntf *escIntf = ci->escapeIntf(); + ci->setEscapeIntf(0); // avoid escaping things we send to standard out + FTextStream ts(stdout); + m_nodes.render(ts,c); + ts << endl; + ci->setEscapeIntf(escIntf); + } + private: + TemplateNodeList m_nodes; +}; + + +//---------------------------------------------------------- + /** @brief Class representing a 'block' tag in a template */ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock> { public: - TemplateNodeBlock(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeBlock(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeBlock>(parser,parent,line) { TRACE(("{TemplateNodeBlock(%s)\n",data.data())); @@ -2014,7 +2097,7 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock> class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> { public: - TemplateNodeExtend(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeExtend(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeExtend>(parser,parent,line) { TRACE(("{TemplateNodeExtend(%s)\n",data.data())); @@ -2065,6 +2148,11 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> { bc->add(nb); } + TemplateNodeMsg *msg = dynamic_cast<TemplateNodeMsg*>(n); + if (msg) + { + msg->render(ts,c); + } } // render the base template with the given context @@ -2090,7 +2178,7 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend> class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude> { public: - TemplateNodeInclude(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeInclude(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeInclude>(parser,parent,line) { TRACE(("TemplateNodeInclude(%s)\n",data.data())); @@ -2140,11 +2228,11 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude> //---------------------------------------------------------- -/** @brief Class representing an 'instantiate' tag in a template */ +/** @brief Class representing an 'create' tag in a template */ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> { public: - TemplateNodeCreate(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeCreate(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line) { TRACE(("TemplateNodeCreate(%s)\n",data.data())); @@ -2237,19 +2325,19 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate> //---------------------------------------------------------- -/** @brief Class representing an 'instantiate' tag in a template */ +/** @brief Class representing an 'tree' tag in a template */ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> { struct TreeContext { - TreeContext(TemplateNodeTree *o,const TemplateListIntf *l,TemplateContext *c) + TreeContext(TemplateNodeTree *o,const TemplateListIntf *l,TemplateContext *c) : object(o), list(l), templateCtx(c) {} TemplateNodeTree *object; const TemplateListIntf *list; TemplateContext *templateCtx; }; public: - TemplateNodeTree(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeTree(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeTree>(parser,parent,line) { TRACE(("{TemplateNodeTree(%s)\n",data.data())); @@ -2269,9 +2357,10 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> { delete m_treeExpr; } - static QCString renderChildrenStub(const void *ctx, const QValueList<TemplateVariant> &) + static TemplateVariant renderChildrenStub(const void *ctx, const QValueList<TemplateVariant> &) { - return ((TreeContext*)ctx)->object->renderChildren((const TreeContext*)ctx); + return TemplateVariant(((TreeContext*)ctx)->object-> + renderChildren((const TreeContext*)ctx),TRUE); } QCString renderChildren(const TreeContext *ctx) { @@ -2305,7 +2394,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> } } } - if (!hasChildren) + if (!hasChildren) { c->set("children",TemplateVariant("")); // provide default m_treeNodes.render(ss,c); @@ -2339,7 +2428,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree> //---------------------------------------------------------- -/** @brief Class representing an 'instantiate' tag in a template */ +/** @brief Class representing an 'with' tag in a template */ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> { struct Mapping @@ -2350,9 +2439,10 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> ExprAst *value; }; public: - TemplateNodeWith(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + TemplateNodeWith(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) : TemplateNodeCreator<TemplateNodeWith>(parser,parent,line) { + TRACE(("{TemplateNodeWith(%s)\n",data.data())); m_args.setAutoDelete(TRUE); ExpressionParser expParser(parser->templateName(),line); QValueList<QCString> args = split(data," "); @@ -2379,6 +2469,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> stopAt.append("endwith"); parser->parse(this,line,stopAt,m_nodes); parser->removeNextToken(); // skip over endwith + TRACE(("}TemplateNodeWith(%s)\n",data.data())); } ~TemplateNodeWith() { @@ -2404,7 +2495,130 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith> //---------------------------------------------------------- -/** @brief Factory class for creating tag AST nodes found in a template */ +/** @brief Class representing an 'spaceless' tag in a template */ +class TemplateNodeSpaceless : public TemplateNodeCreator<TemplateNodeSpaceless> +{ + public: + TemplateNodeSpaceless(TemplateParser *parser,TemplateNode *parent,int line,const QCString &) + : TemplateNodeCreator<TemplateNodeSpaceless>(parser,parent,line) + { + TRACE(("{TemplateNodeSpaceless()\n")); + QStrList stopAt; + stopAt.append("endspaceless"); + parser->parse(this,line,stopAt,m_nodes); + parser->removeNextToken(); // skip over endwith + TRACE(("}TemplateNodeSpaceless()\n")); + } + void render(FTextStream &ts, TemplateContext *c) + { + TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); + bool wasSpaceless = ci->spacelessEnabled(); + ci->enableSpaceless(TRUE); + m_nodes.render(ts,c); + ci->enableSpaceless(wasSpaceless); + } + private: + TemplateNodeList m_nodes; +}; + +//---------------------------------------------------------- + +/** @brief Class representing an 'markers' tag in a template */ +class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers> +{ + public: + TemplateNodeMarkers(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + : TemplateNodeCreator<TemplateNodeMarkers>(parser,parent,line) + { + TRACE(("{TemplateNodeMarkers(%s)\n",data.data())); + int i = data.find(" in "); + int w = data.find(" with "); + if (i==-1 || w==-1 || w<i) + { + warn(m_templateName,line,"markers tag as wrong format. Expected: markers <var> in <list> with <string_with_markers>"); + } + else + { + ExpressionParser expParser(parser->templateName(),line); + m_var = data.left(i); + m_listExpr = expParser.parseVariable(data.mid(i+4,w-i-4)); + m_patternExpr = expParser.parseVariable(data.right(data.length()-w-6)); + } + QStrList stopAt; + stopAt.append("endmarkers"); + parser->parse(this,line,stopAt,m_nodes); + parser->removeNextToken(); // skip over endmarkers + TRACE(("}TemplateNodeMarkers(%s)\n",data.data())); + } + void render(FTextStream &ts, TemplateContext *c) + { + TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c); + ci->setLocation(m_templateName,m_line); + if (!m_var.isEmpty() && m_listExpr && m_patternExpr) + { + TemplateVariant v = m_listExpr->resolve(c); + const TemplateListIntf *list = v.toList(); + TemplateVariant patternStr = m_patternExpr->resolve(c); + if (list) + { + if (patternStr.type()==TemplateVariant::String) + { + TemplateListIntf::ConstIterator *it = list->createIterator(); + c->push(); + QCString str = patternStr.toString(); + QRegExp marker("@[0-9]+"); // pattern for a marker, i.e. @0, @1 ... @12, etc + int index=0,newIndex,matchLen; + while ((newIndex=marker.match(str,index,&matchLen))!=-1) + { + ts << str.mid(index,newIndex-index); // write text before marker + bool ok; + uint entryIndex = str.mid(newIndex+1,matchLen-1).toUInt(&ok); // get marker id + TemplateVariant var; + uint i=0; + // search for list element at position id + for (it->toFirst(); (it->current(var)) && i<entryIndex; it->toNext(),i++) {} + if (ok && i==entryIndex) // found element + { + c->set(m_var,var); // define local variable to hold element of list type + bool wasSpaceless = ci->spacelessEnabled(); + ci->enableSpaceless(TRUE); + m_nodes.render(ts,c); + ci->enableSpaceless(wasSpaceless); + } + else if (!ok) + { + warn(m_templateName,m_line,"markers pattern string has invalid markers '%s'",str.data()); + } + else if (i<entryIndex) + { + warn(m_templateName,m_line,"markers list does not an element for marker position %d",i); + } + index=newIndex+matchLen; // set index just after marker + } + ts << str.right(str.length()-index); // write text after last marker + c->pop(); + } + else + { + warn(m_templateName,m_line,"markers requires a parameter of string type after 'with'!"); + } + } + else + { + warn(m_templateName,m_line,"markers requires a parameter of list type after 'in'!"); + } + } + } + private: + TemplateNodeList m_nodes; + QCString m_var; + ExprAst *m_listExpr; + ExprAst *m_patternExpr; +}; + +//---------------------------------------------------------- + +/** @brief Factory class for creating tag AST nodes found in a template */ class TemplateNodeFactory { public: @@ -2450,20 +2664,23 @@ class TemplateNodeFactory }; // register a handler for each start tag we support -static TemplateNodeFactory::AutoRegister<TemplateNodeIf> autoRefIf("if"); -static TemplateNodeFactory::AutoRegister<TemplateNodeFor> autoRefFor("for"); -static TemplateNodeFactory::AutoRegister<TemplateNodeTree> autoRefTree("recursetree"); -static TemplateNodeFactory::AutoRegister<TemplateNodeWith> autoRefWith("with"); -static TemplateNodeFactory::AutoRegister<TemplateNodeBlock> autoRefBlock("block"); -static TemplateNodeFactory::AutoRegister<TemplateNodeExtend> autoRefExtend("extend"); -static TemplateNodeFactory::AutoRegister<TemplateNodeCreate> autoRefCreate("create"); -static TemplateNodeFactory::AutoRegister<TemplateNodeInclude> autoRefInclude("include"); +static TemplateNodeFactory::AutoRegister<TemplateNodeIf> autoRefIf("if"); +static TemplateNodeFactory::AutoRegister<TemplateNodeFor> autoRefFor("for"); +static TemplateNodeFactory::AutoRegister<TemplateNodeMsg> autoRefMsg("msg"); +static TemplateNodeFactory::AutoRegister<TemplateNodeTree> autoRefTree("recursetree"); +static TemplateNodeFactory::AutoRegister<TemplateNodeWith> autoRefWith("with"); +static TemplateNodeFactory::AutoRegister<TemplateNodeBlock> autoRefBlock("block"); +static TemplateNodeFactory::AutoRegister<TemplateNodeExtend> autoRefExtend("extend"); +static TemplateNodeFactory::AutoRegister<TemplateNodeCreate> autoRefCreate("create"); +static TemplateNodeFactory::AutoRegister<TemplateNodeInclude> autoRefInclude("include"); +static TemplateNodeFactory::AutoRegister<TemplateNodeMarkers> autoRefMarkers("markers"); +static TemplateNodeFactory::AutoRegister<TemplateNodeSpaceless> autoRefSpaceless("spaceless"); //---------------------------------------------------------- -TemplateBlockContext::TemplateBlockContext() : m_blocks(257) -{ - m_blocks.setAutoDelete(TRUE); +TemplateBlockContext::TemplateBlockContext() : m_blocks(257) +{ + m_blocks.setAutoDelete(TRUE); } TemplateNodeBlock *TemplateBlockContext::get(const QCString &name) const @@ -2552,7 +2769,7 @@ class TemplateLexer QCString m_data; }; -TemplateLexer::TemplateLexer(const QCString &fileName,const QCString &data) : +TemplateLexer::TemplateLexer(const QCString &fileName,const QCString &data) : m_fileName(fileName), m_data(data) { } @@ -2585,7 +2802,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) { switch (state) { - case StateText: + case StateText: if (c=='{') // {{ or {% or {# or something else { state=StateBeginTemplate; @@ -2728,7 +2945,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens) { state=StateText; startLinePos=pos+1; - // if the current line only contain commands and whitespace, + // if the current line only contain commands and whitespace, // then skip it in the output by moving lastTokenPos if (markStartPos!=-1 && emptyOutputLine) lastTokenPos = startLinePos; // reset markers @@ -2813,10 +3030,11 @@ void TemplateParser::parse( { nodes.append(node); } - else if (command=="empty" || command=="else" || - command=="endif" || command=="endfor" || - command=="endblock" || command=="endwith" || - command=="endrecursetree") + else if (command=="empty" || command=="else" || + command=="endif" || command=="endfor" || + command=="endblock" || command=="endwith" || + command=="endrecursetree" || command=="endspaceless" || + command=="endmarkers" || command=="endmsg") { warn(m_templateName,tok->line,"Found tag '%s' without matching start tag",command.data()); } @@ -2888,8 +3106,8 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS parser.parse(this,1,QStrList(),m_nodes); } -void TemplateImpl::render(FTextStream &ts, TemplateContext *c) -{ +void TemplateImpl::render(FTextStream &ts, TemplateContext *c) +{ if (!m_nodes.isEmpty()) { TemplateNodeExtend *ne = dynamic_cast<TemplateNodeExtend*>(m_nodes.getFirst()); @@ -2908,7 +3126,7 @@ void TemplateImpl::render(FTextStream &ts, TemplateContext *c) } } } - m_nodes.render(ts,c); + m_nodes.render(ts,c); } } |