Grammar

    document =
        doc_info >> blocks >> space
        ;

    blocks =
       +(   block_markup
        |   code
        |   unordered_list
        |   ordered_list
        |   hr
        |   comment >> *eol_p
        |   paragraph
        |   eol_p
        )
        ;

    space =
        *(blank_p | comment)
        ;

    comment =
        "[/" >> *(anychar_p - ']') >> ']'
        ;

    doc_info =
            *(space_p | comment)
        >> "[doc" >> space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    hr =
        str_p("----")
        >> *(anychar_p - eol_p)
        >> +eol_p;
        ;

    block_markup =
            '['
        >>  (   page
            |   headings
            |   blurb
            |   blockquote
            |   preformatted
            |   def_macro
            |   table
            )
        >>  ']'
        >> +eol_p
        ;

    page =
            "page"
        >>  !(':' >> uint_p)
        >>  space
        >>  (*(anychar_p - ']'))
        ;

    headings =
        h1 | h2 | h3 | h4 | h5 | h6
        ;

    h1 = "h1" >> space >> phrase;
    h2 = "h2" >> space >> phrase;
    h3 = "h3" >> space >> phrase;
    h4 = "h4" >> space >> phrase;
    h5 = "h5" >> space >> phrase;
    h6 = "h6" >> space >> phrase;

    blurb =
        "blurb" >> space
        >> phrase
        ;

    blockquote =
        ':' >> space >>
        phrase
        ;

    preformatted =
        "pre" >> space >>
        phrase
        ;

    def_macro =
        "def" >> space >> identifier
         >> space >> phrase
        ;

    table =
        "table" >> space
        >>  (*(anychar_p - eol_p))
        >>  +eol_p
        >> *(   table_row
                >> +eol_p
            )
        >>  eps_p
        ;

    table_row =
       *(       space
            >>  ch_p('[')
            >>  phrase
            >>  ch_p(']')
            >>  space
        )
        ;

    identifier =
        *(anychar_p - (space_p | ']'))
        ;

    code =
        code_line >> *(*eol_p >> code_line)
        ;

    code_line =
        ((ch_p(' ') | '\t'))
        >> *(anychar_p - eol_p) >> eol_p
        ;

    unordered_list =
        +('*' >> space >> line)
        ;

    ordered_list =
        +('#' >> space >> line)
        ;

    common =
            self.actions.macro
        |   phrase_markup
        |   escape
        |   comment
        ;

    line =
       *(   common
        |   (anychar_p - eol_p)
        )
        >> +eol_p
        ;

    paragraph =
       *(   common
        |   (   anychar_p
                - (eol_p >> eol_p)
            )
        )
        >> +eol_p
        ;

    phrase =
       *(   common
        |   comment
        |   (anychar_p - ']')
        )
        ;

    phrase_markup =
            '['
        >>  (   image
            |   link
            |   bold
            |   italic
            |   underline
            |   teletype
            |   str_p("br")
            |   unexpected
            )
        >>  ']'
        ;

    escape =
            (
                "'''"
            >>  *(anychar_p - "'''")
            >>  "'''"
            )
        |   (
                "\"'"
            >>  *(anychar_p - "\"'")
            >>  "\"'"
            )
        ;

    image =
            '$' >> space
        >> (*(anychar_p - ']'))
        ;

    link =
            '@'
        >>  (*(anychar_p - space))
        >>  space >> phrase
        ;

    bold =
            ch_p('*')
        >>  space >> phrase
        ;

    italic =
            ch_p('\'')
        >>  space >> phrase
        ;

    underline =
            ch_p('_')
        >>  space >> phrase
        ;

    teletype =
            ch_p('^')
        >>  space >> phrase
        ;

    unexpected =
        (*(anychar_p - ']'))
        ;