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 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | class Doc; |
24 | class DocPrivate; |
25 | class CodeMarker; |
26 | struct Macro; |
27 | |
28 | class DocParser |
29 | { |
30 | public: |
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 | |
46 | private: |
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 ¶meters); |
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 ¯o); |
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 ¯o); |
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 {}; |
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 | }; |
168 | QT_END_NAMESPACE |
169 | |
170 | #endif // DOCPARSER_H |
171 | |