Simple parsing for string formatting (version 2) This is my second attempt (version 1) at writing a string formatting utility which uses parsing. This time I more explicitly designed it as a finite state machine. I have very little experience with writing FSMs. As before, I'm not 100% sure that this code does not contain any critical flaws. In addition to pointing out any such oversights, I would appreciate advice on how this could be modified to make it either faster or more readable.

#include &lt;boost/lexical_cast.hpp&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;stdexcept&gt;
#include &lt;utility&gt;
#include &lt;cctype&gt;

using std::to_string;

template &lt;class T&gt;
std::string to_string(T&amp;&amp; item)
{
    return boost::lexical_cast&lt;std::string&gt;(std::forward&lt;T&gt;(item));   
}

template &lt;class... Args&gt;
std::string format(const std::string&amp; fmt, Args&amp;&amp;... args)
{
    std::string arg_strs[] = { to_string(std::forward&lt;Args&gt;(args))... };

    std::string output, index;
    output.reserve(fmt.length() * 2);

    enum { COPYING, OPEN_BRACE, READ_INDEX, CLOSE_BRACE } state = COPYING;

    for (const char c : fmt) 
    {
        switch (state)
        {
            case COPYING:
                if (c == '{') state = OPEN_BRACE;
                else if (c == '}') state = CLOSE_BRACE;
                else output += c;
                break;

            case OPEN_BRACE:
                if (isdigit(c)) {
                    index += c;
                    state = READ_INDEX;
                }
                else if (c == '{') {
                    output += '{';
                    state = COPYING;
                }
                else goto fail;
                break;

            case READ_INDEX:
                if (isdigit(c)) index += c;
                else if (c == '}') {
                    size_t i = std::stoi(index);
                    if (i &gt;= sizeof...(args)) {
                        throw std::out_of_range(
                            "argument index is out of range in format");
                    }
                    output += arg_strs[i];
                    index.clear();
                    state = COPYING;
                }
                else goto fail;
                break;

            case CLOSE_BRACE:
                if (c == '}') {
                    output += '}';
                    state = COPYING;
                }
                else goto fail;
                break;
        }
    }

    if (state != COPYING) goto fail;
    return output;

fail:
    throw std::invalid_argument("invalid format string");
}

template &lt;class... Args&gt;
void print(const std::string&amp; fmt, Args&amp;&amp;... args)
{
    std::cout &lt;&lt; format(fmt, std::forward&lt;Args&gt;(args)...);
}

int main()
{
    print("Hello, {0}! The answer is {1}.", "World", 42);
}


Here is a diagram of the FSM:



Now just for fun, I converted this to JavaScript with regex...

function format(fmt, ...args) {
    if (!fmt.match(/^(?:(?:(?:[^{}]|(?:\{\{)|(?:\}\}))+)|(?:\{[0-9]+\}))+$/)) {
        throw new Error('invalid format string.');
    }
    return fmt.replace(/((?:[^{}]|(?:\{\{)|(?:\}\}))+)|(?:\{([0-9]+)\})/g, (m, str, index) =&gt; {
        if (str) {
            return str.replace(/(?:{{)|(?:}})/g, m =&gt; m[0]);
        } else {
            if (index &gt;= args.length) {
                throw new Error('argument index is out of range in format');
            }
            return args[index];
        }
    });
}

function print(fmt, ...args) {
    console.log(format(fmt, ...args));
}

print("Hello, {0}! The answer is {1}.", "World", 42);
I think CS subjects like automata are too much for this problem, thats more something you have to deal with when implementing a regular expressions engine. Here is some code in C# that I've written to replace tags in a string, its absolutely not optimal because the state is checked every iteration and each character is copied individually, but you'll get the my idea.

private string ReplaceTags(string text, Dictionary&lt;string, string&gt; tags)
{
    StringBuilder result = new StringBuilder();
    StringBuilder tag = new StringBuilder();

    int mode = 0;

    int len = text.Length - 1;

    for (int i = 0; i &lt;= len; i++)
    {
        char c = text[i];

        if (mode == 0)
        {
            if (text[i] == '\\')
            {
                i++;

                if (i &lt;= len)
                {
                    result.Append(text[i]);
                }
            }
            else if (text[i] == '[')
            {
                mode = 1;
            }
            else
            {
                result.Append(text[i]);
            }
        }
        else
        {
            if (text[i] == ']')
            {
                string _tag = tag.ToString().ToLowerInvariant();

                if (tags.ContainsKey(_tag))
                {
                    result.Append(tags[_tag]);
                }

                tag.Length = 0;
                mode = 0;
            }
            else
            {
                tag.Append(text[i]);
            }
        }
    }

    return result.ToString();
}