module Cucumber module Parser # TIP: When you hack on the grammar, just delete feature.rb in this directory. # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber # github gems). # # Treetop will then generate the parser in-memory. When you're happy, just generate # the rb file with tt feature.tt grammar Feature include I18n include Table rule feature white comment white tags white header:(!(scenario_outline / scenario / background) .)* background:(background)? feature_elements comment? { def build if background.respond_to?(:build) Ast::Feature.new(comment.build, tags.build, header.text_value, feature_elements.build, background.build) else Ast::Feature.new(comment.build, tags.build, header.text_value, feature_elements.build) end end } end rule tags white ts:(tag (space/eol)+)* { def build tag_names = ts.elements.map{|e| e.tag.tag_name.text_value} Ast::Tags.new(ts.line, tag_names) end } end rule tag '@' tag_name:([a-z0-9])+ end rule comment (comment_line white)* { def build Ast::Comment.new(text_value) end } end rule comment_line '#' line_to_eol end rule background comment white background_keyword space* (eol+ / eof) steps { def build Ast::Background.new( comment.build, background_keyword.line, background_keyword.text_value, steps.build ) end } end rule feature_elements (scenario / scenario_outline)* { def build elements.map{|s| s.build} end } end rule scenario comment tags white scenario_keyword space* name:line_to_eol (eol+ / eof) steps white { def build Ast::Scenario.new( comment.build, tags.build, scenario_keyword.line, scenario_keyword.text_value, name.text_value, steps.build ) end } end rule scenario_outline comment tags white scenario_outline_keyword space* name:line_to_eol white steps examples_sections white { def build Ast::ScenarioOutline.new( comment.build, tags.build, scenario_outline_keyword.line, scenario_outline_keyword.text_value, name.text_value, steps.build, examples_sections.build ) end } end rule steps step* { def build elements.map{|e| e.build} end } end rule step comment space* step_keyword space* name:line_to_eol (eol+ / eof) multi:multiline_arg? white { def build if multi.respond_to?(:build) Ast::Step.new(step_keyword.line, step_keyword.text_value, name.text_value, multi.build) else Ast::Step.new(step_keyword.line, step_keyword.text_value, name.text_value) end end } end rule examples_sections examples* { def build elements.map{|e| e.build} end } end rule examples space* examples_keyword space* name:line_to_eol? eol table white { def build [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw] end } end rule multiline_arg table / py_string end rule line_to_eol (!eol .)* end rule py_string open_py_string s:(!close_py_string .)* close_py_string { def build Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation) end } end rule open_py_string white '"""' space* eol { def indentation white.text_value.length end def line white.line end } end rule close_py_string eol space* quotes:'"""' white { def line quotes.line end } end rule white (space / eol)* end end end end