private Operation parseNormalArgument() {
            char c = parser.peek();

            // Create the appropriate function for retrieving the value. Positional and relative arguments
            // are known statically, but getting context properties is deferring until it's time to write.
            // This allows things like loops to populate loop control variables.
            Function<AbstractCodeWriter<?>, Object> getter;
            if (Character.isLowerCase(c)) {
                String name = parseNamedArgumentName();
                getter = w -> w.getContext(name);
            } else if (Character.isDigit(c)) {
                getter = parsePositionalArgumentGetter();
            } else {
                getter = parseRelativeArgumentGetter();
            }

            // Parse the formatter and apply it.
            int line = parser.line();
            int column = parser.column();
            char identifier = parser.expect(AbstractCodeWriter.VALID_FORMATTER_CHARS);

            // The error message needs to be created here and given to the operation in way that it can
            // throw with an appropriate message.
            return Operation.formatted(getter,
                    identifier,
                    () -> createErrorMessage(String.format(
                            "Syntax error at line %d column %d: Unknown formatter `%c` found in format string",
                            line,
                            column,
                            identifier)));
        }
A BlockOperation that repeats a template for each value referenced by the block. Each iteration pushes
a state to the writer that includes key, value, key.first, and key.last context properties. The name
of the context property can be customized in the template.
smithy-utils/src/main/java/software/amazon/smithy/utils/CodeFormatter.java