diff --git a/lib/rouge/demos/brainfuck b/lib/rouge/demos/brainfuck new file mode 100644 index 0000000000..8021cc136a --- /dev/null +++ b/lib/rouge/demos/brainfuck @@ -0,0 +1,5 @@ +[ + This is a sample + comment. +] +.[>+<-]>, \ No newline at end of file diff --git a/lib/rouge/lexers/brainfuck.rb b/lib/rouge/lexers/brainfuck.rb new file mode 100644 index 0000000000..e0d1384bfa --- /dev/null +++ b/lib/rouge/lexers/brainfuck.rb @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class Brainfuck < RegexLexer + tag 'brainfuck' + filenames '*.b', '*.bf' + mimetypes 'text/x-brainfuck' + + title "Brainfuck" + desc "The Brainfuck programming language" + + start { push :bol } + + state :bol do + rule /\s+/m, Text + rule /\[/, Comment::Multiline, :comment_multi + rule(//) { pop! } + end + + state :root do + rule /\]/, Error + rule /\[/, Punctuation, :loop + + mixin :comment_single + mixin :commands + end + + state :comment_multi do + rule /\[/, Comment::Multiline, :comment_multi + rule /\]/, Comment::Multiline, :pop! + rule /[^\[\]]+?/m, Comment::Multiline + end + + state :comment_single do + rule /[^><+\-.,\[\]]+/, Comment::Single + end + + state :loop do + rule /\[/, Punctuation, :loop + rule /\]/, Punctuation, :pop! + mixin :comment_single + mixin :commands + end + + state :commands do + rule /[><]+/, Name::Builtin + rule /[+\-.,]+/, Name::Function + end + end + end +end diff --git a/spec/lexers/brainfuck_spec.rb b/spec/lexers/brainfuck_spec.rb new file mode 100644 index 0000000000..fb351439db --- /dev/null +++ b/spec/lexers/brainfuck_spec.rb @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::Brainfuck do + let(:subject) { Rouge::Lexers::Brainfuck.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.b' + assert_guess :filename => 'FOO.bf', :source => 'foo' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-brainfuck' + end + end + + describe 'lexing' do + include Support::Lexing + + it 'recognizes one-line comments not followed by a newline (#796)' do + assert_tokens_equal 'comment', ['Comment.Single', 'comment'] + end + end +end diff --git a/spec/visual/samples/brainfuck b/spec/visual/samples/brainfuck new file mode 100644 index 0000000000..69e8f3e8dc --- /dev/null +++ b/spec/visual/samples/brainfuck @@ -0,0 +1,20 @@ +[ +This program will print "Hello world!" +] +++++++++++ +[ + >+++++++>++++++++++>+++>+<<<<- +] +>++. Initial loop (it will be printed an H) +>+. e ++++++++. l +. l ++++. o +>++. space +<<+++++++++++++++. W +>. o ++++. r +------. l +--------. d +>+. ! +>. \ No newline at end of file