summaryrefslogtreecommitdiff
path: root/src/docparser_p.h
blob: 9e985f5935b9923f633c592ad5b8a6ff830b284a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/******************************************************************************
 *
 * Copyright (C) 1997-2022 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.
 *
 */

#ifndef DOCPARSER_P_H
#define DOCPARSER_P_H

/** @file
 *  @brief Private header shared between docparser.cpp and docnode.cpp
 */

#include <cassert>
#include <stack>
#include <iterator>
#include <vector>
#include <deque>

#include "containers.h"
#include "docparser.h"
#include "docnode.h"
#include "doctokenizer.h"
#include "searchindex.h"

using DefinitionStack = std::vector<const Definition *>;
using DocNodeStack = std::stack<DocNodeVariant *>;

template<typename T, typename Container = std::deque<T>>
class IterableStack : public std::stack<T, Container>
{
    using std::stack<T, Container>::c;

public:

    // expose just the iterators of the underlying container
    auto begin() { return std::begin(c); }
    auto end() { return std::end(c); }

    auto begin() const { return std::begin(c); }
    auto end() const { return std::end(c); }
};
using DocStyleChangeStack = IterableStack<const DocNodeVariant *>;

/** Parser's context to store all global variables.
 */
struct DocParserContext
{
  const Definition *scope;
  QCString context;
  bool inSeeBlock;
  bool xmlComment;
  bool insideHtmlLink;
  DocNodeStack nodeStack;
  DocStyleChangeStack styleStack;
  DocStyleChangeStack initialStyleStack;
  DefinitionStack copyStack;
  QCString fileName;
  QCString relPath;

  bool         hasParamCommand;
  bool         hasReturnCommand;
  StringMultiSet retvalsFound;
  StringMultiSet paramsFound;
  const MemberDef *  memberDef;
  bool         isExample;
  QCString     exampleName;
  QCString     searchUrl;

  QCString includeFileName;
  QCString includeFileText;
  uint     includeFileOffset;
  uint     includeFileLength;
  int      includeFileLine;
  bool     includeFileShowLineNo;

  TokenInfo *token;
  int      lineNo;
  bool     markdownSupport;
};

class DocParser : public IDocParser
{
  public:
    ~DocParser();
    void pushContext();
    void popContext();
    void handleImg(DocNodeVariant *parent,DocNodeList &children,const HtmlAttribList &tagHtmlAttribs);
    int  internalValidatingParseDoc(DocNodeVariant *parent,DocNodeList &children,
                                    const QCString &doc);
    QCString processCopyDoc(const char *data,uint &len);
    QCString findAndCopyImage(const QCString &fileName,DocImage::Type type, bool doWarn = true);
    void checkArgumentName();
    void checkRetvalName();
    void checkUnOrMultipleDocumentedParams();
    bool findDocsForMemberOrCompound(const QCString &commandName,
                                     QCString *pDoc,
                                     QCString *pBrief,
                                     const Definition **pDef);
    bool defaultHandleToken(DocNodeVariant *parent,int tok,
                            DocNodeList &children,bool
                            handleWord=TRUE);
    void errorHandleDefaultToken(DocNodeVariant *parent,int tok,
                                 DocNodeList &children,const QCString &txt);
    void defaultHandleTitleAndSize(const int cmd, DocNodeVariant *parent,
                                   DocNodeList &children, QCString &width,QCString &height);
    int handleStyleArgument(DocNodeVariant *parent,DocNodeList &children,
                            const QCString &cmdName);
    void handleStyleEnter(DocNodeVariant *parent,DocNodeList &children, DocStyleChange::Style s,
                          const QCString &tagName,const HtmlAttribList *attribs);
    void handleStyleLeave(DocNodeVariant *parent,DocNodeList &children, DocStyleChange::Style s,
                          const QCString &tagName);
    void handlePendingStyleCommands(DocNodeVariant *parent,DocNodeList &children);
    void handleInitialStyleCommands(DocNodeVariant *parent,DocNodeList &children);
    int  handleAHref(DocNodeVariant *parent,DocNodeList &children,const HtmlAttribList &tagHtmlAttribs);
    void handleUnclosedStyleCommands();
    void handleLinkedWord(DocNodeVariant *parent,DocNodeList &children,bool ignoreAutoLinkFlag=FALSE);
    void handleParameterType(DocNodeVariant *parent,DocNodeList &children,const QCString &paramTypes);
    void handleInternalRef(DocNodeVariant *parent,DocNodeList &children);
    void handleAnchor(DocNodeVariant *parent,DocNodeList &children);
    void handleImage(DocNodeVariant *parent, DocNodeList &children);
    void readTextFileByName(const QCString &file,QCString &text);

    std::stack< DocParserContext > contextStack;
    DocParserContext               context;
    DocTokenizer                   tokenizer;
    SIDataCollection               searchData;
};

//---------------------------------------------------------------------------

class AutoNodeStack
{
  public:
    AutoNodeStack(DocParser *parser,DocNodeVariant* node)
      : m_parser(parser), m_node(node) { m_parser->context.nodeStack.push(node); }
   ~AutoNodeStack() {
#if defined(NDEBUG)
     (void)m_node;
     if (!m_parser->context.nodeStack.empty())
     {
       m_parser->context.nodeStack.pop(); // robust version that does not assert
     }
#else
     assert(m_parser->context.nodeStack.top()==m_node);
     m_parser->context.nodeStack.pop(); // error checking version
#endif
   }

  private:
   DocParser *m_parser;
   const DocNodeVariant *m_node;
};

inline bool isPreformatted(const DocNodeVariant *n)
{
  return std::visit([](auto &&x)->decltype(auto) { return x.isPreformatted(); }, *n);
}

/*! Returns TRUE iff node n is a child of a preformatted node */
inline bool insidePRE(const DocNodeVariant *n)
{
  while (n)
  {
    if (isPreformatted(n)) return TRUE;
    n=parent(n);
  }
  return FALSE;
}

/*! Returns TRUE iff node n is a child of a html list item node */
inline bool insideLI(const DocNodeVariant *n)
{
  while (n)
  {
    if (std::holds_alternative<DocHtmlListItem>(*n)) return TRUE;
    n=parent(n);
  }
  return FALSE;
}

//---------------------------------------------------------------------------

/*! Returns TRUE iff node n is a child of a unordered html list node */
inline bool insideUL(const DocNodeVariant *n)
{
  while (n)
  {
    if (std::holds_alternative<DocHtmlList>(*n) &&
        std::get<DocHtmlList>(*n).type()==DocHtmlList::Unordered)
    {
      return TRUE;
    }
    n=parent(n);
  }
  return FALSE;
}

//---------------------------------------------------------------------------

/*! Returns TRUE iff node n is a child of a ordered html list node */
inline bool insideOL(const DocNodeVariant *n)
{
  while (n)
  {
    if (std::holds_alternative<DocHtmlList>(*n) &&
        std::get<DocHtmlList>(*n).type()==DocHtmlList::Ordered)
    {
      return TRUE;
    }
    n=parent(n);
  }
  return FALSE;
}

//---------------------------------------------------------------------------

inline bool insideTable(const DocNodeVariant *n)
{
  while (n)
  {
    if (std::holds_alternative<DocHtmlTable>(*n)) return TRUE;
    n=parent(n);
  }
  return FALSE;
}

//---------------------------------------------------------------------------

inline bool insideDetails(const DocNodeVariant *n)
{
  while (n)
  {
    if (std::holds_alternative<DocHtmlDetails>(*n)) return TRUE;
    n=parent(n);
  }
  return FALSE;
}


#endif