/// <summary>
        /// Updates the state of the parser by processing the specified token.
        /// State is updated based on contents of token (e.g. verse change), but position
        /// is the beginning of token, not the end.
        /// </summary>
        /// <param name="tokens">list of all tokens being processed</param>
        /// <param name="index">index of the token to be processed</param>
        /// <param name="tokensPreserveWhitespace">True if the tokens were created while preserving whitespace,
        /// false otherwise</param>
        public void UpdateState(List <UsfmToken> tokens, int index, bool tokensPreserveWhitespace = false)
        {
            if (this.tokens != null && this.tokens != tokens)
            {
                parser = null; // Reset parser
            }
            this.tokens             = tokens;
            this.preserveWhitespace = tokensPreserveWhitespace;

            // Create parser if not done already
            if (parser == null)
            {
                parser = new UsfmParser(ScrStylesheet, tokens, this, new ScrParserUsfmParserSink(this), tokensPreserveWhitespace);
            }

            // Check that token to process is next token
            if (index != parser.Index + 1)
            {
                throw new ArgumentException("Tokens must be processed sequentially");
            }

            // Reset paraStart and cellStart
            ParaStart = false;
            CellStart = false;

            parser.ProcessToken();
        }
Exemple #2
0
        private static void LookaheadParser(UsfmParserState state, UsfmParser lookaheadParser, string marker, out bool isTokenClosed)
        {
            // BEWARE: This method is fairly performance-critical
            // Determine current marker
            string endMarker = marker + "*";

            // Process tokens until either the start of the stack doesn't match (it was closed
            // improperly) or a matching close marker is found
            while (lookaheadParser.ProcessToken())
            {
                UsfmToken currentToken = lookaheadParser.tokens[lookaheadParser.index];

                // Check if same marker was reopened without a close
                bool reopened = currentToken.Marker == marker &&
                                lookaheadParser.State.Stack.SequenceEqual(state.Stack);
                if (reopened)
                {
                    isTokenClosed = false;
                    return;
                }

                // Check if beginning of stack is unchanged. If token is unclosed, it will be unchanged
                bool markerStillOpen = lookaheadParser.State.Stack.Take(state.Stack.Count).SequenceEqual(state.Stack);
                if (!markerStillOpen)
                {
                    // Record whether marker is an end for this marker
                    isTokenClosed = currentToken.Marker == endMarker && currentToken.Type == UsfmTokenType.End;
                    return;
                }
            }
            isTokenClosed = false;
        }
Exemple #3
0
        /// <summary>
        /// Determines if the current token is closed by a matching end marker
        /// </summary>
        /// <returns></returns>
        bool IsTokenClosed()
        {
            // Clone current parser
            if (tokenClosedParser == null)
            {
                tokenClosedParser = new UsfmParser(this);
            }
            tokenClosedParser.UpdateParser(this);

            bool   isTokenClosed;
            string marker = tokens[index].Marker;

            LookaheadParser(State, tokenClosedParser, marker, out isTokenClosed);
            return(isTokenClosed);
        }
Exemple #4
0
        private bool CheckInternal(List <UsfmToken> tokens, int bookNum, ScrStylesheet scrStylesheet)
        {
            VerseRef startVerse = new VerseRef(bookNum, 1, 0, ScrVers.English);

            if (tokens.Count > 0 && tokens[0].Marker != "id")
            {
                RecordError(startVerse, "", 0, "#" + missingIdMarker);
            }

            MarkerCheckSink markerCheckSink = new MarkerCheckSink(scrStylesheet, startVerse.Book, this);
            UsfmParser      parser          = new UsfmParser(scrStylesheet, tokens, startVerse, markerCheckSink);

            parser.ProcessTokens();
            markerCheckSink.ReportPendingVerseNoParaError();
            markerCheckSink.ReportOpenMilestoneErrors();
            return(markerErrors || markerCheckSink.MarkerErrors);
        }
Exemple #5
0
 /// <summary>
 /// Updates the state of this parser to be the same as the state of the specified parser.
 /// </summary>
 internal void UpdateParser(UsfmParser usfmParser)
 {
     state = usfmParser.State.Clone();
     index = usfmParser.index;
     skip  = 0;
 }
Exemple #6
0
 /// <summary>
 /// Constructor for making a duplicate for looking ahead to find closing
 /// tokens of notes and character styles.
 /// </summary>
 UsfmParser(UsfmParser usfmParser, UsfmParserSink sink = null)
 {
     scrStylesheet = usfmParser.scrStylesheet;
     tokens        = usfmParser.tokens;
     this.sink     = sink;
 }