diff --git a/lib/gherkin_ruby/parser/gherkin.rex b/lib/gherkin_ruby/parser/gherkin.rex index 7354dc5..c5358f5 100644 --- a/lib/gherkin_ruby/parser/gherkin.rex +++ b/lib/gherkin_ruby/parser/gherkin.rex @@ -19,7 +19,7 @@ rule Scenario: { [:SCENARIO, text[0..-2]] } # Tags - @(\w|-)+ { [:TAG, text[1..-1]] } + @(\w|-|:)+ { [:TAG, text[1..-1]] } # Step keywords Given { [:GIVEN, text] } @@ -27,6 +27,7 @@ rule Then { [:THEN, text] } And { [:AND, text] } But { [:BUT, text] } + \* { [:STAR, text] } # Text [^#\n]* { [:TEXT, text.strip] } diff --git a/lib/gherkin_ruby/parser/gherkin.y b/lib/gherkin_ruby/parser/gherkin.y index 3657789..33d8614 100644 --- a/lib/gherkin_ruby/parser/gherkin.y +++ b/lib/gherkin_ruby/parser/gherkin.y @@ -6,7 +6,7 @@ class GherkinRuby::Parser token NEWLINE token FEATURE BACKGROUND SCENARIO token TAG -token GIVEN WHEN THEN AND BUT +token GIVEN WHEN THEN AND BUT STAR token TEXT rule @@ -73,7 +73,7 @@ rule ; Keyword: - GIVEN | WHEN | THEN | AND | BUT + GIVEN | WHEN | THEN | AND | BUT | STAR ; Scenarios: diff --git a/lib/gherkin_ruby/parser/lexer.rb b/lib/gherkin_ruby/parser/lexer.rb index 30baac3..673dbed 100644 --- a/lib/gherkin_ruby/parser/lexer.rb +++ b/lib/gherkin_ruby/parser/lexer.rb @@ -1,113 +1,117 @@ #-- # DO NOT MODIFY!!!! -# This file is automatically generated by rex 1.0.5 -# from lexical definition file "lib/gherkin_ruby/parser/gherkin.rex". +# This file is automatically generated by rex 1.0.7 +# from lexical definition file "gherkin.rex". #++ require 'racc/parser' # Compile with: rex gherkin.rex -o lexer.rb class GherkinRuby::Parser < Racc::Parser - require 'strscan' + require 'strscan' - class ScanError < StandardError ; end + class ScanError < StandardError ; end - attr_reader :lineno - attr_reader :filename - attr_accessor :state + attr_reader :lineno + attr_reader :filename + attr_accessor :state - def scan_setup(str) - @ss = StringScanner.new(str) - @lineno = 1 - @state = nil - end + def scan_setup(str) + @ss = StringScanner.new(str) + @lineno = 1 + @state = nil + end - def action - yield - end + def action + yield + end - def scan_str(str) - scan_setup(str) - do_parse - end - alias :scan :scan_str + def scan_str(str) + scan_setup(str) + do_parse + end + alias :scan :scan_str - def load_file( filename ) - @filename = filename - open(filename, "r") do |f| - scan_setup(f.read) - end - end + def load_file( filename ) + @filename = filename + File.open(filename, "r") do |f| + scan_setup(f.read) + end + end - def scan_file( filename ) - load_file(filename) - do_parse - end + def scan_file( filename ) + load_file(filename) + do_parse + end - def next_token - return if @ss.eos? - - # skips empty actions - until token = _next_token or @ss.eos?; end - token - end + def next_token + return if @ss.eos? + + # skips empty actions + until token = _next_token or @ss.eos?; end + token + end + + def _next_token + text = @ss.peek(1) + @lineno += 1 if text == "\n" + token = case @state + when nil + case + when (text = @ss.scan(/[ \t]+/)) + ; - def _next_token - text = @ss.peek(1) - @lineno += 1 if text == "\n" - token = case @state - when nil - case - when (text = @ss.scan(/[ \t]+/)) - ; + when (text = @ss.scan(/\#.*$/)) + ; - when (text = @ss.scan(/\#.*$/)) - ; + when (text = @ss.scan(/\n/)) + action { [:NEWLINE, text] } - when (text = @ss.scan(/\n/)) - action { [:NEWLINE, text] } + when (text = @ss.scan(/Feature:/)) + action { [:FEATURE, text[0..-2]] } - when (text = @ss.scan(/Feature:/)) - action { [:FEATURE, text[0..-2]] } + when (text = @ss.scan(/Background:/)) + action { [:BACKGROUND, text[0..-2]] } - when (text = @ss.scan(/Background:/)) - action { [:BACKGROUND, text[0..-2]] } + when (text = @ss.scan(/Scenario:/)) + action { [:SCENARIO, text[0..-2]] } - when (text = @ss.scan(/Scenario:/)) - action { [:SCENARIO, text[0..-2]] } + when (text = @ss.scan(/@(\w|-|:)+/)) + action { [:TAG, text[1..-1]] } - when (text = @ss.scan(/@(\w|-)+/)) - action { [:TAG, text[1..-1]] } + when (text = @ss.scan(/Given/)) + action { [:GIVEN, text] } - when (text = @ss.scan(/Given/)) - action { [:GIVEN, text] } + when (text = @ss.scan(/When/)) + action { [:WHEN, text] } - when (text = @ss.scan(/When/)) - action { [:WHEN, text] } + when (text = @ss.scan(/Then/)) + action { [:THEN, text] } - when (text = @ss.scan(/Then/)) - action { [:THEN, text] } + when (text = @ss.scan(/And/)) + action { [:AND, text] } - when (text = @ss.scan(/And/)) - action { [:AND, text] } + when (text = @ss.scan(/But/)) + action { [:BUT, text] } - when (text = @ss.scan(/But/)) - action { [:BUT, text] } + when (text = @ss.scan(/\*/)) + action { [:STAR, text] } - when (text = @ss.scan(/[^#\n]*/)) - action { [:TEXT, text.strip] } + when (text = @ss.scan(/[^#\n]*/)) + action { [:TEXT, text.strip] } - else - text = @ss.string[@ss.pos .. -1] - raise ScanError, "can not match: '" + text + "'" - end # if + + else + text = @ss.string[@ss.pos .. -1] + raise ScanError, "can not match: '" + text + "'" + end # if - else - raise ScanError, "undefined state: '" + state.to_s + "'" - end # case state - token - end # def _next_token + else + raise ScanError, "undefined state: '" + state.to_s + "'" + end # case state + token + end # def _next_token def tokenize(code) scan_setup(code) diff --git a/lib/gherkin_ruby/parser/parser.rb b/lib/gherkin_ruby/parser/parser.rb index 515c289..30a0417 100644 --- a/lib/gherkin_ruby/parser/parser.rb +++ b/lib/gherkin_ruby/parser/parser.rb @@ -1,7 +1,7 @@ # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.4.11 -# from Racc grammer file "". +# This file is automatically generated by Racc 1.6.2 +# from Racc grammar file "". # require 'racc/parser.rb' @@ -22,58 +22,60 @@ def parse(input) ##### State transition tables begin ### racc_action_table = [ - 18, 18, 20, 4, 26, 10, 18, 21, 14, 10, - 43, 36, 37, 38, 39, 40, 18, 18, 14, 10, - 45, 36, 37, 38, 39, 40, 18, 14, 10, 4, - 9, 36, 37, 38, 39, 40, 36, 37, 38, 39, - 40, 4, 9, 14, 10, 10, 18, 20, 32, 24, - 21, 4, 4, 29, 21, 4, 47, 18, 48, 4, - 27, 51, 11, 4, 18, 4, 18, 4 ] + 18, 36, 37, 38, 39, 40, 41, 18, 14, 10, + 11, 44, 36, 37, 38, 39, 40, 41, 18, 18, + 4, 9, 46, 36, 37, 38, 39, 40, 41, 18, + 14, 10, 14, 10, 36, 37, 38, 39, 40, 41, + 4, 9, 18, 20, 10, 4, 10, 18, 20, 21, + 14, 10, 21, 24, 4, 26, 27, 29, 21, 32, + 4, 4, 4, 48, 18, 49, 4, 52, 4, 18, + 4, 18 ] racc_action_check = [ - 25, 5, 5, 15, 9, 5, 54, 15, 31, 31, - 25, 54, 54, 54, 54, 54, 44, 30, 12, 12, - 30, 44, 44, 44, 44, 44, 46, 2, 2, 3, - 3, 46, 46, 46, 46, 46, 23, 23, 23, 23, - 23, 0, 0, 16, 16, 0, 17, 17, 20, 7, - 6, 8, 29, 14, 19, 34, 35, 41, 42, 43, - 11, 45, 1, 48, 49, 51, 53, 24 ] + 25, 23, 23, 23, 23, 23, 23, 45, 2, 2, + 1, 25, 45, 45, 45, 45, 45, 45, 47, 30, + 3, 3, 30, 47, 47, 47, 47, 47, 47, 55, + 12, 12, 16, 16, 55, 55, 55, 55, 55, 55, + 0, 0, 5, 5, 0, 15, 5, 17, 17, 15, + 31, 31, 6, 7, 8, 9, 11, 14, 19, 20, + 24, 29, 34, 35, 42, 43, 44, 46, 49, 50, + 52, 54 ] racc_action_pointer = [ - 39, 62, 22, 27, nil, -1, 44, 45, 49, -8, - nil, 60, 13, nil, 41, 1, 38, 44, nil, 48, - 36, nil, nil, 29, 65, -2, nil, nil, nil, 50, - 15, 3, nil, nil, 53, 44, nil, nil, nil, nil, - nil, 55, 46, 57, 14, 49, 24, nil, 61, 62, - nil, 63, nil, 64, 4, nil ] + 38, 10, 3, 18, nil, 40, 46, 49, 52, 42, + nil, 56, 25, nil, 44, 43, 27, 45, nil, 52, + 46, nil, nil, -6, 58, -2, nil, nil, nil, 59, + 17, 45, nil, nil, 60, 50, nil, nil, nil, nil, + nil, nil, 62, 52, 64, 5, 54, 16, nil, 66, + 67, nil, 68, nil, 69, 27, nil ] racc_action_default = [ - -35, -35, -1, -35, -5, -35, -7, -9, -11, -35, - -33, -35, -2, -29, -35, -35, -3, -35, -6, -8, - -35, -34, -10, -35, -35, -12, -14, 56, -30, -35, - -35, -4, -15, -18, -20, -35, -24, -25, -26, -27, - -28, -19, -13, -35, -35, -35, -21, -23, -35, -16, - -31, -35, -22, -17, -35, -32 ] + -36, -36, -1, -36, -5, -36, -7, -9, -11, -36, + -34, -36, -2, -30, -36, -36, -3, -36, -6, -8, + -36, -35, -10, -36, -36, -12, -14, 57, -31, -36, + -36, -4, -15, -18, -20, -36, -24, -25, -26, -27, + -28, -29, -19, -13, -36, -36, -36, -21, -23, -36, + -16, -32, -36, -22, -17, -36, -33 ] racc_goto_table = [ - 5, 28, 33, 17, 12, 6, 2, 23, 25, 16, - 19, 42, 22, 3, 1, 30, nil, nil, 31, nil, - 28, nil, nil, 50, 41, 52, nil, nil, nil, 44, - nil, nil, nil, 55, 46, nil, nil, nil, nil, nil, - nil, nil, nil, 49, nil, nil, nil, nil, 53, nil, - nil, 54 ] + 5, 33, 28, 17, 12, 6, 2, 1, 25, 16, + 19, 3, 22, 43, 23, 30, nil, nil, 31, nil, + nil, 28, nil, 51, 42, 53, nil, nil, nil, 45, + nil, nil, nil, 56, 47, nil, nil, nil, nil, nil, + nil, nil, nil, nil, 50, nil, nil, nil, nil, 54, + nil, nil, 55 ] racc_goto_check = [ - 5, 15, 12, 5, 3, 6, 2, 11, 5, 2, - 6, 10, 8, 4, 1, 5, nil, nil, 3, nil, - 15, nil, nil, 12, 5, 12, nil, nil, nil, 5, + 5, 12, 15, 5, 3, 6, 2, 1, 5, 2, + 6, 4, 8, 10, 11, 5, nil, nil, 3, nil, + nil, 15, nil, 12, 5, 12, nil, nil, nil, 5, nil, nil, nil, 12, 5, nil, nil, nil, nil, nil, - nil, nil, nil, 5, nil, nil, nil, nil, 5, nil, - nil, 5 ] + nil, nil, nil, nil, 5, nil, nil, nil, nil, 5, + nil, nil, 5 ] racc_goto_pointer = [ - nil, 14, 6, 2, 13, 0, 5, nil, 5, nil, - -14, 0, -21, nil, nil, -11 ] + nil, 7, 6, 2, 11, 0, 5, nil, 5, nil, + -12, 7, -22, nil, nil, -10 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, 15, 7, nil, 8, @@ -81,44 +83,45 @@ def parse(input) racc_reduce_table = [ 0, 0, :racc_error, - 1, 14, :_reduce_1, - 2, 14, :_reduce_2, - 2, 14, :_reduce_3, - 3, 14, :_reduce_4, - 1, 18, :_reduce_none, - 2, 18, :_reduce_none, - 1, 17, :_reduce_7, - 2, 17, :_reduce_8, - 1, 15, :_reduce_9, - 2, 15, :_reduce_10, - 1, 20, :_reduce_11, - 2, 20, :_reduce_12, - 3, 20, :_reduce_13, - 2, 22, :_reduce_14, - 3, 22, :_reduce_15, - 2, 23, :_reduce_16, - 3, 23, :_reduce_17, - 2, 21, :_reduce_18, - 2, 24, :_reduce_19, - 1, 25, :_reduce_20, - 2, 25, :_reduce_21, - 3, 25, :_reduce_22, - 2, 26, :_reduce_23, - 1, 27, :_reduce_none, - 1, 27, :_reduce_none, - 1, 27, :_reduce_none, - 1, 27, :_reduce_none, - 1, 27, :_reduce_none, - 1, 16, :_reduce_29, - 2, 16, :_reduce_30, - 4, 28, :_reduce_31, - 6, 28, :_reduce_32, - 1, 19, :_reduce_33, - 2, 19, :_reduce_34 ] - -racc_reduce_n = 35 - -racc_shift_n = 56 + 1, 15, :_reduce_1, + 2, 15, :_reduce_2, + 2, 15, :_reduce_3, + 3, 15, :_reduce_4, + 1, 19, :_reduce_none, + 2, 19, :_reduce_none, + 1, 18, :_reduce_7, + 2, 18, :_reduce_8, + 1, 16, :_reduce_9, + 2, 16, :_reduce_10, + 1, 21, :_reduce_11, + 2, 21, :_reduce_12, + 3, 21, :_reduce_13, + 2, 23, :_reduce_14, + 3, 23, :_reduce_15, + 2, 24, :_reduce_16, + 3, 24, :_reduce_17, + 2, 22, :_reduce_18, + 2, 25, :_reduce_19, + 1, 26, :_reduce_20, + 2, 26, :_reduce_21, + 3, 26, :_reduce_22, + 2, 27, :_reduce_23, + 1, 28, :_reduce_none, + 1, 28, :_reduce_none, + 1, 28, :_reduce_none, + 1, 28, :_reduce_none, + 1, 28, :_reduce_none, + 1, 28, :_reduce_none, + 1, 17, :_reduce_30, + 2, 17, :_reduce_31, + 4, 29, :_reduce_32, + 6, 29, :_reduce_33, + 1, 20, :_reduce_34, + 2, 20, :_reduce_35 ] + +racc_reduce_n = 36 + +racc_shift_n = 57 racc_token_table = { false => 0, @@ -133,9 +136,10 @@ def parse(input) :THEN => 9, :AND => 10, :BUT => 11, - :TEXT => 12 } + :STAR => 12, + :TEXT => 13 } -racc_nt_base = 13 +racc_nt_base = 14 racc_use_result_var = true @@ -168,6 +172,7 @@ def parse(input) "THEN", "AND", "BUT", + "STAR", "TEXT", "$start", "Root", @@ -194,28 +199,28 @@ def parse(input) module_eval(<<'.,.,', 'gherkin.y', 14) def _reduce_1(val, _values, result) - result = val[0]; + result = val[0]; result end .,., module_eval(<<'.,.,', 'gherkin.y', 17) def _reduce_2(val, _values, result) - result = val[0]; result.scenarios = val[1] + result = val[0]; result.scenarios = val[1] result end .,., module_eval(<<'.,.,', 'gherkin.y', 18) def _reduce_3(val, _values, result) - result = val[1]; result.tags = val[0] + result = val[1]; result.tags = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 20) def _reduce_4(val, _values, result) - result = val[1]; result.scenarios = val[2]; result.tags = val[0] + result = val[1]; result.scenarios = val[2]; result.tags = val[0] result end .,., @@ -226,119 +231,119 @@ def _reduce_4(val, _values, result) module_eval(<<'.,.,', 'gherkin.y', 29) def _reduce_7(val, _values, result) - result = val[0] + result = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 30) def _reduce_8(val, _values, result) - result = val[1] + result = val[1] result end .,., module_eval(<<'.,.,', 'gherkin.y', 33) def _reduce_9(val, _values, result) - result = val[0] + result = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 35) def _reduce_10(val, _values, result) - result = val[0]; result.background = val[1] + result = val[0]; result.background = val[1] result end .,., module_eval(<<'.,.,', 'gherkin.y', 39) def _reduce_11(val, _values, result) - result = val[0] + result = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 40) def _reduce_12(val, _values, result) - result = val[0] + result = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 42) def _reduce_13(val, _values, result) - result = val[0]; result.description = val[2] + result = val[0]; result.description = val[2] result end .,., module_eval(<<'.,.,', 'gherkin.y', 46) def _reduce_14(val, _values, result) - result = AST::Feature.new(val[1]); result.pos(filename, lineno) + result = AST::Feature.new(val[1]); result.pos(filename, lineno) result end .,., module_eval(<<'.,.,', 'gherkin.y', 47) def _reduce_15(val, _values, result) - result = AST::Feature.new(val[2]); result.pos(filename, lineno) + result = AST::Feature.new(val[2]); result.pos(filename, lineno) result end .,., module_eval(<<'.,.,', 'gherkin.y', 51) def _reduce_16(val, _values, result) - result = val[0] + result = val[0] result end .,., module_eval(<<'.,.,', 'gherkin.y', 52) def _reduce_17(val, _values, result) - result = val[0...-1].flatten + result = val[0...-1].flatten result end .,., module_eval(<<'.,.,', 'gherkin.y', 57) def _reduce_18(val, _values, result) - result = val[0]; result.steps = val[1] + result = val[0]; result.steps = val[1] result end .,., module_eval(<<'.,.,', 'gherkin.y', 61) def _reduce_19(val, _values, result) - result = AST::Background.new; result.pos(filename, lineno) + result = AST::Background.new; result.pos(filename, lineno) result end .,., module_eval(<<'.,.,', 'gherkin.y', 65) def _reduce_20(val, _values, result) - result = [val[0]] + result = [val[0]] result end .,., module_eval(<<'.,.,', 'gherkin.y', 66) def _reduce_21(val, _values, result) - result = [val[0]] + result = [val[0]] result end .,., module_eval(<<'.,.,', 'gherkin.y', 67) def _reduce_22(val, _values, result) - val[2].unshift(val[0]); result = val[2] + val[2].unshift(val[0]); result = val[2] result end .,., module_eval(<<'.,.,', 'gherkin.y', 71) def _reduce_23(val, _values, result) - result = AST::Step.new(val[1], val[0]); result.pos(filename, lineno) + result = AST::Step.new(val[1], val[0]); result.pos(filename, lineno) result end .,., @@ -353,44 +358,46 @@ def _reduce_23(val, _values, result) # reduce 28 omitted +# reduce 29 omitted + module_eval(<<'.,.,', 'gherkin.y', 79) - def _reduce_29(val, _values, result) - result = [val[0]] + def _reduce_30(val, _values, result) + result = [val[0]] result end .,., module_eval(<<'.,.,', 'gherkin.y', 80) - def _reduce_30(val, _values, result) - result = val[0] << val[1] + def _reduce_31(val, _values, result) + result = val[0] << val[1] result end .,., module_eval(<<'.,.,', 'gherkin.y', 85) - def _reduce_31(val, _values, result) - result = AST::Scenario.new(val[1], val[3]); result.pos(filename, lineno - 1) + def _reduce_32(val, _values, result) + result = AST::Scenario.new(val[1], val[3]); result.pos(filename, lineno - 1) result end .,., module_eval(<<'.,.,', 'gherkin.y', 88) - def _reduce_32(val, _values, result) - result = AST::Scenario.new(val[3], val[5], val[0]); result.pos(filename, lineno - 2) + def _reduce_33(val, _values, result) + result = AST::Scenario.new(val[3], val[5], val[0]); result.pos(filename, lineno - 2) result end .,., module_eval(<<'.,.,', 'gherkin.y', 92) - def _reduce_33(val, _values, result) - result = [AST::Tag.new(val[0])] + def _reduce_34(val, _values, result) + result = [AST::Tag.new(val[0])] result end .,., module_eval(<<'.,.,', 'gherkin.y', 93) - def _reduce_34(val, _values, result) - result = val[0] << AST::Tag.new(val[1]) + def _reduce_35(val, _values, result) + result = val[0] << AST::Tag.new(val[1]) result end .,., @@ -400,4 +407,4 @@ def _reduce_none(val, _values, result) end end # class Parser - end # module GherkinRuby +end # module GherkinRuby diff --git a/test/gherkin/parser/parser_test.rb b/test/gherkin/parser/parser_test.rb index 6f3d1eb..ac9acbf 100644 --- a/test/gherkin/parser/parser_test.rb +++ b/test/gherkin/parser/parser_test.rb @@ -111,8 +111,8 @@ def parse(input) Feature: Do something Scenario: Foo bar baz - Given blah foo bar - Then something else + * blah foo bar + * something else @javascript @wip @with-vcr Scenario: Foo bar baz blah