valid BBCOde Document
Hello World # => rule text
[b]I'd like to teach the world to dance[/b] # => rule expression
Also Valid
[b]Hello World[/b] # rule expression
I'd like to teach the world to dance # rule text
This too
[b]Hello World[/b] # rule expression
I'd like to teach the world to dance # rule text
[i]Some other nonsensical statement # rule expression
BBcodes can even be nested indefinitely
[b][i]Hello World[/i][/b] # rule expression (with recursive expression as :enclosed_expression)
Therefore a document is a series of ocilating BBCode Expressions and Plaintext, in no particular order
Rules:
rule(:open_tag) do
parslet = str('[')
parslet = parslet >> (str(']').absent? >> match("[a-zA-Z]")).repeat(1).as(:open_tag_name)
parslet = parslet >> str(']')
parslet
end
rule(:close_tag) do
parslet = str('[/')
parslet = parslet >> (str(']').absent? >> match("[a-zA-Z]")).repeat(1).as(:close_tag_name)
parslet = parslet >> str(']')
parslet
end
rule(:text) do
match("[a-zA-Z\s?]").repeat(1)
end
rule(:expression) do
open_tag >> (expression.as(:enclosed_expression) | text.as(:enclosed_text)) >> close_tag
end
rule(:document) do
(expression.repeat(1) >> text.maybe) | (text >> expression.repeat(0))
end
Testing
#bbcode expression
parser.document.parse("[b]Hello World[/b]") # => {:open_tag_name=>"b"@1, :enclosed_text=>"Hello World"@3, :close_tag_name=>"b"@16}
parser.document.parse("[b][i]Hello World[/i][/b]") # => {:open_tag_name=>"b"@1, :enclosed_expression=>{:open_tag_name=>"i"@4, :enclosed_text=>"Hello World"@6, :close_tag_name=>"i"@19}, :close_tag_name=>"b"@23}
parser.document.parse(" Yes Hello") # => " Yes hello"@0
# this fails
parser.document.parse("[b]Hello World[/b] Yes Hello")
# => Failure/Error: p parser.document.parse("[b]Hello World[/b] [i]Yes hello[/i]")
# Parslet::UnconsumedInput:
# Don't know what to do with "[i]Yes hel" at line 1 char 20.