Skip to content

Instantly share code, notes, and snippets.

@DVG
Created December 10, 2012 19:51
Show Gist options
  • Save DVG/4252885 to your computer and use it in GitHub Desktop.
Save DVG/4252885 to your computer and use it in GitHub Desktop.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment