Exemple #1
0
        /// <summary>Extract a token from the front of a lexical input queue.</summary>
        /// <param name="input">The input from which to extract a token. The extracted lexical bits will be removed from the queue.</param>
        /// <param name="impliedBraces">Whether we're parsing a token context (so the outer '{{' and '}}' are implied); else parse as a tokenizable string which main contain a mix of literal and {{token}} values.</param>
        /// <returns>Returns the token.</returns>
        public LexTokenToken ExtractToken(Queue <LexBit> input, bool impliedBraces)
        {
            LexBit GetNextAndAssert(string expectedPhrase)
            {
                if (!input.Any())
                {
                    throw new LexFormatException($"Reached end of input, expected {expectedPhrase}.");
                }
                return(input.Dequeue());
            }

            // start token
            if (!impliedBraces)
            {
                LexBit startToken = GetNextAndAssert("start of token ('{{')");
                if (startToken.Type != LexBitType.StartToken)
                {
                    throw new LexFormatException($"Unexpected {startToken.Type} at start of token.");
                }
            }

            // extract token name
            LexBit name = GetNextAndAssert("token name");

            if (name.Type != LexBitType.Literal)
            {
                throw new LexFormatException($"Unexpected {name.Type} where token name should be.");
            }

            // extract input arguments if present
            // Note: the positional input argument separator (:) is the 'real' separator between
            // the token name and input arguments, but a token can skip positional arguments and
            // start named arguments directly like {{TokenName |key=value}}. In that case the ':'
            // is implied, and the '|' separator *is* included in the input arguments string.
            LexTokenInput inputArgs = null;

            if (input.Any())
            {
                var next = input.Peek().Type;
                if (next == LexBitType.PositionalInputArgSeparator || next == LexBitType.NamedInputArgSeparator)
                {
                    if (next == LexBitType.PositionalInputArgSeparator)
                    {
                        input.Dequeue();
                    }
                    inputArgs = this.ExtractInputArguments(input);
                }
            }

            // end token
            if (!impliedBraces)
            {
                LexBit endToken = GetNextAndAssert("end of token ('}}')");
                if (endToken.Type != LexBitType.EndToken)
                {
                    throw new LexFormatException($"Unexpected {endToken.Type} before end of token.");
                }
            }

            return(new LexTokenToken(name.Text.Trim(), inputArgs, impliedBraces));
        }
 /// <summary>Construct an instance.</summary>
 /// <param name="inputArgs">The raw token input arguments.</param>
 /// <param name="context">The available token context.</param>
 /// <param name="path">The path to the value from the root content file.</param>
 public TokenString(LexTokenInput inputArgs, IContext context, LogPathBuilder path)
     : this(lexTokens : inputArgs?.Parts, context : context, path : path)
 {
 }