/// <summary> /// Loops until token pattern match succeeds. /// This method matches using the same primary token filter as the parent match. /// Keeps state machine if match was found on the first token that follows the match /// </summary> public static FSMI LoopUntilAfterMatch <TToken>(this LazyFSMState <TToken> state, params LazyFSMPredicate <TToken>[] predicates ) where TToken : Token { if (state.m_SkipCount > 0) { state.m_SkipCount--; if (state.m_SkipCount == 0) { return(FSMI.Advance); } return(FSMI.Loop); } var stream = state.Tokens; if (state.m_CurrentTokenIndex > 0) { stream = stream.Skip(state.m_CurrentTokenIndex); } LazyFSMState <TToken> subState = new LazyFSMState <TToken>(); if (stream.LazyFSM(state.m_OnlyPrimary, ref subState, predicates) != null) { return(state.Skip(subState.m_PatternTokenLength - 1)); } return(FSMI.Loop); }
/// <summary> /// Makes finite state machine fed from IEnumerable(Token) /// </summary> /// <typeparam name="TToken">Concrete language-typed token</typeparam> /// <param name="tokens">Token enumerable</param> /// <param name="onlyPrimary">Sets filter to consider only primary language tokens (skip comments, directives, etc.)</param> /// <param name="predicates">Predicates that supply machine state transition instructions</param> /// <returns>Resulting token fetched by FSMI.Take instruction or null</returns> public static TToken LazyFSM <TToken>(this IEnumerable <TToken> tokens, bool onlyPrimary, params LazyFSMPredicate <TToken>[] predicates) where TToken : Token { LazyFSMState <TToken> state = null; return(tokens.LazyFSM <TToken>(onlyPrimary, ref state, predicates)); }
/// <summary> /// Loops until token pattern match succeeds, conditionally considering only primary language tokens. /// Keeps state machine if match was found on the first matching token /// </summary> public static FSMI LoopUntilMatch <TToken>(this LazyFSMState <TToken> state, bool onlyPrimary, params LazyFSMPredicate <TToken>[] predicates ) where TToken : Token { var stream = state.Tokens; if (state.m_CurrentTokenIndex > 0) { stream = stream.Skip(state.m_CurrentTokenIndex); } LazyFSMState <TToken> subState = new LazyFSMState <TToken>(); return(stream.LazyFSM(onlyPrimary, ref subState, predicates) != null ? FSMI.AdvanceOnSameToken : FSMI.Loop); }
/// <summary> /// Skips specified number of tokens by returning FSMI.Loop count times /// </summary> public static FSMI Skip <TToken>(this LazyFSMState <TToken> state, int count) where TToken : Token { if (count == 0) { return(FSMI.Advance); } if (count < 0) { throw new CodeAnalysisException("FSMI Skip(count) must be > 0"); } if (state.m_SkipCount > 0) { state.m_SkipCount--; if (state.m_SkipCount == 0) { return(FSMI.Advance); } return(FSMI.Loop); } state.m_SkipCount = count; return(FSMI.Loop); }
/// <summary> /// Makes finite state machine fed from IEnumerable(Token) /// </summary> /// <typeparam name="TToken">Concrete language-typed token</typeparam> /// <param name="tokens">Token enumerable</param> /// <param name="onlyPrimary">Sets filter to consider only primary language tokens (skip comments, directives, etc.)</param> /// <param name="state">Machine's state which will be allocated if null passed</param> /// <param name="predicates">Predicates that supply machine state transition instructions</param> /// <returns>Resulting token fetched by FSMI.Take instruction or null</returns> public static TToken LazyFSM <TToken>(this IEnumerable <TToken> tokens, bool onlyPrimary, ref LazyFSMState <TToken> state, params LazyFSMPredicate <TToken>[] predicates) where TToken : Token { var first = true; var pidx = 0; TToken result = null; var en = tokens.GetEnumerator(); if (state == null) { state = new LazyFSMState <TToken>(); } state.m_Tokens = tokens; state.m_CurrentTokenIndex = -1; state.m_PatternTokenLength = -1; state.m_OnlyPrimary = onlyPrimary; var dontMove = false; while (pidx < predicates.Length) { if (dontMove) { dontMove = false; } else { if (!en.MoveNext()) { break; } state.m_CurrentTokenIndex++; state.m_PatternTokenLength++; } TToken token = en.Current; if (token.IsEOF) { break; } if (!onlyPrimary || token.IsPrimary || first) { first = false; state.m_CurrentToken = token; var action = predicates[pidx](state, token); switch (action) { case FSMI.Loop: break; case FSMI.Abort: return(null); case FSMI.Advance: { pidx++; break; } case FSMI.AdvanceOnSameToken: { pidx++; dontMove = true; break; } case FSMI.Take: { result = token; pidx++; break; } case FSMI.TakeAndComplete: return(token); case FSMI.Complete: return(result); default: return(null); } } }//while return(result); }
/// <summary> /// Loops until token pattern match succeeds, considering only primary language tokens. /// Keeps state machine if match was found on the first matching token /// </summary> public static FSMI LoopUntilMatch <TToken>(this LazyFSMState <TToken> state, params LazyFSMPredicate <TToken>[] predicates ) where TToken : Token { return(state.LoopUntilMatch(true, predicates)); }