diff options
Diffstat (limited to 'src/docparser.cpp')
-rw-r--r-- | src/docparser.cpp | 3037 |
1 files changed, 3037 insertions, 0 deletions
diff --git a/src/docparser.cpp b/src/docparser.cpp new file mode 100644 index 0000000..90441bc --- /dev/null +++ b/src/docparser.cpp @@ -0,0 +1,3037 @@ +/****************************************************************************** + * + * + * + * + * Copyright (C) 1997-2002 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include <stdio.h> +#include <stdlib.h> + +#include <qfile.h> +#include <qfileinfo.h> +#include <qcstring.h> +#include <qstack.h> +#include <qdict.h> + +#include "doxygen.h" +#include "debug.h" + +#include "docparser.h" +#include "doctokenizer.h" +#include "cmdmapper.h" +#include "printdocvisitor.h" + +#define DBG(x) do {} while(0) +//#define DBG(x) printf x + +//--------------------------------------------------------------------------- + +static QStack<DocNode> g_nodeStack; +static QStack<DocStyleChange> g_styleStack; + +//--------------------------------------------------------------------------- + +/*! Returns TRUE iff node n is a child of a preformatted node */ +static bool insidePRE(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlPre) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + +/*! Returns TRUE iff node n is a child of a html list item node */ +static bool insideLI(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlListItem) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + +/*! Returns TRUE iff node n is a child of a unordered html list node */ +static bool insideUL(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlList && + ((DocHtmlList *)n)->type()==DocHtmlList::Unordered) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + +/*! Returns TRUE iff node n is a child of a ordered html list node */ +static bool insideOL(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlList && + ((DocHtmlList *)n)->type()==DocHtmlList::Ordered) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + +/*! Returns TRUE iff node n is a child of a language node */ +static bool insideLang(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_Language) return TRUE; + n=n->parent(); + } + return FALSE; +} + + +//--------------------------------------------------------------------------- + +// forward declaration +static bool defaultHandleToken(DocNode *parent,int tok, + QList<DocNode> &children,bool + handleWord=TRUE); + + +static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, + const QCString &cmdName) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return tok; + } + while ((tok=doctokenizerYYlex()) && tok!=TK_WHITESPACE && tok!=TK_NEWPARA) + { + if (!defaultHandleToken(parent,tok,children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command \\%s as the argument of a \\%s command at line %d\n", + g_token->name.data(),cmdName.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + return tok==TK_NEWPARA ? TK_NEWPARA : RetVal_OK; +} + +static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,DocStyleChange::Style s) +{ + DBG(("HandleStyleEnter\n")); + DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,TRUE); + children.append(sc); + g_styleStack.push(sc); +} + +static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,DocStyleChange::Style s,const char *tagName) +{ + DBG(("HandleStyleLeave\n")); + if (g_styleStack.isEmpty() || // no style change + g_styleStack.top()->style()!=s || // wrong style change + g_styleStack.top()->position()!=g_nodeStack.count() // wrong position + ) + { + printf("Error: found </%s> tag at line %d without matching <%s> in the same paragraph\n", + tagName,doctokenizerYYlineno,tagName); + } + else // end the section + { + DocStyleChange *sc= new DocStyleChange(parent,g_nodeStack.count(),s,FALSE); + children.append(sc); + g_styleStack.pop(); + } +} + +static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children) +{ + if (!g_styleStack.isEmpty()) + { + DocStyleChange *sc = g_styleStack.top(); + while (sc && sc->position()>=g_nodeStack.count()) + { // there are unclosed style modifiers in the paragraph + const char *cmd; + switch (sc->style()) + { + case DocStyleChange::Bold: cmd = "b"; break; + case DocStyleChange::Italic: cmd = "em"; break; + case DocStyleChange::Code: cmd = "code"; break; + case DocStyleChange::Center: cmd = "center"; break; + case DocStyleChange::Small: cmd = "small"; break; + case DocStyleChange::Subscript: cmd = "subscript"; break; + case DocStyleChange::Superscript: cmd = "superscript"; break; + } + printf("Error: end of paragraph at line %d without end of style " + "command </%s>\n",doctokenizerYYlineno,cmd); + children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE)); + g_styleStack.pop(); + sc = g_styleStack.top(); + } + } +} + +/* Helper function that deals with the most common tokens allowed in + * title like sections. + * @param parent Parent node, owner of the children list passed as + * the third argument. + * @param tok The token to process. + * @param children The list of child nodes to which the node representing + * the token can be added. + * @param handleWord Indicates if word token should be processed + * @retval TRUE The token was handled. + * @retval FALSE The token was not handled. + */ +static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool + handleWord=TRUE) +{ + DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + if (tok==TK_WORD || tok==TK_SYMBOL || tok==TK_URL || + tok==TK_COMMAND || tok==TK_HTMLTAG + ) + { + DBG((" name=%s",g_token->name.data())); + } + DBG(("\n")); + QCString tokenName = g_token->name; + switch (tok) + { + case TK_COMMAND: + switch (CmdMapper::map(tokenName)) + { + case CMD_BSLASH: + children.append(new DocSymbol(parent,DocSymbol::BSlash)); + break; + case CMD_AT: + children.append(new DocSymbol(parent,DocSymbol::At)); + break; + case CMD_LESS: + children.append(new DocSymbol(parent,DocSymbol::Less)); + break; + case CMD_GREATER: + children.append(new DocSymbol(parent,DocSymbol::Greater)); + break; + case CMD_AMP: + children.append(new DocSymbol(parent,DocSymbol::Amp)); + break; + case CMD_DOLLAR: + children.append(new DocSymbol(parent,DocSymbol::Dollar)); + break; + case CMD_HASH: + children.append(new DocSymbol(parent,DocSymbol::Hash)); + break; + case CMD_PERCENT: + children.append(new DocSymbol(parent,DocSymbol::Percent)); + break; + case CMD_EMPHASIS: + { + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,TRUE)); + int retval=handleStyleArgument(parent,children,tokenName); + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Italic,FALSE)); + if (retval==TK_NEWPARA) goto handlepara; + } + break; + case CMD_BOLD: + { + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); + int retval=handleStyleArgument(parent,children,tokenName); + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); + if (retval==TK_NEWPARA) goto handlepara; + } + break; + case CMD_CODE: + { + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,TRUE)); + int retval=handleStyleArgument(parent,children,tokenName); + children.append(new DocStyleChange(parent,g_nodeStack.count(),DocStyleChange::Code,FALSE)); + if (retval==TK_NEWPARA) goto handlepara; + } + break; + case CMD_HTMLONLY: + { + doctokenizerYYsetStateHtmlOnly(); + int retval = doctokenizerYYlex(); + children.append(new DocVerbatim(parent,g_token->verb,DocVerbatim::HtmlOnly)); + if (retval==0) printf("Error: htmlonly section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_LATEXONLY: + { + doctokenizerYYsetStateLatexOnly(); + int retval = doctokenizerYYlex(); + children.append(new DocVerbatim(parent,g_token->verb,DocVerbatim::LatexOnly)); + if (retval==0) printf("Error: latexonly section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_FORMULA: + { + DocFormula *form=new DocFormula(parent,g_token->id); + children.append(form); + } + break; + default: + return FALSE; + } + break; + case TK_HTMLTAG: + { + switch (HtmlTagMapper::map(tokenName)) + { + case HTML_BOLD: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Bold); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName); + } + break; + case HTML_CODE: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Code); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Code,tokenName); + } + break; + case HTML_EMPHASIS: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Italic); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Italic,tokenName); + } + break; + case HTML_SUB: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Subscript); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Subscript,tokenName); + } + break; + case HTML_SUP: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Superscript); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Superscript,tokenName); + } + break; + case HTML_CENTER: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Center); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Center,tokenName); + } + break; + case HTML_SMALL: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Small); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Small,tokenName); + } + break; + default: + return FALSE; + break; + } + } + break; + case TK_SYMBOL: + { + char letter='\0'; + DocSymbol::SymType s = DocSymbol::decodeSymbol(tokenName,&letter); + if (s!=DocSymbol::Unknown) + { + children.append(new DocSymbol(parent,s,letter)); + } + else + { + return FALSE; + } + } + break; + case TK_WHITESPACE: + case TK_NEWPARA: +handlepara: + if (insidePRE(parent) || !children.isEmpty()) + { + children.append(new DocWhiteSpace(parent,g_token->chars)); + } + break; + case TK_WORD: + if (handleWord) + children.append(new DocWord(parent,g_token->name)); + else + return FALSE; + break; + case TK_URL: + children.append(new DocURL(parent,g_token->name)); + break; + default: + return FALSE; + } + return TRUE; +} + + +//--------------------------------------------------------------------------- + +DocSymbol::SymType DocSymbol::decodeSymbol(const QCString &symName,char *letter) +{ + int l=symName.length(); + DBG(("decodeSymbol(%s) l=%d\n",symName.data(),l)); + if (symName=="©") return DocSymbol::Copy; + else if (symName=="<") return DocSymbol::Less; + else if (symName==">") return DocSymbol::Greater; + else if (symName=="&") return DocSymbol::Amp; + else if (symName=="'") return DocSymbol::Apos; + else if (symName==""") return DocSymbol::Quot; + else if (symName=="ß") return DocSymbol::Szlig; + else if (symName==" ") return DocSymbol::Nbsp; + else if (l==6 && symName.right(4)=="uml;") + { + *letter=symName.at(1); + return DocSymbol::Uml; + } + else if (l==8 && symName.right(6)=="acute;") + { + *letter=symName.at(1); + return DocSymbol::Acute; + } + else if (l==8 && symName.right(6)=="grave;") + { + *letter=symName.at(1); + return DocSymbol::Grave; + } + else if (l==7 && symName.right(5)=="circ;") + { + *letter=symName.at(1); + return DocSymbol::Circ; + } + else if (l==8 && symName.right(6)=="tilde;") + { + *letter=symName.at(1); + return DocSymbol::Tilde; + } + else if (l==8 && symName.right(6)=="cedil;") + { + *letter=symName.at(1); + return DocSymbol::Cedil; + } + else if (l==7 && symName.right(5)=="ring;") + { + *letter=symName.at(1); + return DocSymbol::Ring; + } + return DocSymbol::Unknown; +} + +//--------------------------------------------------------------------------- + +int DocLanguage::parse() +{ + int retval; + DBG(("DocLanguage::parse() start\n")); + g_nodeStack.push(this); + + // parse one or more paragraphs + do + { + DocPara *par = new DocPara(this); + m_children.append(par); + retval=par->parse(); + } + while (retval==TK_NEWPARA); + + DBG(("DocLanguage::parse() end\n")); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +void DocSecRefItem::parse() +{ + DBG(("DocSecRefItem::parse() start\n")); + g_nodeStack.push(this); + + doctokenizerYYsetStateTitle(); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a \\refitem at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + doctokenizerYYsetStatePara(); + handlePendingStyleCommands(this,m_children); + DBG(("DocSecRefItem::parse() end\n")); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); +} + +//--------------------------------------------------------------------------- + +void DocSecRefList::parse() +{ + DBG(("DocSecRefList::parse() start\n")); + g_nodeStack.push(this); + + int tok=doctokenizerYYlex(); + // skip white space + while (tok==TK_WHITESPACE) tok=doctokenizerYYlex(); + // handle items + while (tok) + { + if (tok==TK_COMMAND) + { + switch (CmdMapper::map(g_token->name)) + { + case CMD_SECREFITEM: + { + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after \\refitem command at line %d\n", + doctokenizerYYlineno); + break; + } + tok=doctokenizerYYlex(); + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of \\refitem at line %d.\n", + tokToString(tok),doctokenizerYYlineno); + break; + } + + DocSecRefItem *item = new DocSecRefItem(this,g_token->name); + m_children.append(item); + item->parse(); + } + break; + case CMD_ENDSECREFLIST: + goto endsecreflist; + default: + printf("Error: Illegal command %s as part of a \\secreflist at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + goto endsecreflist; + } + } + else + { + printf("Error: Unexpected token %s inside section reference list at line %d\n", + tokToString(tok),doctokenizerYYlineno); + goto endsecreflist; + } + tok=doctokenizerYYlex(); + } + +endsecreflist: + DBG(("DocSecRefList::parse() end\n")); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); +} + + + +//--------------------------------------------------------------------------- + +void DocRef::parse() +{ + g_nodeStack.push(this); + DBG(("DocRef::parse() start\n")); + + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a \\ref at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + + handlePendingStyleCommands(this,m_children); + DBG(("DocRef::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); +} + +//--------------------------------------------------------------------------- + +QCString DocLink::parse(bool isJavaLink) +{ + QCString result; + g_nodeStack.push(this); + DBG(("DocLink::parse() start\n")); + + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children,FALSE)) + { + switch (tok) + { + case TK_COMMAND: + switch (CmdMapper::map(g_token->name)) + { + case CMD_ENDLINK: + if (isJavaLink) + { + printf("Error: {@link.. ended with @endlink command at line %d\n", + doctokenizerYYlineno); + } + goto endlink; + default: + printf("Error: Illegal command %s as part of a \\ref at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_WORD: + if (isJavaLink) // special case to detect closing } + { + QCString w = g_token->name; + uint l=w.length(); + int p; + if (w=="}") + { + goto endlink; + } + else if ((p=w.find('}'))!=-1) + { + m_children.append(new DocWord(this,w.left(p))); + if ((uint)p<l-1) // something left after the } (for instance a .) + { + result=w.right(l-p-1); + } + goto endlink; + } + } + m_children.append(new DocWord(this,g_token->name)); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok==0) + { + printf("Error: Unexpected end of comment at line %d while inside" + " link command\n",doctokenizerYYlineno); + } +endlink: + + handlePendingStyleCommands(this,m_children); + DBG(("DocLink::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return result; +} + + +//--------------------------------------------------------------------------- + +void DocDotFile::parse() +{ + g_nodeStack.push(this); + DBG(("DocDotFile::parse() start\n")); + + doctokenizerYYsetStateTitle(); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a \\dotfile at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + doctokenizerYYsetStatePara(); + + handlePendingStyleCommands(this,m_children); + DBG(("DocDotFile::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); +} + + +//--------------------------------------------------------------------------- + +void DocImage::parse() +{ + g_nodeStack.push(this); + DBG(("DocImage::parse() start\n")); + + doctokenizerYYsetStateTitle(); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a \\image at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + doctokenizerYYsetStatePara(); + + handlePendingStyleCommands(this,m_children); + DBG(("DocImage::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); +} + + +//--------------------------------------------------------------------------- + +int DocHtmlHeader::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlHeader::parse() start\n")); + + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a <h%d> tag at line %d\n", + g_token->name.data(),m_level,doctokenizerYYlineno); + break; + case TK_HTMLTAG: + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_H1 && g_token->endTag) // found </h1> tag + { + if (m_level!=1) + { + printf("Error: <h%d> ended with </h1> at line %d\n", + m_level,doctokenizerYYlineno); + } + goto endheader; + } + else if (tagId==HTML_H2 && g_token->endTag) // found </h2> tag + { + if (m_level!=2) + { + printf("Error: <h%d> ended with </h2> at line %d\n", + m_level,doctokenizerYYlineno); + } + goto endheader; + } + else if (tagId==HTML_H3 && g_token->endTag) // found </h3> tag + { + if (m_level!=3) + { + printf("Error: <h%d> ended with </h3> at line %d\n", + m_level,doctokenizerYYlineno); + } + goto endheader; + } + else + { + printf("Error: Unexpected html tag <%s%s> found at line %d within <h%d> context\n", + g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno,m_level); + } + } + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok==0) + { + printf("Error: Unexpected end of comment at line %d while inside" + " <h%d> tag\n",doctokenizerYYlineno,m_level); + } +endheader: + handlePendingStyleCommands(this,m_children); + DBG(("DocHtmlHeader::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHRef::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHRef::parse() start\n")); + + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a <a>..</a> block at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_HTMLTAG: + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_A && g_token->endTag) // found </a> tag + { + goto endhref; + } + else + { + printf("Error: Unexpected html tag <%s%s> found at line %d within <a href=...> context\n", + g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno); + } + } + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok==0) + { + printf("Error: Unexpected end of comment at line %d while inside" + " <a href=...> tag\n",doctokenizerYYlineno); + } +endhref: + handlePendingStyleCommands(this,m_children); + DBG(("DocHRef::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocInternal::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocInternal::parse() start\n")); + + // first parse any number of paragraphs + do + { + DocPara *par = new DocPara(this); + retval=par->parse(); + if (!par->isEmpty()) m_children.append(par); + if (retval==TK_LISTITEM) + { + printf("Error: Invalid list item found at line %d!\n",doctokenizerYYlineno); + } + } while (retval!=0 && retval!=RetVal_Section); + + // then parse any number of level1 sections + while (retval==RetVal_Section) + { + SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + int secLev = sec->type==SectionInfo::Subsection ? 2 : 1; + if (secLev!=1) // wrong level + { + printf("Error: Expected level 1 section, found a section with level %d at line %d.\n",secLev,doctokenizerYYlineno); + break; + } + else + { + DocSection *s=new DocSection(this,secLev,g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + } + + if (retval==RetVal_Internal) + { + printf("Error: \\internal command found inside internal section\n"); + } + + DBG(("DocInternal::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocIndexEntry::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocIndexEntry::parse() start\n")); + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after \\addindex command at line %d\n", + doctokenizerYYlineno); + goto endindexentry; + } + while ((tok=doctokenizerYYlex()) && tok!=TK_WHITESPACE && tok!=TK_NEWPARA) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a \\addindex at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok!=TK_WHITESPACE) retval=tok; +endindexentry: + handlePendingStyleCommands(this,m_children); + DBG(("DocIndexEntry::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlCaption::parse() +{ + int retval=0; + g_nodeStack.push(this); + DBG(("DocHtmlCaption::parse() start\n")); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a <caption> tag at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_HTMLTAG: + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_CAPTION && g_token->endTag) // found </caption> tag + { + retval = RetVal_OK; + goto endcaption; + } + else + { + printf("Error: Unexpected html tag <%s%s> found at line %d within <caption> context\n", + g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno); + } + } + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok==0) + { + printf("Error: Unexpected end of comment at line %d while inside" + " <caption> tag\n",doctokenizerYYlineno); + } +endcaption: + handlePendingStyleCommands(this,m_children); + DBG(("DocHtmlCaption::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlCell::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlCell::parse() start\n")); + + // parse one or more paragraphs + do + { + DocPara *par = new DocPara(this); + m_children.append(par); + retval=par->parse(); + } + while (retval==TK_NEWPARA); + + DBG(("DocHtmlCell::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlRow::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlRow::parse() start\n")); + + bool isHeading=FALSE; + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_TD && !g_token->endTag) // found <td> tag + { + } + else if (tagId==HTML_TH && !g_token->endTag) // found <th> tag + { + isHeading=TRUE; + } + else // found some other tag + { + printf("Error: expected <td> or <th> tag at line %d but " + "found <%s> instead!\n",doctokenizerYYlineno,g_token->name.data()); + goto endrow; + } + } + else if (tok==0) // premature end of comment + { + printf("Error: unexpected end of comment at line %d while looking" + " for a html description title\n",doctokenizerYYlineno); + goto endrow; + } + else // token other than html token + { + printf("Error: expected <td> or <th> tag at line %d but found %s token instead!\n", + doctokenizerYYlineno,tokToString(tok)); + goto endrow; + } + + // parse one or more cells + do + { + DocHtmlCell *td=new DocHtmlCell(this,isHeading); + m_children.append(td); + retval=td->parse(); + isHeading = retval==RetVal_TableHCell; + } + while (retval==RetVal_TableCell || retval==RetVal_TableHCell); + +endrow: + DBG(("DocHtmlRow::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlTable::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlTable::parse() start\n")); + +getrow: + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_TR && !g_token->endTag) // found <tr> tag + { + // no caption, just rows + retval=RetVal_TableRow; + } + else if (tagId==HTML_CAPTION && !g_token->endTag) // found <caption> tag + { + if (m_caption) + { + printf("Error: table already has a caption, found another one at line %d\n", + doctokenizerYYlineno); + } + else + { + m_caption = new DocHtmlCaption(this); + retval=m_caption->parse(); + + if (retval==RetVal_OK) // caption was parsed ok + { + goto getrow; + } + } + } + else // found wrong token + { + printf("Error: expected <tr> or <caption> tag at line %d but " + "found <%s%s> instead!\n",doctokenizerYYlineno, + g_token->endTag ? "/" : "", g_token->name.data()); + } + } + else if (tok==0) // premature end of comment + { + printf("Error: unexpected end of comment at line %d while looking" + " for a <tr> or <caption> tag\n",doctokenizerYYlineno); + } + else // token other than html token + { + printf("Error: expected <tr> tag at line %d but found %s token instead!\n", + doctokenizerYYlineno,tokToString(tok)); + } + + // parse one or more rows + while (retval==RetVal_TableRow) + { + DocHtmlRow *tr=new DocHtmlRow(this); + m_children.append(tr); + retval=tr->parse(); + } + + DBG(("DocHtmlTable::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval==RetVal_EndTable ? RetVal_OK : retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlDescTitle::parse() +{ + int retval=0; + g_nodeStack.push(this); + DBG(("DocHtmlDescTitle::parse() start\n")); + + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a <dt> tag at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_HTMLTAG: + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_DD && !g_token->endTag) // found <dd> tag + { + retval = RetVal_DescData; + goto endtitle; + } + else if (tagId==HTML_DT && g_token->endTag) + { + // ignore </dt> tag. + } + else + { + printf("Error: Unexpected html tag <%s%s> found at line %d within <dt> context\n", + g_token->endTag?"/":"",g_token->name.data(),doctokenizerYYlineno); + } + } + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + if (tok==0) + { + printf("Error: Unexpected end of comment at line %d while inside" + " <dt> tag\n",doctokenizerYYlineno); + } +endtitle: + handlePendingStyleCommands(this,m_children); + DBG(("DocHtmlDescTitle::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlDescData::parse() +{ + int retval=0; + g_nodeStack.push(this); + DBG(("DocHtmlDescData::parse() start\n")); + + do + { + DocPara *par = new DocPara(this); + m_children.append(par); + retval=par->parse(); + } + while (retval==TK_NEWPARA); + + DBG(("DocHtmlDescData::parse() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlDescList::parse() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlDescList::parse() start\n")); + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_DT && !g_token->endTag) // found <dt> tag + { + // continue + } + else // found some other tag + { + printf("Error: expected <dt> tag at line %d but " + "found <%s> instead!\n",doctokenizerYYlineno,g_token->name.data()); + goto enddesclist; + } + } + else if (tok==0) // premature end of comment + { + printf("Error: unexpected end of comment at line %d while looking" + " for a html description title\n",doctokenizerYYlineno); + goto enddesclist; + } + else // token other than html token + { + printf("Error: expected <dt> tag at line %d but found %s token instead!\n", + doctokenizerYYlineno,tokToString(tok)); + goto enddesclist; + } + + do + { + DocHtmlDescTitle *dt=new DocHtmlDescTitle(this); + m_children.append(dt); + DocHtmlDescData *dd=new DocHtmlDescData(this); + m_children.append(dd); + retval=dt->parse(); + if (retval==RetVal_DescData) + { + retval=dd->parse(); + } + else + { + // error + break; + } + } while (retval==RetVal_DescTitle); + + if (retval==0) + { + printf("Error: unexpected end of comment at line %d while inside <dl> block\n", + doctokenizerYYlineno); + } + +enddesclist: + + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + DBG(("DocHtmlDescList::parse() end\n")); + return retval==RetVal_EndDesc ? RetVal_OK : retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlPre::parse() +{ + int rv; + g_nodeStack.push(this); + + do + { + DocPara *par = new DocPara(this); + m_children.append(par); + rv=par->parse(); + } + while (rv==TK_NEWPARA); + + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return rv==RetVal_EndPre ? RetVal_OK : rv; +} + +//--------------------------------------------------------------------------- + +int DocHtmlListItem::parse() +{ + DBG(("DocHtmlListItem::parse() start\n")); + int retval=0; + g_nodeStack.push(this); + + // parse one or more paragraphs + do + { + DocPara *par = new DocPara(this); + m_children.append(par); + retval=par->parse(); + } + while (retval==TK_NEWPARA); + + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + DBG(("DocHtmlListItem::parse() end retval=%x\n",retval)); + return retval; +} + +//--------------------------------------------------------------------------- + +int DocHtmlList::parse() +{ + DBG(("DocHtmlList::parse() start\n")); + int retval=RetVal_OK; + g_nodeStack.push(this); + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=HtmlTagMapper::map(g_token->name); + if (tagId==HTML_LI && !g_token->endTag) // found <li> tag + { + // ok, we can go on. + } + else // found some other tag + { + printf("Error: expected <li> tag at line %d but " + "found <%s> instead!\n",doctokenizerYYlineno,g_token->name.data()); + goto endlist; + } + } + else if (tok==0) // premature end of comment + { + printf("Error: unexpected end of comment at line %d while looking" + " for a html list item\n",doctokenizerYYlineno); + goto endlist; + } + else // token other than html token + { + printf("Error: expected <li> tag at line %d but found %s token instead!\n", + doctokenizerYYlineno,tokToString(tok)); + goto endlist; + } + + do + { + DocHtmlListItem *li=new DocHtmlListItem(this); + m_children.append(li); + retval=li->parse(); + } while (retval==RetVal_ListItem); + + if (retval==0) + { + printf("Error: unexpected end of comment at line %d while inside <%cl> block\n", + doctokenizerYYlineno,m_type==Unordered ? 'u' : 'o'); + } + +endlist: + DBG(("DocHtmlList::parse() end retval=%x\n",retval)); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval==RetVal_EndList ? RetVal_OK : retval; +} + +//--------------------------------------------------------------------------- + +int DocSimpleListItem::parse() +{ + g_nodeStack.push(this); + int rv=m_paragraph->parse(); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return rv; +} + +//-------------------------------------------------------------------------- + +int DocSimpleList::parse() +{ + g_nodeStack.push(this); + int rv; + do + { + DocSimpleListItem *li=new DocSimpleListItem(this); + m_children.append(li); + rv=li->parse(); + } while (rv==RetVal_ListItem); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return (rv!=TK_NEWPARA) ? rv : RetVal_OK; +} + +//-------------------------------------------------------------------------- + +int DocAutoListItem::parse() +{ + int retval = RetVal_OK; + g_nodeStack.push(this); + retval=m_paragraph->parse(); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//-------------------------------------------------------------------------- + +int DocAutoList::parse() +{ + int retval = RetVal_OK; + g_nodeStack.push(this); + // first item or sub list => create new list + do + { + DocAutoListItem *li = new DocAutoListItem(this); + m_children.append(li); + retval=li->parse(); + } + while (retval==TK_LISTITEM && // new list item + m_indent==g_token->indent && // at same indent level + m_isEnumList==g_token->isEnumList // of the same kind + ); + + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//-------------------------------------------------------------------------- + +void DocTitle::parse() +{ + DBG(("DocTitle::parse() start\n")); + g_nodeStack.push(this); + doctokenizerYYsetStateTitle(); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command %s as part of a title section at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + doctokenizerYYsetStatePara(); + handlePendingStyleCommands(this,m_children); + DBG(("DocTitle::parse() end\n")); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); +} + +//-------------------------------------------------------------------------- + +DocSimpleSect::DocSimpleSect(DocNode *parent,Type t) : + m_parent(parent), m_type(t) +{ + m_paragraph = new DocPara(this); + //m_params.setAutoDelete(TRUE); + m_title = 0; +} + +DocSimpleSect::~DocSimpleSect() +{ + delete m_paragraph; + delete m_title; +} + +void DocSimpleSect::accept(DocVisitor *v) +{ + v->visitPre(this); + if (m_title) m_title->accept(v); + m_paragraph->accept(v); + v->visitPost(this); +} + +int DocSimpleSect::parse(bool userTitle) +{ + DBG(("DocSimpleSect::parse() start\n")); + g_nodeStack.push(this); + + // handle case for user defined title + if (userTitle) + { + m_title = new DocTitle(this); + m_title->parse(); + } + + int retval = m_paragraph->parse(); + + DBG(("DocSimpleSect::parse() end retval=%d\n",retval)); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); + return retval; // 0==EOF, TK_NEWPARA, TK_LISTITEM, TK_ENDLIST, RetVal_SimpleSec +} + +void DocSimpleSect::addParam(const QCString &name) +{ + m_params.append(name); +} + +//-------------------------------------------------------------------------- + +int DocPara::handleSimpleSection(DocSimpleSect::Type t) +{ + DocSimpleSect *ss=new DocSimpleSect(this,t); + m_children.append(ss); + int rv = ss->parse(t==DocSimpleSect::User); + return (rv!=TK_NEWPARA) ? rv : RetVal_OK; +} + +int DocPara::handleParamSection(const QCString &cmdName,DocSimpleSect::Type t) +{ + int tok=doctokenizerYYlex(); + DocSimpleSect *ss=new DocSimpleSect(this,t); + m_children.append(ss); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + } + doctokenizerYYsetStateParam(); + tok=doctokenizerYYlex(); + doctokenizerYYsetStatePara(); + while (tok==TK_WORD) /* there is a parameter name */ + { + ss->addParam(g_token->name); + tok=doctokenizerYYlex(); + } + if (tok==0) /* premature end of comment block */ + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + return 0; + } + ASSERT(tok==TK_WHITESPACE); + int rv = ss->parse(FALSE); + return (rv!=TK_NEWPARA) ? rv : RetVal_OK; +} + +#if 0 +int DocPara::handleStyleArgument(const QCString &cmdName) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + while ((tok=doctokenizerYYlex()) && tok!=TK_WHITESPACE && tok!=TK_NEWPARA) + { + if (!defaultHandleToken(this,tok,m_children)) + { + switch (tok) + { + case TK_COMMAND: + printf("Error: Illegal command \\%s as the argument of a \\%s command at line %d\n", + g_token->name.data(),cmdName.data(),doctokenizerYYlineno); + break; + case TK_SYMBOL: + printf("Error: Unsupported symbol %s found at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + default: + printf("Error: Unexpected token %s at line %d\n", + g_token->name.data(),doctokenizerYYlineno); + break; + } + } + } + return tok==TK_NEWPARA ? TK_NEWPARA : RetVal_OK; +} + +void DocPara::handleStyleEnter(DocStyleChange::Style s) +{ + DBG(("HandleStyleEnter\n")); + DocStyleChange *sc= new DocStyleChange(this,g_nodeStack.count(),s,TRUE); + m_children.append(sc); + g_styleStack.push(sc); +} + +void DocPara::handleStyleLeave(DocStyleChange::Style s,const char *tagName) +{ + DBG(("HandleStyleLeave\n")); + if (g_styleStack.isEmpty() || // no style change + g_styleStack.top()->style()!=s || // wrong style change + g_styleStack.top()->position()!=g_nodeStack.count() // wrong position + ) + { + printf("Error: found </%s> tag at line %d without matching <%s> in the same paragraph\n", + tagName,doctokenizerYYlineno,tagName); + } + else // end the section + { + DocStyleChange *sc= new DocStyleChange(this,g_nodeStack.count(),s,FALSE); + m_children.append(sc); + g_styleStack.pop(); + } +} +#endif + +int DocPara::handleXRefItem(DocXRefItem::Type t) +{ + int retval=doctokenizerYYlex(); + ASSERT(retval==TK_WHITESPACE); + doctokenizerYYsetStateXRefItem(); + retval=doctokenizerYYlex(); + if (retval!=0) + { + m_children.append(new DocXRefItem(this,g_token->id,t)); + } + doctokenizerYYsetStatePara(); + return retval; +} + +void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStatePattern(); + tok=doctokenizerYYlex(); + doctokenizerYYsetStatePara(); + if (tok==0) + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + return; + } + else if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + DocIncOperator *op = new DocIncOperator(this,t,g_token->name); + m_children.append(op); +} + +void DocPara::handleImage(const QCString &cmdName) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + tok=doctokenizerYYlex(); + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + DocImage::Type t; + QCString imgType = g_token->name.lower(); + if (imgType=="html") t=DocImage::Html; + else if (imgType=="latex") t=DocImage::Latex; + else if (imgType=="rtf") t=DocImage::Rtf; + else + { + printf("Error: image type %s specified as the first argument of " + "%s at line %d is not valid.\n", + imgType.data(),cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStateFile(); + tok=doctokenizerYYlex(); + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStatePara(); + DocImage *img = new DocImage(this,g_token->name,t); + m_children.append(img); + img->parse(); +} + +void DocPara::handleDotFile(const QCString &cmdName) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStateFile(); + tok=doctokenizerYYlex(); + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStatePara(); + DocDotFile *df = new DocDotFile(this,g_token->name); + m_children.append(df); + df->parse(); +} + +void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStateLink(); + tok=doctokenizerYYlex(); + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStatePara(); + DocLink *lnk = new DocLink(this,g_token->name); + m_children.append(lnk); + QCString leftOver = lnk->parse(isJavaLink); + if (!leftOver.isEmpty()) + { + m_children.append(new DocWord(this,leftOver)); + } +} + +void DocPara::handleRef(const QCString &cmdName) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStateRef(); + tok=doctokenizerYYlex(); // get the reference id + DocRef *ref=0; + if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + goto endref; + } + ref = new DocRef(this,g_token->name); + m_children.append(ref); + ref->parse(); +endref: + doctokenizerYYsetStatePara(); +} + + +int DocPara::handleLanguageSwitch() +{ + int retval=RetVal_OK; + + if (!insideLang(this)) // start a language section at this level + { + do + { + int tok = doctokenizerYYlex(); + if (tok==TK_WHITESPACE) + { + // end of language specific sections + retval=RetVal_OK; + goto endlang; + } + else if (tok==TK_NEWPARA) + { + // end of language specific sections + retval = tok; + goto endlang; + } + else if (tok==TK_WORD) + { + DocLanguage *dl = new DocLanguage(this,g_token->name); + m_children.append(dl); + retval = dl->parse(); + } + else + { + printf("Error: Unexpected token %s as parameter of \\~ at line %d\n", + tokToString(tok),doctokenizerYYlineno); + goto endlang; + } + } + while (retval==RetVal_SwitchLang); + } + else // return from this section + { + retval = RetVal_SwitchLang; + } +endlang: + return retval; +} + +void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) +{ + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + return; + } + doctokenizerYYsetStateFile(); + tok=doctokenizerYYlex(); + doctokenizerYYsetStatePara(); + if (tok==0) + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + return; + } + else if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + return; + } + DocInclude *inc = new DocInclude(this,g_token->name,t); + m_children.append(inc); +} + + +int DocPara::handleCommand(const QCString &cmdName) +{ + int retval = RetVal_OK; + switch (CmdMapper::map(cmdName)) + { + case CMD_UNKNOWN: + printf("Error: Found unknown command `\\%s' at line %d\n",cmdName.data(),doctokenizerYYlineno); + break; + case CMD_EMPHASIS: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,TRUE)); + retval=handleStyleArgument(this,m_children,cmdName); + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,FALSE)); + break; + case CMD_BOLD: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); + retval=handleStyleArgument(this,m_children,cmdName); + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); + break; + case CMD_CODE: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,TRUE)); + retval=handleStyleArgument(this,m_children,cmdName); + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Code,FALSE)); + break; + case CMD_BSLASH: + m_children.append(new DocSymbol(this,DocSymbol::BSlash)); + break; + case CMD_AT: + m_children.append(new DocSymbol(this,DocSymbol::At)); + break; + case CMD_LESS: + m_children.append(new DocSymbol(this,DocSymbol::Less)); + break; + case CMD_GREATER: + m_children.append(new DocSymbol(this,DocSymbol::Greater)); + break; + case CMD_AMP: + m_children.append(new DocSymbol(this,DocSymbol::Amp)); + break; + case CMD_DOLLAR: + m_children.append(new DocSymbol(this,DocSymbol::Dollar)); + break; + case CMD_HASH: + m_children.append(new DocSymbol(this,DocSymbol::Hash)); + break; + case CMD_PERCENT: + m_children.append(new DocSymbol(this,DocSymbol::Percent)); + break; + case CMD_SA: + retval = handleSimpleSection(DocSimpleSect::See); + break; + case CMD_RETURN: + retval = handleSimpleSection(DocSimpleSect::Return); + break; + case CMD_AUTHOR: + retval = handleSimpleSection(DocSimpleSect::Author); + break; + case CMD_VERSION: + retval = handleSimpleSection(DocSimpleSect::Version); + break; + case CMD_SINCE: + retval = handleSimpleSection(DocSimpleSect::Since); + break; + case CMD_DATE: + retval = handleSimpleSection(DocSimpleSect::Date); + break; + case CMD_NOTE: + retval = handleSimpleSection(DocSimpleSect::Note); + break; + case CMD_WARNING: + retval = handleSimpleSection(DocSimpleSect::Warning); + break; + case CMD_PRE: + retval = handleSimpleSection(DocSimpleSect::Pre); + break; + case CMD_POST: + retval = handleSimpleSection(DocSimpleSect::Post); + break; + case CMD_INVARIANT: + retval = handleSimpleSection(DocSimpleSect::Invar); + break; + case CMD_REMARK: + retval = handleSimpleSection(DocSimpleSect::Remark); + break; + case CMD_ATTENTION: + retval = handleSimpleSection(DocSimpleSect::Attention); + break; + case CMD_PAR: + retval = handleSimpleSection(DocSimpleSect::User); + break; + case CMD_LI: + { + DocSimpleList *sl=new DocSimpleList(this); + m_children.append(sl); + retval = sl->parse(); + } + break; + case CMD_SECTION: + { + // get the argument of the section command. + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + break; + } + tok=doctokenizerYYlex(); + if (tok==0) + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + break; + } + else if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + break; + } + g_token->sectionId = g_token->name; + retval = RetVal_Section; + } + break; + case CMD_STARTCODE: + { + doctokenizerYYsetStateCode(); + retval = doctokenizerYYlex(); + m_children.append(new DocVerbatim(this,g_token->verb,DocVerbatim::Code)); + if (retval==0) printf("Error: code section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_HTMLONLY: + { + doctokenizerYYsetStateHtmlOnly(); + retval = doctokenizerYYlex(); + m_children.append(new DocVerbatim(this,g_token->verb,DocVerbatim::HtmlOnly)); + if (retval==0) printf("Error: htmlonly section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_LATEXONLY: + { + doctokenizerYYsetStateLatexOnly(); + retval = doctokenizerYYlex(); + m_children.append(new DocVerbatim(this,g_token->verb,DocVerbatim::LatexOnly)); + if (retval==0) printf("Error: latexonly section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_VERBATIM: + { + doctokenizerYYsetStateVerbatim(); + retval = doctokenizerYYlex(); + m_children.append(new DocVerbatim(this,g_token->verb,DocVerbatim::Verbatim)); + if (retval==0) printf("Error: verbatim section ended without end marker at line %d\n", + doctokenizerYYlineno); + doctokenizerYYsetStatePara(); + } + break; + case CMD_ENDCODE: + case CMD_ENDHTMLONLY: + case CMD_ENDLATEXONLY: + case CMD_ENDLINK: + case CMD_ENDVERBATIM: + printf("Error: unexpected command %s at line %d\n",g_token->name.data(),doctokenizerYYlineno); + break; + case CMD_PARAM: + retval = handleParamSection(cmdName,DocSimpleSect::Param); + break; + case CMD_RETVAL: + retval = handleParamSection(cmdName,DocSimpleSect::RetVal); + break; + case CMD_EXCEPTION: + retval = handleParamSection(cmdName,DocSimpleSect::Exception); + break; + case CMD_BUG: + retval = handleXRefItem(DocXRefItem::Bug); + break; + case CMD_TODO: + retval = handleXRefItem(DocXRefItem::Todo); + break; + case CMD_TEST: + retval = handleXRefItem(DocXRefItem::Test); + break; + case CMD_DEPRECATED: + retval = handleXRefItem(DocXRefItem::Deprecated); + break; + case CMD_LINEBREAK: + { + DocLineBreak *lb = new DocLineBreak(this); + m_children.append(lb); + } + break; + case CMD_ANCHOR: + { + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + break; + } + tok=doctokenizerYYlex(); + if (tok==0) + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + break; + } + else if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + break; + } + DocAnchor *anchor = new DocAnchor(this,g_token->name); + m_children.append(anchor); + } + break; + case CMD_ADDINDEX: + { + DocIndexEntry *ie = new DocIndexEntry(this); + m_children.append(ie); + retval = ie->parse(); + } + break; + case CMD_INTERNAL: + retval = RetVal_Internal; + break; + case CMD_COPYDOC: + { + int tok=doctokenizerYYlex(); + if (tok!=TK_WHITESPACE) + { + printf("Error: expected whitespace after %s command at line %d\n", + cmdName.data(),doctokenizerYYlineno); + break; + } + tok=doctokenizerYYlex(); + if (tok==0) + { + printf("Error: unexpected end of comment block at line %d while parsing the " + "argument of command %s\n",doctokenizerYYlineno, cmdName.data()); + break; + } + else if (tok!=TK_WORD) + { + printf("Error: unexpected token %s as the argument of %s at line %d.\n", + tokToString(tok),cmdName.data(),doctokenizerYYlineno); + break; + } + DocCopy *cpy = new DocCopy(this,g_token->name); + m_children.append(cpy); + } + break; + case CMD_INCLUDE: + handleInclude(cmdName,DocInclude::Include); + break; + case CMD_DONTINCLUDE: + handleInclude(cmdName,DocInclude::DontInclude); + break; + case CMD_HTMLINCLUDE: + handleInclude(cmdName,DocInclude::HtmlInclude); + break; + case CMD_VERBINCLUDE: + handleInclude(cmdName,DocInclude::VerbInclude); + break; + case CMD_SKIP: + handleIncludeOperator(cmdName,DocIncOperator::Skip); + break; + case CMD_UNTIL: + handleIncludeOperator(cmdName,DocIncOperator::Until); + break; + case CMD_SKIPLINE: + handleIncludeOperator(cmdName,DocIncOperator::SkipLine); + break; + case CMD_LINE: + handleIncludeOperator(cmdName,DocIncOperator::Line); + break; + case CMD_IMAGE: + handleImage(cmdName); + break; + case CMD_DOTFILE: + handleDotFile(cmdName); + break; + case CMD_LINK: + handleLink(cmdName,FALSE); + break; + case CMD_JAVALINK: + handleLink(cmdName,TRUE); + break; + case CMD_REF: + handleRef(cmdName); + break; + case CMD_SECREFLIST: + { + DocSecRefList *list = new DocSecRefList(this); + m_children.append(list); + list->parse(); + } + break; + case CMD_SECREFITEM: + printf("Error: unexpected command %s at line %d\n",g_token->name.data(),doctokenizerYYlineno); + break; + case CMD_ENDSECREFLIST: + printf("Error: unexpected command %s at line %d\n",g_token->name.data(),doctokenizerYYlineno); + break; + case CMD_FORMULA: + { + DocFormula *form=new DocFormula(this,g_token->id); + m_children.append(form); + } + break; + case CMD_LANGSWITCH: + retval = handleLanguageSwitch(); + break; + default: + // we should not get here! + ASSERT(0); + break; + } + ASSERT(retval==0 || retval==RetVal_OK || retval==RetVal_SimpleSec || + retval==TK_LISTITEM || retval==TK_ENDLIST || retval==TK_NEWPARA || + retval==RetVal_Section || retval==RetVal_EndList || + retval==RetVal_Internal || retval==RetVal_SwitchLang + ); + return retval; +} + +#if 0 +void DocPara::handlePendingStyleCommands() +{ + if (!g_styleStack.isEmpty()) + { + DocStyleChange *sc = g_styleStack.top(); + while (sc && sc->position()>=g_nodeStack.count()) + { // there are unclosed style modifiers in the paragraph + const char *cmd; + switch (sc->style()) + { + case DocStyleChange::Bold: cmd = "b"; break; + case DocStyleChange::Italic: cmd = "em"; break; + case DocStyleChange::Code: cmd = "code"; break; + case DocStyleChange::Center: cmd = "center"; break; + case DocStyleChange::Small: cmd = "small"; break; + case DocStyleChange::Subscript: cmd = "subscript"; break; + case DocStyleChange::Superscript: cmd = "superscript"; break; + } + printf("Error: end of paragraph at line %d without end of style " + "command </%s>\n",doctokenizerYYlineno,cmd); + m_children.append(new DocStyleChange(this,g_nodeStack.count(),sc->style(),FALSE)); + g_styleStack.pop(); + sc = g_styleStack.top(); + } + } +} +#endif + +int DocPara::handleHtmlStartTag(const QCString &tagName,const QList<Option> &tagOptions) +{ + DBG(("handleHtmlStartTag(%s,%d)\n",tagName.data(),tagOptions.count())); + int retval=RetVal_OK; + int tagId = HtmlTagMapper::map(tagName); + switch (tagId) + { + case HTML_UL: + { + DocHtmlList *list = new DocHtmlList(this,DocHtmlList::Unordered); + m_children.append(list); + retval=list->parse(); + } + break; + case HTML_OL: + { + DocHtmlList *list = new DocHtmlList(this,DocHtmlList::Ordered); + m_children.append(list); + retval=list->parse(); + } + break; + case HTML_LI: + if (!insideUL(this) && !insideOL(this)) + { + printf("Error: lonely <li> tag found at line %d\n",doctokenizerYYlineno); + } + else + { + retval=RetVal_ListItem; + } + break; + case HTML_PRE: + { + DocHtmlPre *pre = new DocHtmlPre(this); + m_children.append(pre); + retval=pre->parse(); + } + break; + case HTML_BOLD: + handleStyleEnter(this,m_children,DocStyleChange::Bold); + break; + case HTML_CODE: + handleStyleEnter(this,m_children,DocStyleChange::Code); + break; + case HTML_EMPHASIS: + handleStyleEnter(this,m_children,DocStyleChange::Italic); + break; + case HTML_SUB: + handleStyleEnter(this,m_children,DocStyleChange::Subscript); + break; + case HTML_SUP: + handleStyleEnter(this,m_children,DocStyleChange::Superscript); + break; + case HTML_CENTER: + handleStyleEnter(this,m_children,DocStyleChange::Center); + break; + case HTML_SMALL: + handleStyleEnter(this,m_children,DocStyleChange::Small); + break; + case HTML_P: + retval=TK_NEWPARA; + break; + case HTML_DL: + { + DocHtmlDescList *list = new DocHtmlDescList(this); + m_children.append(list); + retval=list->parse(); + } + break; + case HTML_DT: + retval = RetVal_DescTitle; + break; + case HTML_DD: + printf("Error: Unexpected tag <dd> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_TABLE: + { + DocHtmlTable *table = new DocHtmlTable(this); + m_children.append(table); + retval=table->parse(); + } + break; + case HTML_TR: + retval = RetVal_TableRow; + break; + case HTML_TD: + retval = RetVal_TableCell; + break; + case HTML_TH: + retval = RetVal_TableHCell; + break; + case HTML_CAPTION: + printf("Error: Unexpected tag <caption> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_BR: + { + DocLineBreak *lb = new DocLineBreak(this); + m_children.append(lb); + } + break; + case HTML_HR: + { + DocHorRuler *hr = new DocHorRuler(this); + m_children.append(hr); + } + break; + case HTML_A: + { + QListIterator<Option> li(tagOptions); + Option *opt; + for (li.toFirst();(opt=li.current());++li) + { + if (opt->name=="name") // <a name=label> tag + { + if (!opt->value.isEmpty()) + { + DocAnchor *anc = new DocAnchor(this,opt->value); + m_children.append(anc); + break; // stop looking for other tag options + } + else + { + printf("Error: found <a> tag at line %d with name option but without value!\n", + doctokenizerYYlineno); + } + } + else if (opt->name=="href") // <a href=url>..</a> tag + { + DocHRef *href = new DocHRef(this,opt->value); + m_children.append(href); + retval = href->parse(); + break; + } + else // unsupport option for tag a + { + } + } + } + break; + case HTML_H1: + { + DocHtmlHeader *header = new DocHtmlHeader(this,1); + m_children.append(header); + retval = header->parse(); + } + break; + case HTML_H2: + { + DocHtmlHeader *header = new DocHtmlHeader(this,2); + m_children.append(header); + retval = header->parse(); + } + break; + case HTML_H3: + { + DocHtmlHeader *header = new DocHtmlHeader(this,3); + m_children.append(header); + retval = header->parse(); + } + break; + case HTML_IMG: + { + QListIterator<Option> li(tagOptions); + Option *opt; + for (li.toFirst();(opt=li.current());++li) + { + if (opt->name=="src" && !opt->value.isEmpty()) + { + DocImage *img = new DocImage(this,opt->value,DocImage::Html); + m_children.append(img); + } + } + } + break; + case HTML_UNKNOWN: + printf("Error: Unsupported html tag <%s> found at line %d\n", + tagName.data(), doctokenizerYYlineno); + break; + default: + // we should not get here! + ASSERT(0); + break; + } + return retval; +} + +int DocPara::handleHtmlEndTag(const QCString &tagName) +{ + DBG(("handleHtmlEndTag(%s)\n",tagName.data())); + int tagId = HtmlTagMapper::map(tagName); + int retval=RetVal_OK; + switch (tagId) + { + case HTML_UL: + if (!insideUL(this)) + { + printf("Error: found </ul> tag at line %d without matching <ul>\n", + doctokenizerYYlineno); + } + else + { + retval=RetVal_EndList; + } + break; + case HTML_OL: + if (!insideOL(this)) + { + printf("Error: found </ol> tag at line %d without matching <ol>\n", + doctokenizerYYlineno); + } + else + { + retval=RetVal_EndList; + } + break; + case HTML_LI: + if (!insideLI(this)) + { + printf("Error: found </li> tag at line %d without matching <li>\n", + doctokenizerYYlineno); + } + else + { + // ignore </li> tags + } + break; + case HTML_PRE: + if (!insidePRE(this)) + { + printf("Error: found </pre> tag at line %d without matching <pre>\n", + doctokenizerYYlineno); + } + else + { + retval=RetVal_EndPre; + } + break; + case HTML_BOLD: + handleStyleLeave(this,m_children,DocStyleChange::Bold,"b"); + break; + case HTML_CODE: + handleStyleLeave(this,m_children,DocStyleChange::Code,"code"); + break; + case HTML_EMPHASIS: + handleStyleLeave(this,m_children,DocStyleChange::Italic,"em"); + break; + case HTML_SUB: + handleStyleLeave(this,m_children,DocStyleChange::Subscript,"sub"); + break; + case HTML_SUP: + handleStyleLeave(this,m_children,DocStyleChange::Superscript,"sup"); + break; + case HTML_CENTER: + handleStyleLeave(this,m_children,DocStyleChange::Center,"center"); + break; + case HTML_SMALL: + handleStyleLeave(this,m_children,DocStyleChange::Small,"small"); + break; + case HTML_P: + // ignore </p> tag + break; + case HTML_DL: + retval=RetVal_EndDesc; + break; + case HTML_DT: + // ignore </dt> tag + break; + case HTML_DD: + // ignore </dd> tag + break; + case HTML_TABLE: + retval=RetVal_EndTable; + break; + case HTML_TR: + // ignore </tr> tag + break; + case HTML_TD: + // ignore </td> tag + break; + case HTML_TH: + // ignore </th> tag + break; + case HTML_CAPTION: + printf("Error: Unexpected tag </caption> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_BR: + printf("Error: Illegal </br> tag found\n"); + break; + case HTML_H1: + printf("Error: Unexpected tag </h1> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_H2: + printf("Error: Unexpected tag </h2> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_H3: + printf("Error: Unexpected tag </h3> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_IMG: + printf("Error: Unexpected tag </img> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_HR: + printf("Error: Unexpected tag </hr> found at line %d\n", + doctokenizerYYlineno); + break; + case HTML_A: + //printf("Error: Unexpected tag </a> found at line %d\n", + // doctokenizerYYlineno); + // ignore </a> tag (can be part of <a name=...></a> + break; + case HTML_UNKNOWN: + printf("Error: Unsupported html tag </%s> found at line %d\n", + tagName.data(), doctokenizerYYlineno); + break; + default: + // we should not get here! + ASSERT(0); + break; + } + return retval; +} + +int DocPara::parse() +{ + DBG(("DocPara::parse() start\n")); + g_nodeStack.push(this); + int tok; + int retval=0; + while ((tok=doctokenizerYYlex())) // get the next token + { +reparsetoken: + DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + if (tok==TK_WORD || tok==TK_SYMBOL || tok==TK_URL || + tok==TK_COMMAND || tok==TK_HTMLTAG + ) + { + DBG((" name=%s",g_token->name.data())); + } + DBG(("\n")); + switch(tok) + { + case TK_WORD: + m_children.append(new DocWord(this,g_token->name)); + break; + case TK_URL: + m_children.append(new DocURL(this,g_token->name)); + break; + case TK_WHITESPACE: + // prevent leading whitespace and collapse multiple whitespace areas + if (insidePRE(this) || // all whitespace is relavant + ( // keep only whitespace after words, URL or symbols + !m_children.isEmpty() && + ( + m_children.last()->kind()==DocNode::Kind_Word || + m_children.last()->kind()==DocNode::Kind_URL || + m_children.last()->kind()==DocNode::Kind_Symbol + ) + ) + ) + { + m_children.append(new DocWhiteSpace(this,g_token->chars)); + } + break; + case TK_LISTITEM: + { + DBG(("found list item at %d parent=%d\n",g_token->indent,parent()->kind())); + DocNode *n=parent(); + while (n && n->kind()!=DocNode::Kind_AutoList) n=n->parent(); + if (n) // we found an auto list up in the hierarchy + { + DocAutoList *al = (DocAutoList *)n; + DBG(("previous list item at %d\n",al->indent())); + if (al->indent()>=g_token->indent) + // new item at the same or lower indent level + { + retval=TK_LISTITEM; + goto endparagraph; + } + } + // first item or sub list => create new list + DocAutoList *al=0; + do + { + al = new DocAutoList(this,g_token->indent,g_token->isEnumList); + m_children.append(al); + retval = al->parse(); + } while (retval==TK_LISTITEM && // new list + al->indent()==g_token->indent // at some indent level + ); + + // check the return value + if (retval==RetVal_SimpleSec) // auto list ended due to simple section command + { + // Reparse the token that ended the section at this level, + // so a new simple section will be started at this level. + // This is the same as unputting the last read token and continuing. + g_token->name = g_token->simpleSectName; + tok = TK_COMMAND; + DBG(("reparsing command %s\n",g_token->name.data())); + goto reparsetoken; + } + else if (retval==TK_ENDLIST) + { + if (al->indent()>g_token->indent) // end list + { + goto endparagraph; + } + else // continue with current paragraph + { + } + } + else // paragraph ended due to TK_NEWPARA, TK_LISTITEM, or EOF + { + goto endparagraph; + } + } + break; + case TK_ENDLIST: + DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno)); + if (parent()->kind()==DocNode::Kind_AutoListItem) + { + ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList); + DocAutoList *al = (DocAutoList *)parent()->parent(); + if (al->indent()>=g_token->indent) + { + // end of list marker ends this paragraph + retval=TK_ENDLIST; + goto endparagraph; + } + else + { + printf("Error: End of list marker found at line %d " + "has invalid indent level ",doctokenizerYYlineno); + } + } + else + { + printf("Error: End of list marker found at line %d without any preceding " + "list items\n",doctokenizerYYlineno); + } + break; + case TK_COMMAND: + { + // see if we have to start a simple section + int cmd = CmdMapper::map(g_token->name); + DocNode *n=parent(); + while (n && n->kind()!=DocNode::Kind_SimpleSect) n=n->parent(); + if (cmd&SIMPLESECT_BIT) + { + if (n // already in a simple section + //|| // no section or root as parent + // (parent()->kind()!=DocNode::Kind_Root && + // parent()->kind()!=DocNode::Kind_Section + // ) + ) + { + // simple section cannot start in this paragraph, need + // to unwind the stack and remember the command. + g_token->simpleSectName = g_token->name.copy(); + retval=RetVal_SimpleSec; + goto endparagraph; + } + } + // see if we are in a simple list + n=parent(); + while (n && n->kind()!=DocNode::Kind_SimpleListItem) n=n->parent(); + if (n) + { + if (cmd==CMD_LI) + { + retval=RetVal_ListItem; + goto endparagraph; + } + } + + // handle the command + retval=handleCommand(g_token->name.copy()); + + // check the return value + if (retval==RetVal_SimpleSec) + { + // Reparse the token that ended the section at this level, + // so a new simple section will be started at this level. + // This is the same as unputting the last read token and continuing. + g_token->name = g_token->simpleSectName; + tok = TK_COMMAND; + DBG(("reparsing command %s\n",g_token->name.data())); + goto reparsetoken; + } + else if (retval==RetVal_OK) + { + // the command ended normally, keep scanner for new tokens. + retval = 0; + } + else // end of file, end of paragraph, start or end of section + // or some auto list marker + { + goto endparagraph; + } + } + break; + case TK_HTMLTAG: + { + if (!g_token->endTag) // found a start tag + { + retval = handleHtmlStartTag(g_token->name,g_token->options); + } + else // found an end tag + { + retval = handleHtmlEndTag(g_token->name); + } + if (retval==RetVal_OK) + { + // the command ended normally, keep scanner for new tokens. + retval = 0; + } + else + { + goto endparagraph; + } + } + break; + case TK_SYMBOL: + break; + case TK_NEWPARA: + retval=TK_NEWPARA; + goto endparagraph; + } + } +endparagraph: + handlePendingStyleCommands(this,m_children); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); + DBG(("DocPara::parse() end retval=%x\n",retval)); + ASSERT(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || + retval==TK_ENDLIST || retval>RetVal_OK + ); + + if (!(retval==0 || retval==TK_NEWPARA || retval==TK_LISTITEM || + retval==TK_ENDLIST || retval>RetVal_OK + )) printf("DocPara::parse: Error retval=%x unexpected at line %d!\n",retval,doctokenizerYYlineno); + return retval; +} + +//-------------------------------------------------------------------------- + +int DocSection::parse() +{ + DBG(("DocSection::parse() start %s\n",g_token->sectionId.data())); + int retval=RetVal_OK; + g_nodeStack.push(this); + + // first parse any number of paragraphs + do + { + DocPara *par = new DocPara(this); + retval=par->parse(); + if (!par->isEmpty()) m_children.append(par); + if (retval==TK_LISTITEM) + { + printf("Error: Invalid list item found at line %d!\n",doctokenizerYYlineno); + } + } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal); + + // then parse any number of nested sections + while (retval==RetVal_Section) // more sections follow + { + SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + int secLev = sec->type==SectionInfo::Subsection ? 2 : 1; + if (secLev==level()) // new section at same level + { + break; + } + if (secLev!=level()+1) // new section at wrong level + { + printf("Error: Expected level %d section, found a section " + "with level %d at line %d.\n",level()+1,secLev,doctokenizerYYlineno); + retval=0; // stop parsing any further. + break; + } + else // nested section + { + DocSection *s=new DocSection(this,secLev,g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + } + ASSERT(retval==0 || retval==RetVal_Section); + + DBG(("DocSection::parse() end\n")); + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + +//-------------------------------------------------------------------------- + +void DocRoot::parse() +{ + g_nodeStack.push(this); + doctokenizerYYsetStatePara(); + DocPara *par=0; + int retval=0; + + // first parse any number of paragraphs + do + { + par = new DocPara(this); + retval=par->parse(); + if (!par->isEmpty()) m_children.append(par); + if (retval==TK_LISTITEM) + { + printf("Error: Invalid list item found at line %d!\n",doctokenizerYYlineno); + } + } while (retval!=0 && retval!=RetVal_Section && retval!=RetVal_Internal); + + // then parse any number of level1 sections + while (retval==RetVal_Section) + { + SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + int secLev = sec->type==SectionInfo::Subsection ? 2 : 1; + if (secLev!=1) // wrong level + { + printf("Error: Expected level 1 section, found a section with level %d at line %d.\n",secLev,doctokenizerYYlineno); + break; + } + else + { + DocSection *s=new DocSection(this,secLev,g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + } + + if (retval==RetVal_Internal) + { + DocInternal *in = new DocInternal(this); + m_children.append(in); + retval = in->parse(); + } + + DocNode *n = g_nodeStack.pop(); + ASSERT(n==this); +} + +//-------------------------------------------------------------------------- + +void validatingParseDoc(const char *fileName,int startLine,const char *input) +{ + //printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input); + // + printf("========== validating %s at line %d\n",fileName,startLine); + g_token = new TokenInfo; + + doctokenizerYYlineno=startLine; + doctokenizerYYinit(input); + + // build abstract syntax tree + DocRoot *root = new DocRoot; + root->parse(); + + if (Debug::isFlagSet(Debug::PrintTree)) + { + // pretty print the result + PrintDocVisitor *v = new PrintDocVisitor; + root->accept(v); + } + + delete root; + + delete g_token; + + // TODO: These should be called at the end of the program. + //doctokenizerYYcleanup(); + //CmdMapper::freeInstance(); + //HtmlTagMapper::freeInstance(); +} + |