15using TextProcessingTransition = TextProcessingMachine::Transition;
17using ChurningState = LexerObject<TextProcessingState, NullTest, MarksClearer>;
18using FinalizeTokenState = LexerObject<TextProcessingState, NullTest, TokenFinalizer>;
19using EofHandler = LexerObject<TextProcessingTransition, NullTest, TokenFinalizer>;
20using EofHandlerWithTrimming = LexerObject<TextProcessingTransition, NullTest, TokenFinalizerWithTrimming>;
22using MaybeTemplateSyntaxHandler = CharacterTransition<
'{'>;
24using TagStartHandler = CharacterTransition<
'%', MarkStartSyntax>;
25using CommentStartHandler = CharacterTransition<
'#', MarkStartSyntax>;
26using TagEndHandler = CharacterTransition<
'%'>;
27using CommentEndHandler = CharacterTransition<
'#'>;
28using BeginValueHandler = CharacterTransition<
'{', MarkStartSyntax>;
29using MaybeEndValueHandler = CharacterTransition<
'}'>;
30using NewlineHandler = CharacterTransition<
'\n', MarkNewline>;
31using EndTemplateSyntaxHandler = CharacterTransition<
'}', MarkEndSyntax>;
32using NotEndTemplateSyntaxHandler = NegateCharacterTransition<
'}'>;
34using NotBeginTemplateSyntaxHandler = LexerObject<TextProcessingTransition, Negate<OrTest<CharacterTest<
'{'>, OrTest<CharacterTest<
'#'>, CharacterTest<
'%'>>>>>;
36using NotBeginTemplateSyntaxOrNewlineHandler =
37 LexerObject<TextProcessingTransition, Negate<OrTest<CharacterTest<
'{'>, OrTest<CharacterTest<
'#'>, OrTest<CharacterTest<
'%'>, CharacterTest<
'\n'>>>>>>;
39using NotTagCommentOrNewlineHandler =
40 LexerObject<TextProcessingTransition, Negate<OrTest<CharacterTest<
'#'>, OrTest<CharacterTest<
'%'>, CharacterTest<
'\n'>>>>>;
42using NonWhitespaceLineTextHandler = LexerObject<TextProcessingTransition, Negate<OrTest<IsSpace, CharacterTest<
'{'>>>>;
44using WhitespaceNonNewlineHandler = LexerObject<TextProcessingTransition, AndTest<Negate<CharacterTest<
'\n'>>, IsSpace>>;
46using FinalizingLineTextHandler = LexerObject<TextProcessingTransition, Negate<OrTest<CharacterTest<
'{'>, IsSpace>>, TokenFinalizer>;
48using SyntaxBoundaryNewlineHandler = CharacterTransition<
'\n', TokenFinalizerWithTrimmingAndNewline>;
49using SyntaxBoundaryHandler = CharacterTransition<
'{', FinalizeAndMarkStartSyntax>;
51template<
typename Transition>
54 auto tr =
new Transition(lexer, source);
55 tr->setTargetState(target);
58TextProcessingMachine *createMachine(
Lexer *lexer, Lexer::TrimType type)
60 auto machine =
new TextProcessingMachine;
64 machine->setInitialState(notFinished);
66 auto processingText =
new ChurningState(lexer, notFinished);
78 if (type == Lexer::SmartTrim)
81 processingPostTemplateSyntax =
new FinalizeTokenState(lexer, notFinished);
84 if (type == Lexer::SmartTrim)
85 notFinished->setInitialState(processingPostNewline);
87 notFinished->setInitialState(processingText);
89 if (type == Lexer::SmartTrim) {
90 addTransition<NewlineHandler>(processingText, lexer, processingPostNewline);
92 addTransition<NewlineHandler>(processingPostNewline, lexer, processingPostNewline);
93 addTransition<MaybeTemplateSyntaxHandler>(processingPostNewline, lexer, processingBeginTemplateSyntax);
94 addTransition<NonWhitespaceLineTextHandler>(processingPostNewline, lexer, processingText);
96 addTransition<MaybeTemplateSyntaxHandler>(processingText, lexer, processingBeginTemplateSyntax);
98 addTransition<TagStartHandler>(processingBeginTemplateSyntax, lexer, processingTag);
99 addTransition<CommentStartHandler>(processingBeginTemplateSyntax, lexer, processingComment);
100 addTransition<BeginValueHandler>(processingBeginTemplateSyntax, lexer, maybeProcessingValue);
102 if (type == Lexer::SmartTrim) {
103 addTransition<NotBeginTemplateSyntaxOrNewlineHandler>(processingBeginTemplateSyntax, lexer, processingText);
104 addTransition<NewlineHandler>(processingBeginTemplateSyntax, lexer, processingPostNewline);
106 addTransition<NotBeginTemplateSyntaxHandler>(processingBeginTemplateSyntax, lexer, processingText);
109 addTransition<NewlineHandler>(processingTag, lexer, type == Lexer::SmartTrim ? processingPostNewline : processingText);
110 addTransition<TagEndHandler>(processingTag, lexer, processingEndTag);
112 addTransition<NewlineHandler>(processingComment, lexer, type == Lexer::SmartTrim ? processingPostNewline : processingText);
113 addTransition<CommentEndHandler>(processingComment, lexer, processingEndComment);
115 addTransition<TagStartHandler>(maybeProcessingValue, lexer, processingTag);
116 addTransition<CommentStartHandler>(maybeProcessingValue, lexer, processingComment);
117 addTransition<NotTagCommentOrNewlineHandler>(maybeProcessingValue, lexer, processingValue);
118 addTransition<NewlineHandler>(maybeProcessingValue, lexer, type == Lexer::SmartTrim ? processingPostNewline : processingText);
120 addTransition<NewlineHandler>(processingValue, lexer, type == Lexer::SmartTrim ? processingPostNewline : processingText);
121 addTransition<MaybeEndValueHandler>(processingValue, lexer, processingEndValue);
123 addTransition<NewlineHandler>(processingEndTag, lexer, processingPostNewline);
124 addTransition<NotEndTemplateSyntaxHandler>(processingEndTag, lexer, processingTag);
125 addTransition<EndTemplateSyntaxHandler>(processingEndTag, lexer, processingPostTemplateSyntax);
127 addTransition<NewlineHandler>(processingEndComment, lexer, processingPostNewline);
128 addTransition<NotEndTemplateSyntaxHandler>(processingEndComment, lexer, processingComment);
129 addTransition<EndTemplateSyntaxHandler>(processingEndComment, lexer, processingPostTemplateSyntax);
131 addTransition<NewlineHandler>(processingEndValue, lexer, processingPostNewline);
132 addTransition<NotEndTemplateSyntaxHandler>(processingEndValue, lexer, processingValue);
133 addTransition<EndTemplateSyntaxHandler>(processingEndValue, lexer, processingPostTemplateSyntax);
135 if (type != Lexer::SmartTrim) {
136 processingPostTemplateSyntax->setUnconditionalTransition(processingText);
138 addTransition<SyntaxBoundaryNewlineHandler>(processingPostTemplateSyntax, lexer, processingPostNewline);
139 addTransition<WhitespaceNonNewlineHandler>(processingPostTemplateSyntax, lexer, processingPostTemplateSyntaxWhitespace);
140 addTransition<FinalizingLineTextHandler>(processingPostTemplateSyntax, lexer, processingText);
141 addTransition<SyntaxBoundaryHandler>(processingPostTemplateSyntax, lexer, processingBeginTemplateSyntax);
147 addTransition<SyntaxBoundaryNewlineHandler>(processingPostTemplateSyntaxWhitespace, lexer, processingPostNewline);
148 addTransition<FinalizingLineTextHandler>(processingPostTemplateSyntaxWhitespace, lexer, processingText);
149 addTransition<SyntaxBoundaryHandler>(processingPostTemplateSyntaxWhitespace, lexer, processingBeginTemplateSyntax);
153 auto handler =
new EofHandler(lexer, notFinished);
154 handler->setTargetState(finished);
155 notFinished->setEndTransition(handler);
158 if (type == Lexer::SmartTrim) {
160 auto handler =
new EofHandlerWithTrimming(lexer, processingPostTemplateSyntaxWhitespace);
161 handler->setTargetState(finished);
162 processingPostTemplateSyntaxWhitespace->setEndTransition(handler);
165 auto handler =
new EofHandlerWithTrimming(lexer, processingPostTemplateSyntax);
166 handler->setTargetState(finished);
167 processingPostTemplateSyntax->setEndTransition(handler);
173Lexer::Lexer(
const QString &templateString)
174 : m_templateString(templateString)
178Lexer::~Lexer() =
default;
180void Lexer::clearMarkers()
182 m_startSyntaxPosition = -1;
183 m_endSyntaxPosition = -1;
184 m_newlinePosition = -1;
198 auto machine = createMachine(
this, type);
202 auto it = m_templateString.constBegin();
203 const auto end = m_templateString.constEnd();
206 for (; it !=
end; ++it, ++m_upto)
207 machine->processCharacter(it);
218void Lexer::markStartSyntax()
220 m_startSyntaxPosition = m_upto;
223void Lexer::markEndSyntax()
225 m_endSyntaxPosition = m_upto + 1;
228void Lexer::markNewline()
230 m_newlinePosition = m_upto;
234void Lexer::finalizeToken()
237 const auto validSyntax = m_endSyntaxPosition > m_startSyntaxPosition && (m_startSyntaxPosition >= m_processedUpto);
240 Q_ASSERT(m_startSyntaxPosition >= 0);
243 finalizeToken(nextPosition, validSyntax);
246void Lexer::finalizeTokenWithTrimmedWhitespace()
254 Q_ASSERT(m_endSyntaxPosition > m_startSyntaxPosition);
256 Q_ASSERT(m_startSyntaxPosition >= 0);
257 if (m_newlinePosition >= 0 && m_newlinePosition >= m_processedUpto)
258 nextPosition = qMin(m_startSyntaxPosition - 1, m_newlinePosition);
261 finalizeToken(nextPosition,
true);
264void Lexer::finalizeToken(
int nextPosition,
bool processSyntax)
268 token.
content = m_templateString.
mid(m_processedUpto, nextPosition - m_processedUpto);
271 m_tokenList.append(token);
279 m_processedUpto = m_endSyntaxPosition;
281 const auto differentiator = m_templateString.at(m_startSyntaxPosition);
286 syntaxToken.
content = m_templateString.
mid(m_startSyntaxPosition + 1, m_endSyntaxPosition - m_startSyntaxPosition - 3).
trimmed();
295 m_tokenList.append(syntaxToken);
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
The KTextTemplate namespace holds all public KTextTemplate API.
@ TextToken
The Token is a text fragment.
@ VariableToken
The Token is a variable node.
@ BlockToken
The Token is a block, ie, part of a tag.
std::pair< long long int, long long int > nextPosition(const MdBlock< Trait > &fr, long long int pos, long long int line)
QString mid(qsizetype position, qsizetype n) const const
QString trimmed() const const
A token in a parse stream for a template.
int tokenType
The Type of this Token.
QString content
The content of this Token.
int linenumber
The line number this Token starts at.