Recursive-descent Textile parser in Ruby

operand = operand1+ ?;

operand1 =

<text>

| '[==', operand, '==]'
| '[bq=", <author>, '"]', operand, '[/bq]'
| '[bq]', operand, '[/bq]'
| '[spoiler]', operand, '[/spoiler]'
| '==', operand, '=='

| link
| image

| '[**', operand, '**]' | '**', operand, '**'
| '[*', operand, '*]' | '*', operand, '*'
| '[__', operand, '__]' | '__', operand, '__'
| '[_', operand, '_]' | '_', operand, '_'
| '[@', operand, '@]' | '@', operand, '@'
| '[+', operand, '+]' | '+', operand, '+'
| '[^', operand, '^]' | '^', operand, '^'
| '[-', operand, '-]' | '-', operand, '-'
| '[~', operand, '~]' | '~', operand, '~'
| '[??', operand, '??]' | '??', operand, '??'
;

link =

  '["', operand, '(', <text>, ')":', <url>, ']'
| '"', operand, '(', <text>, ')":', <url>
| '["', operand, '":', <url>, ']'
| '"', operand, '":', <url>;

image =

  '[!', <url>, '(', <text>, ')!:', <url>, ']'
| '!', <url>, '(', <text>, ')!:', <url>
| '[!', <url>, '(', <text>, ')!]'
| '!', <url>, '(', <text>, ')!'
| '[!', <url>, '!]'
| '!', <url>, '!';