ngle-line triple-quoted string
    rules << Rule("'''.*?'''", quote_format);
    rules << Rule("\"\"\".*?\"\"\"", quote_format);
    // Beginning of multiline string
    rules << Rule("'''.*$", quote_format, BASE, MULTILINE_SINGLE);
    rules << Rule("\"\"\".*$", quote_format, BASE, MULTILINE_DOUBLE);
    // End of multiline string
    rules << Rule("^.*'''", quote_format, MULTILINE_SINGLE, BASE);
    rules << Rule("^.*\"\"\"", quote_format, MULTILINE_DOUBLE, BASE);
    // Inside of multiline string
    rules << Rule("^.+$", quote_format, MULTILINE_SINGLE, MULTILINE_SINGLE);
    rules << Rule("^.+$", quote_format, MULTILINE_DOUBLE, MULTILINE_DOUBLE);

    // Regular strings
    rules << Rule("\".*?\"", quote_format);
    rules << Rule("'.*?'", quote_format);

    // String that can be prepended to a regex to make it detect negative
    // numbers (but not subtraction).  Note that a closing parenthesis is
    // needed and the desired number is the last match group.
    QString neg = "(^|\\*\\*|[(+\\-=*\\/,\\[])([+\\-\\s]*";

    QTextCharFormat float_format;
    float_format.setForeground(Colors::yellow);
    rules << Rule(neg + "\\b\\d+\\.\\d*)", float_format);
    rules << Rule(neg + "\\b\\d+\\.\\d*e\\d+)", float_format);
    rules << Rule(neg + "\\b\\d+e\\d+)", float_format);

    QTextCharFormat int_format;
    int_format.setForeground(Colors::orange);
    rules << Rule(neg + "\\b\\d+\\b)", int_format);

    QTextCharFormat comment_format;
    comment_format.setForeground(Colors::base03);

    rules << Rule("#.*", comment_format);
}

////////////////////////////////////////////////////////////////////////////////

void ScriptHighlighter::highlightBlock(const QString& text)
{
    int offset = 0;
    int state = previousBlockState();

    while (offset <= text.length())
    {
        int match_start = -1;
        int match_length;
        Rule rule;

        for (auto r : rules)
        {
            if (r.state_in != state)
                continue;

            auto match = r.regex.match(text, offset);
      