Create a gist now

Instantly share code, notes, and snippets.

Cucumber treetop grammar
module Cucumber
# :stopdoc:
module TreetopParser
grammar Feature
rule root
space? header scenario_sequence space? {
def compile
feature_elements = scenario_sequence.compile
feature = Cucumber::Ast::Feature.new(nil, nil, header.text_value.strip, feature_elements)
feature
end
}
end
rule header
(!(scenario_keyword / scenario_outline_keyword / comment_to_eol) .)+
end
rule scenario_sequence
head:scenario_outline_or_scenario? tail:(space scenario_or_scenario_outline)* {
def compile
sequence = []
([head] + tail).each do |scenario_or_scenario_outline|
sequence << scenario_or_scenario_outline.compile if scenario_or_scenario_outline.respond_to?(:compile)
end
sequence
end
def tail
super.elements.map { |elt| elt.scenario_or_scenario_outline }
end
}
end
rule scenario_outline_or_scenario
scenario_outline / scenario
end
rule scenario
scenario_keyword space? name:line_to_eol steps:(space step_sequence)? table:(space examples)? {
def compile
step_names_and_inline_args = []
step_names_and_inline_args = steps.step_sequence.compile if steps.respond_to?(:step_sequence)
#TODO: compile table
Ast::Scenario.new(@step_mother, nil, nil, name.text_value.strip, step_names_and_inline_args)
end
}
end
rule scenario_outline
scenario_outline_keyword space? name:line_to_eol steps:(space step_sequence)? table:(space examples) {
def compile
step_names = []
matrix = []
step_names = steps.step_sequence.compile if steps.respond_to?(:step_sequence)
matrix = table.examples.compile if table.respond_to?(:examples)
Ast::ScenarioOutline.new(@step_mother, nil, nil, name.text_value.strip, step_names, matrix)
end
}
end
rule scenario_or_scenario_outline
scenario_outline / scenario
end
rule examples
(more_examples_keyword / examples_keyword) table {
def compile
table.compile
end
}
end
rule table
space head:table_line body:(blank* eol space? table_line)* {
def compile
([head] + body).map do |table_line|
table_line.cell_values
end
end
def line
input.line_of(interval.first)
end
def body
super.elements.map { |elt| elt.table_line }
end
}
end
rule table_line
separator cells:(blank* cell_value blank* separator)+ {
def cell_values
cells.elements.map { |elt| elt.cell_value.text_value.strip }
end
def line
input.line_of(interval.first)
end
}
end
rule cell_value
(!(separator / eol) .)*
end
rule step_sequence
head:step tail:(space step)* {
def compile
([head] + tail).map do |step|
step.compile
end
end
def tail
super.elements.map { |elt| elt.step }
end
}
end
rule step
given_scenario / plain_step
end
rule given_scenario
given_scenario_keyword space? name:line_to_eol {
def compile
end
}
end
rule plain_step
step_keyword space? name:line_to_eol multi:multiline_arg? {
def compile
step_data = [step_keyword.text_value.strip, name.text_value.strip]
step_data += [multi.compile] if multi.respond_to?(:compile)
step_data
end
}
end
rule multiline_arg
table / multiline_string
end
rule multiline_string
eol indent:space triple_quote string:(!triple_quote .)* triple_quote {
def compile
indent_length = indent.text_value.length
significant_lines = string.text_value.split("\n")[1..-2]
significant_lines.map do |l|
l[indent_length..-1]
end.join("\n")
end
}
end
rule triple_quote
'"""'
end
rule separator
'|'
end
rule space
(white / comment_to_eol)+
end
rule line_to_eol
(!eol .)*
end
rule comment_to_eol
'#' line_to_eol
end
rule white
blank / eol
end
rule blank
[ \t]
end
rule eol
("\r" "\n"?) / "\n"
end
rule step_keyword
"<%= words['given'] %>" / "<%= words['when'] %>" / "<%= words['then'] %>" / "<%= words['and'] %>" / "<%= words['but'] %>"
end
rule scenario_keyword
"<%= words['scenario'] %>" ":"?
end
rule scenario_outline_keyword
"<%= words['scenario_outline'] %>" ":"?
end
rule more_examples_keyword
"<%= words['more_examples'] %>" ":"?
end
rule examples_keyword
"<%= words['examples'] %>" ":"?
end
rule given_scenario_keyword
"<%= words['given_scenario'] %>" ":"?
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment