lib/cucumber/cucumber_expressions/ast.rb
module Cucumber module CucumberExpressions ESCAPE_CHARACTER = '\\' ALTERNATION_CHARACTER = '/' BEGIN_PARAMETER_CHARACTER = '{' END_PARAMETER_CHARACTER = '}' BEGIN_OPTIONAL_CHARACTER = '(' END_OPTIONAL_CHARACTER = ')' class Node def initialize(type, nodes, token, start, _end) if nodes.nil? && token.nil? raise 'Either nodes or token must be defined' end @type = type @nodes = nodes @token = token @start = start @end = _end end def type @type end def nodes @nodes end def token @token end def start @start end def end @end end def text if @token.nil? return @nodes.map { |value| value.text }.join('') end @token end def to_hash hash = Hash.new hash["type"] = @type unless @nodes.nil? hash["nodes"] = @nodes.map { |node| node.to_hash } end unless @token.nil? hash["token"] = @token end hash["start"] = @start hash["end"] = @end hash end end module NodeType TEXT = 'TEXT_NODE' OPTIONAL = 'OPTIONAL_NODE' ALTERNATION = 'ALTERNATION_NODE' ALTERNATIVE = 'ALTERNATIVE_NODE' PARAMETER = 'PARAMETER_NODE' EXPRESSION = 'EXPRESSION_NODE' end class Token def initialize(type, text, start, _end) @type, @text, @start, @end = type, text, start, _end end def type @type end def text @text end def start @start end def end @end end def self.is_escape_character(codepoint) codepoint.chr(Encoding::UTF_8) == ESCAPE_CHARACTER end def self.can_escape(codepoint) c = codepoint.chr(Encoding::UTF_8) if c == ' ' # TODO: Unicode whitespace? return true end case c when ESCAPE_CHARACTER true when ALTERNATION_CHARACTER true when BEGIN_PARAMETER_CHARACTER true when END_PARAMETER_CHARACTER true when BEGIN_OPTIONAL_CHARACTER true when END_OPTIONAL_CHARACTER true else false end end def self.type_of(codepoint) c = codepoint.chr(Encoding::UTF_8) if c == ' ' # TODO: Unicode whitespace? return TokenType::WHITE_SPACE end case c when ALTERNATION_CHARACTER TokenType::ALTERNATION when BEGIN_PARAMETER_CHARACTER TokenType::BEGIN_PARAMETER when END_PARAMETER_CHARACTER TokenType::END_PARAMETER when BEGIN_OPTIONAL_CHARACTER TokenType::BEGIN_OPTIONAL when END_OPTIONAL_CHARACTER TokenType::END_OPTIONAL else TokenType::TEXT end end def self.symbol_of(token) case token when TokenType::BEGIN_OPTIONAL return BEGIN_OPTIONAL_CHARACTER when TokenType::END_OPTIONAL return END_OPTIONAL_CHARACTER when TokenType::BEGIN_PARAMETER return BEGIN_PARAMETER_CHARACTER when TokenType::END_PARAMETER return END_PARAMETER_CHARACTER when TokenType::ALTERNATION return ALTERNATION_CHARACTER else return '' end end def self.purpose_of(token) case token when TokenType::BEGIN_OPTIONAL return 'optional text' when TokenType::END_OPTIONAL return 'optional text' when TokenType::BEGIN_PARAMETER return 'a parameter' when TokenType::END_PARAMETER return 'a parameter' when TokenType::ALTERNATION return 'alternation' else return '' end end def to_hash { "type" => @type, "text" => @text, "start" => @start, "end" => @end } end end module TokenType START_OF_LINE = 'START_OF_LINE' END_OF_LINE = 'END_OF_LINE' WHITE_SPACE = 'WHITE_SPACE' BEGIN_OPTIONAL = 'BEGIN_OPTIONAL' END_OPTIONAL = 'END_OPTIONAL' BEGIN_PARAMETER = 'BEGIN_PARAMETER' END_PARAMETER = 'END_PARAMETER' ALTERNATION = 'ALTERNATION' TEXT = 'TEXT' end end end