Ejemplo n.º 1
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Given the information of the currently open quotation marks, process the next encountered
		/// quotation mark, updating the information and generating errors where appropriate.
		/// </summary>
		/// <param name="qmTok">The quotation mark token being processed</param>
		/// <param name="openQuotes">The currently open quotes</param>
		/// ------------------------------------------------------------------------------------
		private void CheckQuote(QuotationMarkToken qmtok, OpenQuotes openQuotes)
		{
			GenerateTraceMsg(qmtok, string.Format(qmtok.IsOpener ?
				Localize("Level {0} quote opened") : Localize("Level {0} quote closed"),
				(qmtok.IsOpener ? openQuotes.Level + 1 : openQuotes.Level)));

			if (m_qmCategorizer.IsMarkForLevel(qmtok.Tts.Text, openQuotes.Level + 1) && qmtok.IsOpener)
			{
				// The quote is opened properly
				openQuotes.Level++;
				openQuotes.Openers.Add(qmtok);
				return;
			}
			else if (m_qmCategorizer.IsMarkForLevel(qmtok.Tts.Text, openQuotes.Level) &&
				(!qmtok.IsOpener || m_qmCategorizer.OpeningAndClosingAreIdentical(openQuotes.Level)))
			{
				// The quote is closed properly
				openQuotes.Level--;
				openQuotes.Openers.RemoveAt(openQuotes.Level);
				return;
			}

			int possibleQuoteMarkLevel = m_qmCategorizer.Level(qmtok.Tts.Text,
				openQuotes.Level, qmtok.IsOpener);

			if (m_fFoundMissingContinuer)
			{
				//Debug.Assert(openQuotes.Level == openQuotes.Openers.Count);
				Debug.Assert(possibleQuoteMarkLevel != 0);

				int newLevel = qmtok.IsOpener ? possibleQuoteMarkLevel : possibleQuoteMarkLevel - 1;
				if (newLevel < openQuotes.Openers.Count)
				{
					while (openQuotes.Openers.Count > newLevel)
						openQuotes.Openers.RemoveAt(openQuotes.Openers.Count - 1);
				}
				else if (newLevel > openQuotes.Openers.Count)
				{
					while (openQuotes.Openers.Count < newLevel)
						openQuotes.Openers.Add("Missing Quote");
				}
				openQuotes.Level = newLevel;
				if (qmtok.IsOpener)
					openQuotes.Openers.Add(qmtok);
				else if (openQuotes.Openers.Count > 0 && openQuotes.Openers.Count > openQuotes.Level)
					openQuotes.Openers.RemoveAt(openQuotes.Level);
				return;
			}
			else if (!m_qmCategorizer.TopLevelClosingExists && possibleQuoteMarkLevel == 1 &&
				openQuotes.Level == 1)
			{
				// Opens a top-level quote when top-level closing quotes do not exist
				openQuotes.Openers.RemoveAt(0);
				openQuotes.Openers.Add(qmtok);
				return;
			}
			else if (possibleQuoteMarkLevel > openQuotes.Level && !qmtok.IsOpener)
			{
				// The quote was closed, but was not opened
				if (!m_qmCategorizer.CollapseAdjacentQuotes || openQuotes.MostRecent == null)
				{
					ReportError(qmtok, string.Format(Localize(m_noOpenerMsg),
						possibleQuoteMarkLevel));
				}
				return;
			}
			else if (possibleQuoteMarkLevel > openQuotes.Level + 1 && qmtok.IsOpener)
			{
				// The opener for the quote belongs to a quote level that is too high
				ReportError(qmtok, string.Format(
					Localize("Unexpected opening mark: level {0}"),
					possibleQuoteMarkLevel));

				// Add missing tokens for skipped levels
				while (openQuotes.Openers.Count < possibleQuoteMarkLevel - 1)
					openQuotes.Openers.Add("Missing Quote");

				openQuotes.Level = possibleQuoteMarkLevel;
				openQuotes.Openers.Add(qmtok);
				return;
			}
			else if (possibleQuoteMarkLevel <= openQuotes.Level && qmtok.IsOpener)
			{
				// Opens a quote at the level already open or at too far out a level
				for (int i = openQuotes.Level; i >= possibleQuoteMarkLevel; i--)
				{
					if (!(openQuotes.Openers[i - 1] is QToken))
						continue;

					ReportError(openQuotes.Openers[i - 1] as QToken,
						string.Format(m_noCloserMsg, i));
				}

				openQuotes.Openers.RemoveRange(possibleQuoteMarkLevel - 1,
					openQuotes.Level - possibleQuoteMarkLevel + 1);
				openQuotes.Level = possibleQuoteMarkLevel;
				openQuotes.Openers.Add(qmtok);
				return;
			}

			// A quote outside the current one is closed before the current one
			for (int i = possibleQuoteMarkLevel; i < openQuotes.Level; i++)
			{
				if (!(openQuotes.Openers[i] is QToken))
					continue;

				ReportError(openQuotes.Openers[i] as QToken,
					string.Format(m_noCloserMsg, i + 1));
			}

			openQuotes.Openers.RemoveRange(possibleQuoteMarkLevel - 1, openQuotes.Level - possibleQuoteMarkLevel);
			openQuotes.Level = possibleQuoteMarkLevel - 1;
		}
Ejemplo n.º 2
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// If the token starts a typographic paragraph, store it as a paragraph-start token and
		/// highlight (shows up on user interface) its text. Otherwise, if the token is
		/// a quotation mark (either opening or closing, as defined by the quotation
		/// categorizer), store it as a quotation mark token.
		/// </summary>
		/// <param name="tok">The token being processed</param>
		/// ------------------------------------------------------------------------------------
		internal void ProcessToken(ITextToken tok, VerseTextToken verseTok)
		{
			if (tok == null)
				throw new ArgumentNullException("tok");

			Debug.Assert(!(tok is VerseTextToken));

			if (tok.IsParagraphStart)
			{
				TextTokenSubstring tts = new TextTokenSubstring(tok, 0, 0);
				ParaStartToken pstok = new ParaStartToken(tts, tok.ParaStyleName);
				m_quotationRelatedTokens.Add(pstok);
			}

			AddTextToParaStartTokens(tok);

			// Find the first non whitespace, non quotation mark character in the token's
			// text. This will be used in the following loop to determine what quotation
			// marks precede all other characters in the token (i.e. what quotation marks
			// begin the paragraph and are possible continuers).
			Match match = m_regExNonQuotes.Match(tok.Text);
			int iFirstNoneQMarkChar = (match.Success ? match.Index : -1);

			// Now find all the quotation marks in the token's text.
			MatchCollection mc = m_regExQuotes.Matches(tok.Text);

			// Go through all the quotation marks found, creating quotation tokens
			// for each.
			foreach (Match m in mc)
			{
				TextTokenSubstring tts = new TextTokenSubstring(tok, m.Index, m.Length);

				bool fIsParaStart = verseTok != null ? verseTok.IsParagraphStart : tok.IsParagraphStart;
				bool fIsOpener = m_qmCategorizer.IsInitialPunctuation(tts.Text);
				bool fPossibleContinuer = (m.Index < iFirstNoneQMarkChar && fIsParaStart);
				QuotationMarkToken qmt = new QuotationMarkToken(tts, m_qmCategorizer,
					fIsOpener, fPossibleContinuer);
				m_quotationRelatedTokens.Add(qmt);
			}
		}