diff --git a/bbsandbox.rb b/bbsandbox.rb
index f1cdcbe..ee213f5 100644
--- a/bbsandbox.rb
+++ b/bbsandbox.rb
@@ -3,8 +3,9 @@ require 'slim'
require 'digest/sha1'
require 'bb-ruby'
require 'ruby-bbcode'
+require './bristlecode.rb'
-@@engines = ['bb-ruby', 'ruby-bbcode', 'raw']
+@@engines = ['bb-ruby', 'ruby-bbcode', 'bristle', 'raw']
get '/' do
@posts = list_posts
@@ -35,6 +36,8 @@ def exec_bbcode(engine, body)
BBRuby.to_html body
when "ruby-bbcode"
RubyBBCode.to_html body
+ when "bristle"
+ Bristlecode::to_html body
when "raw"
body
else
diff --git a/bristlecode.rb b/bristlecode.rb
new file mode 100644
index 0000000..c668e5e
--- /dev/null
+++ b/bristlecode.rb
@@ -0,0 +1,109 @@
+require 'parslet'
+
+module Bristlecode
+
+ def Bristlecode.to_html(text)
+ parser = Bristlecode::Parser.new
+ parse_tree = parser.parse(text)
+ tree = Bristlecode::Transform.new.apply(parse_tree)
+ tree.to_html
+ end
+
+ class Parser < Parslet::Parser
+ rule(:space) { match('\s').repeat(1) }
+ rule(:space?) { space.maybe }
+
+ rule(:bold_open) {
+ (str('[b]') | str('[B]'))
+ }
+ rule(:bold_close) {
+ (str('[/b]') | str('[/B]'))
+ }
+ rule(:bold) {
+ (bold_open >> children.as(:bold) >> bold_close)
+ }
+
+ rule(:italic_open) {
+ (str('[i]') | str('[I]'))
+ }
+ rule(:italic_close) {
+ (str('[/i]') | str('[/I]'))
+ }
+ rule(:italic) {
+ (italic_open >> children.as(:italic) >> italic_close)
+ }
+
+ rule(:eof) { any.absent? }
+ rule(:tag) { (bold | italic) }
+ rule(:elem) { text | tag }
+ rule(:tag_open) { bold_open | italic_open }
+ rule(:tag_close) { bold_close | italic_close }
+ rule(:tag_delim) { tag_open | tag_close }
+
+ rule(:text) { (tag_delim.absent? >> any).repeat(1).as(:text) }
+ rule(:children) {
+ space? >> elem.repeat(1)
+ }
+ rule(:doc) {
+ space? >> elem.repeat(1).as(:doc)
+ }
+ root(:doc)
+ end
+
+ class Transform < Parslet::Transform
+ rule(bold: sequence(:children)) { Bold.new(children) }
+ rule(italic: sequence(:children)) { Italic.new(children) }
+ rule(text: simple(:text)) { Text.new(text) }
+ rule(doc: subtree(:doc)) { Doc.new(doc) }
+ end
+
+ class Doc
+ def initialize(children)
+ @children = children
+ end
+
+ def to_html
+ s = StringIO.new
+ @children.each{|child| s << child.to_html }
+ s.string
+ end
+ end
+
+ class Text
+ def initialize(text)
+ @text = text
+ end
+
+ def to_html
+ @text
+ end
+ end
+
+ class Bold
+ def initialize(children)
+ @children = children
+ end
+
+ def to_html
+ s = StringIO.new
+ s << ""
+ @children.each{|child| s << child.to_html }
+ s << ""
+ s.string
+ end
+ end
+
+ class Italic
+ def initialize(children)
+ @children = children
+ end
+
+ def to_html
+ s = StringIO.new
+ s << ""
+ @children.each{|child| s << child.to_html }
+ s << ""
+ s.string
+ end
+ end
+end