// Copyright Epic Games, Inc. All Rights Reserved. using System; using EpicGames.UHT.Utils; namespace EpicGames.UHT.Tokenizer { /// /// Series of extensions to token reading that are far too specialized to be included in the reader. /// public static class UhtTokenReaderSkipExtensions { /// /// Skip a token regardless of the type. /// /// Token reader /// Token reader public static IUhtTokenReader SkipOne(this IUhtTokenReader tokenReader) { tokenReader.PeekToken(); tokenReader.ConsumeToken(); return tokenReader; } /// /// Skip any block of tokens wrapped by the given token symbols /// /// Token reader /// Initiating token (i.e. "(") /// Terminating token (i.e. ")") /// If true, start with an initial nesting count of one (assume we already parsed an initiator) /// Extra context for any errors /// Token reader /// Throw if end of file is reached public static IUhtTokenReader SkipBrackets(this IUhtTokenReader tokenReader, char initiator, char terminator, int initialNesting, object? exceptionContext = null) { int nesting = initialNesting; if (nesting == 0) { tokenReader.Require(initiator, exceptionContext); ++nesting; } do { UhtToken skipToken = tokenReader.GetToken(); if (skipToken.TokenType.IsEndType()) { throw new UhtTokenException(tokenReader, skipToken, terminator, exceptionContext); } else if (skipToken.IsSymbol(initiator)) { ++nesting; } else if (skipToken.IsSymbol(terminator)) { --nesting; } } while (nesting != 0); return tokenReader; } /// /// Skip any block of tokens wrapped by the given token symbols /// /// Token reader /// Initiating token (i.e. "(") /// Terminating token (i.e. ")") /// If true, start with an initial nesting count of one (assume we already parsed an initiator) /// Invoked for each matching token /// Extra context for any errors /// Token reader /// Throw if end of file is reached public static IUhtTokenReader SkipBrackets(this IUhtTokenReader tokenReader, char initiator, char terminator, int initialNesting, Action callback, object? exceptionContext = null) { int nesting = initialNesting; if (nesting == 0) { ref UhtToken token = ref tokenReader.PeekToken(); if (token.IsSymbol(initiator)) { callback(token); tokenReader.ConsumeToken(); } else { throw new UhtTokenException(tokenReader, token, initiator, exceptionContext); } ++nesting; } do { UhtToken skipToken = tokenReader.GetToken(); if (skipToken.TokenType.IsEndType()) { throw new UhtTokenException(tokenReader, skipToken, terminator, exceptionContext); } else if (skipToken.IsSymbol(initiator)) { ++nesting; } else if (skipToken.IsSymbol(terminator)) { --nesting; } callback(skipToken); } while (nesting != 0); return tokenReader; } /// /// Skip tokens until the given terminator is found. The terminator will not be consumed. /// /// Token reader /// Terminator to skip until /// Extra context for any exceptions /// Token reader public static IUhtTokenReader SkipUntil(this IUhtTokenReader tokenReader, char terminator, object? exceptionContext = null) { while (true) { ref UhtToken skipToken = ref tokenReader.PeekToken(); if (skipToken.TokenType.IsEndType()) { throw new UhtTokenException(tokenReader, skipToken, terminator, exceptionContext); } else if (skipToken.IsSymbol(terminator)) { break; } tokenReader.ConsumeToken(); } return tokenReader; } } }