/// <summary>Grammar based auto complete controller.</summary>
class
GuiGrammarAutoComplete
:
public
GuiTextBoxAutoCompleteBase
,
protected
RepeatingParsingExecutor
::
CallbackBase
,
private
RepeatingTaskExecutor
<
RepeatingParsingOutput
>
{
public
:
/// <summary>The auto complete list data.</summary>
struct
AutoCompleteData
:
ParsingTokenContext
{
/// <summary>Available candidate tokens (in lexer token index).</summary>
collections
::
List
<
vint
>
candidates
;
/// <summary>Available candidate tokens (in lexer token index) that marked with @AutoCompleteCandidate().</summary>
collections
::
List
<
vint
>
shownCandidates
;
/// <summary>Candidate items.</summary>
collections
::
List
<
ParsingCandidateItem
>
candidateItems
;
/// <summary>The start position of the editing token in global coordination.</summary>
TextPos
startPosition
;
};
/// <summary>The analysed data from an input code.</summary>
struct
AutoCompleteContext
:
RepeatingPartialParsingOutput
{
/// <summary>The edit version of modified code.</summary>
vuint
modifiedEditVersion
=
0
;
/// <summary>The analysed auto complete list data.</summary>
Ptr
<
AutoCompleteData
>
autoComplete
;
};
private
:
Ptr
<
parsing
::
tabling
::
ParsingGeneralParser
>
grammarParser
;
collections
::
SortedList
<
WString
>
leftRecursiveRules
;
bool
editing
;
SpinLock
editTraceLock
;
collections
::
List
<
TextEditNotifyStruct
>
editTrace
;
SpinLock
contextLock
;
AutoCompleteContext
context
;
void
Attach
(
elements
::
GuiColorizedTextElement
*
_element
,
SpinLock
&
_elementModifyLock
,
compositions
::
GuiGraphicsComposition
*
_ownerComposition
,
vuint
editVersion
)
override
;
void
Detach
()
override
;
void
TextEditPreview
(
TextEditPreviewStruct
&
arguments
)
override
;
void
TextEditNotify
(
const
TextEditNotifyStruct
&
arguments
)
override
;
void
TextCaretChanged
(
const
TextCaretChangedStruct
&
arguments
)
override
;
void
TextEditFinished
(
vuint
editVersion
)
override
;
void
OnParsingFinishedAsync
(
const
RepeatingParsingOutput
&
output
)
override
;
void
CollectLeftRecursiveRules
();
vint
UnsafeGetEditTraceIndex
(
vuint
editVersion
);
TextPos
ChooseCorrectTextPos
(
TextPos
pos
,
const
regex
::
RegexTokens
&
tokens
);
void
ExecuteRefresh
(
AutoCompleteContext
&
newContext
);
bool
NormalizeTextPos
(
AutoCompleteContext
&
newContext
,
elements
::
text
::
TextLines
&
lines
,
TextPos
&
pos
);
void
ExecuteEdit
(
AutoCompleteContext
&
newContext
);
void
DeleteFutures
(
collections
::
List
<
parsing
::
tabling
::
ParsingState
::
Future
*>&
futures
);
regex
::
RegexToken
*
TraverseTransitions
(
parsing
::
tabling
::
ParsingState
&
state
,
parsing
::
tabling
::
ParsingTransitionCollector
&
transitionCollector
,
TextPos
stopPosition
,
collections
::
List
<
parsing
::
tabling
::
ParsingState
::
Future
*>&
nonRecoveryFutures
,
collections
::
List
<
parsing
::
tabling
::
ParsingState
::
Future
*>&
recoveryFutures
);
regex
::
RegexToken
*
SearchValidInputToken
(
parsing
::
tabling
::
ParsingState
&
state
,
parsing
::
tabling
::
ParsingTransitionCollector
&
transitionCollector
,
TextPos
stopPosition
,
AutoCompleteContext
&
newContext
,
collections
::
SortedList
<
vint
>&
tableTokenIndices
);
TextPos
GlobalTextPosToModifiedTextPos
(
AutoCompleteContext
&
newContext
,
TextPos
pos
);
TextPos
ModifiedTextPosToGlobalTextPos
(
AutoCompleteContext
&
newContext
,
TextPos
pos
);
void
ExecuteCalculateList
(
AutoCompleteContext
&
newContext
);
void
Execute
(
const
RepeatingParsingOutput
&
input
)
override
;
void
PostList
(
const
AutoCompleteContext
&
newContext
,
bool
byGlobalCorrection
);
void
Initialize
();
protected
:
/// <summary>Called when the context of the code is selected. It is encouraged to set the "candidateItems" field in "context.autoComplete" during the call. If there is an <see cref="RepeatingParsingExecutor::IParsingAnalyzer"/> binded to the <see cref="RepeatingParsingExecutor"/>, this function can be automatically done.</summary>