1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3#ifndef DOCPARSER_H
4#define DOCPARSER_H
5
6#include "atom.h"
7#include "config.h"
8#include "docutilities.h"
9#include "location.h"
10#include "openedlist.h"
11#include "quoter.h"
12
13#include "filesystem/fileresolver.h"
14
15#include <QtCore/QCoreApplication>
16#include <QtCore/qglobalstatic.h>
17#include <QtCore/qhash.h>
18#include <QtCore/qstack.h>
19#include <QtCore/qstring.h>
20
21QT_BEGIN_NAMESPACE
22
23class Doc;
24class DocPrivate;
25class CodeMarker;
26struct Macro;
27
28class DocParser
29{
30public:
31 void parse(const QString &source, DocPrivate *docPrivate, const QSet<QString> &metaCommandSet,
32 const QSet<QString> &possibleTopics);
33
34 static void initialize(const Config &config, FileResolver& file_resolver);
35 static int endCmdFor(int cmd);
36 static QString cmdName(int cmd);
37 static QString endCmdName(int cmd);
38 static QString untabifyEtc(const QString &str);
39 static int indentLevel(const QString &str);
40 static QString dedent(int level, const QString &str);
41
42 static int s_tabSize;
43 static QStringList s_ignoreWords;
44 static bool s_quoting;
45
46private:
47 Location &location();
48 QString detailsUnknownCommand(const QSet<QString> &metaCommandSet, const QString &str);
49 void insertTarget(const QString &target);
50 void insertKeyword(const QString &keyword);
51 void include(const QString &fileName, const QString &identifier, const QStringList &parameters);
52 void startFormat(const QString &format, int cmd);
53 bool openCommand(int cmd);
54 bool closeCommand(int endCmd);
55 void startSection(Doc::Sections unit, int cmd);
56 void endSection(int unit, int endCmd);
57 void parseAlso();
58 void append(const QString &string);
59 void append(Atom::AtomType type, const QString &string = QString());
60 void append(Atom::AtomType type, const QString &p1, const QString &p2);
61 void append(const QString &p1, const QString &p2);
62 void appendChar(QChar ch);
63 void appendWord(const QString &word);
64 void appendToCode(const QString &code);
65 void appendToCode(const QString &code, Atom::AtomType defaultType);
66 void enterPara(Atom::AtomType leftType = Atom::ParaLeft,
67 Atom::AtomType rightType = Atom::ParaRight, const QString &string = QString());
68 void leavePara();
69 void leaveValue();
70 void leaveValueList();
71 void leaveTableRow();
72 void quoteFromFile(const QString& filename);
73 bool expandMacro();
74 void expandMacro(const QString &def, const QStringList &args);
75 QString expandMacroToString(const QString &name, const Macro &macro);
76 Doc::Sections getSectioningUnit();
77 QString getArgument(bool verbatim = false);
78 QString getBracedArgument(bool verbatim);
79 QString getBracketedArgument();
80 QStringList getMacroArguments(const QString &name, const Macro &macro);
81 QString getOptionalArgument();
82 QString getRestOfLine();
83 QString getMetaCommandArgument(const QString &cmdStr);
84 QString getUntilEnd(int cmd);
85 QString getCode(int cmd, CodeMarker *marker, const QString &argStr = QString());
86
87 inline bool isAutoLinkString(const QString &word);
88 bool isAutoLinkString(const QString &word, qsizetype &curPos);
89 bool isBlankLine();
90 bool isLeftBraceAhead();
91 bool isLeftBracketAhead();
92 void skipSpacesOnLine();
93 void skipSpacesOrOneEndl();
94 void skipAllSpaces();
95 void skipToNextPreprocessorCommand();
96 static bool isCode(const Atom *atom);
97 static bool isQuote(const Atom *atom);
98 static void expandArgumentsInString(QString &str, const QStringList &args);
99
100 QStack<qsizetype> m_openedInputs {};
101
102 QString m_input {};
103 qsizetype m_position {};
104 qsizetype m_backslashPosition {};
105 qsizetype m_endPosition {};
106 qsizetype m_inputLength {};
107 Location m_cachedLocation {};
108 qsizetype m_cachedPosition {};
109
110 DocPrivate *m_private { nullptr };
111 enum ParagraphState { OutsideParagraph, InSingleLineParagraph, InMultiLineParagraph };
112 ParagraphState m_paragraphState {};
113 bool m_inTableHeader {};
114 bool m_inTableRow {};
115 bool m_inTableItem {};
116 bool m_indexStartedParagraph {}; // ### rename
117 Atom::AtomType m_pendingParagraphLeftType {};
118 Atom::AtomType m_pendingParagraphRightType {};
119 QString m_pendingParagraphString {};
120
121 int m_braceDepth {};
122 Doc::Sections m_currentSection {};
123 QMap<QString, Location> m_targetMap {};
124 QMap<int, QString> m_pendingFormats {};
125 QStack<int> m_openedCommands {};
126 QStack<OpenedList> m_openedLists {};
127 Quoter m_quoter {};
128 Atom *m_lastAtom { nullptr };
129
130 static DocUtilities &s_utilities;
131
132 // KLUDGE: When parsing documentation, there is a need to find
133 // files to resolve quoting commands. Ideally, the system that
134 // takes care of this would be a non-static member that is a
135 // reference that is passed at
136 // construction time.
137 // Nonetheless, with how the current codebase is constructed, this
138 // has proven to be extremely difficult until more changes are
139 // done. In particular, the construction of a DocParser happens in
140 // multiple places at multiple depths and, in particular, happens
141 // in one of Doc's constructor.
142 // Doc itself is built, again, in multiple places at multiple
143 // depths, making it clumsy and sometimes infeasible to pass the
144 // dependency around so that it is available at the required
145 // places. In particular, this stems from the fact that Doc is
146 // holding many responsabilities and is spread troughtout much of
147 // the codebase in different ways. DocParser mostly depends on Doc
148 // and Doc currently depends on DocParser, making the two
149 // difficult to separate.
150 //
151 // In the future, we expect Doc to mostly be removed, such as to
152 // remove this dependencies and the parsing of documentation to
153 // happen near main and atomically from other endevours, producing
154 // an intermediate representation that is consumed by later
155 // phases.
156 // At that point, it should be possible to not have this kind of
157 // indirection while, for now, the only accessible way to pass
158 // this dependency is trough the initialize method which passes
159 // for Doc::initialize.
160 //
161 // Furthemore, as we cannot late-bind a reference, and having a
162 // desire to avoid an unnecessary copy, we are thus forced to use
163 // a different storage method, in this case a pointer.
164 // This too should be removed later on, using reference or move
165 // semantic depending on the required data-flow.
166 static FileResolver* file_resolver;
167};
168QT_END_NAMESPACE
169
170#endif // DOCPARSER_H
171

source code of qttools/src/qdoc/qdoc/docparser.h