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>
52void addTransition(TextProcessingState *source,
Lexer *lexer, TextProcessingState *target)
54 auto tr =
new Transition(lexer, source);
55 tr->setTargetState(target);
58TextProcessingMachine *createMachine(
Lexer *lexer, Lexer::TrimType type)
60 auto machine =
new TextProcessingMachine;
62 auto notFinished =
new TextProcessingState(machine);
63 auto finished =
new TextProcessingState(machine);
64 machine->setInitialState(notFinished);
66 auto processingText =
new ChurningState(lexer, notFinished);
67 auto processingPostNewline =
new TextProcessingState(notFinished);
68 auto processingBeginTemplateSyntax =
new TextProcessingState(notFinished);
69 auto processingTag =
new TextProcessingState(notFinished);
70 auto processingComment =
new TextProcessingState(notFinished);
71 auto processingValue =
new TextProcessingState(notFinished);
72 auto maybeProcessingValue =
new TextProcessingState(notFinished);
73 auto processingEndTag =
new TextProcessingState(notFinished);
74 auto processingEndComment =
new TextProcessingState(notFinished);
75 auto processingEndValue =
new TextProcessingState(notFinished);
76 TextProcessingState *processingPostTemplateSyntax;
78 if (type == Lexer::SmartTrim)
79 processingPostTemplateSyntax =
new TextProcessingState(notFinished);
81 processingPostTemplateSyntax =
new FinalizeTokenState(lexer, notFinished);
82 auto processingPostTemplateSyntaxWhitespace =
new TextProcessingState(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);
282 if (differentiator == QLatin1Char(
'#'))
286 syntaxToken.
content = m_templateString.
mid(m_startSyntaxPosition + 1, m_endSyntaxPosition - m_startSyntaxPosition - 3).
trimmed();
289 if (differentiator == QLatin1Char(
'{')) {
292 Q_ASSERT(differentiator == QLatin1Char(
'%'));
295 m_tokenList.append(syntaxToken);
const QList< QKeySequence > & end()
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
int tokenType
The Type of this Token.
QString content
The content of this Token.
int linenumber
The line number this Token starts at.