8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/cucumber-cucumber-expressions-15.2.0/lib/cucumber/cucumber_expressions/cucumber_expression_parser.rb', line 8
def parse(expression)
parse_text = lambda do |_, tokens, current|
token = tokens[current]
case token.type
when TokenType::WHITE_SPACE, TokenType::TEXT, TokenType::END_PARAMETER, TokenType::END_OPTIONAL
return 1, [Node.new(NodeType::TEXT, nil, token.text, token.start, token.end)]
when TokenType::ALTERNATION
raise AlternationNotAllowedInOptional.new(expression, token)
when TokenType::BEGIN_PARAMETER, TokenType::START_OF_LINE, TokenType::END_OF_LINE, TokenType::BEGIN_OPTIONAL
else
return 0, nil
end
return 0, nil
end
parse_name = lambda do |_, tokens, current|
token = tokens[current]
case token.type
when TokenType::WHITE_SPACE, TokenType::TEXT
return 1, [Node.new(NodeType::TEXT, nil, token.text, token.start, token.end)]
when TokenType::BEGIN_PARAMETER, TokenType::END_PARAMETER, TokenType::BEGIN_OPTIONAL, TokenType::END_OPTIONAL, TokenType::ALTERNATION
raise InvalidParameterTypeNameInNode.new(expression, token)
when TokenType::START_OF_LINE, TokenType::END_OF_LINE
return 0, nil
else
return 0, nil
end
end
parse_parameter = parse_between(
NodeType::PARAMETER,
TokenType::BEGIN_PARAMETER,
TokenType::END_PARAMETER,
[parse_name]
)
optional_sub_parsers = []
parse_optional = parse_between(
NodeType::OPTIONAL,
TokenType::BEGIN_OPTIONAL,
TokenType::END_OPTIONAL,
optional_sub_parsers
)
optional_sub_parsers << parse_optional << parse_parameter << parse_text
parse_alternative_separator = lambda do |_, tokens, current|
unless looking_at(tokens, current, TokenType::ALTERNATION)
return 0, nil
end
token = tokens[current]
return 1, [Node.new(NodeType::ALTERNATIVE, nil, token.text, token.start, token.end)]
end
alternative_parsers = [
parse_alternative_separator,
parse_optional,
parse_parameter,
parse_text,
]
parse_alternation = lambda do |expr, tokens, current|
previous = current - 1
unless looking_at_any(tokens, previous, [TokenType::START_OF_LINE, TokenType::WHITE_SPACE, TokenType::END_PARAMETER])
return 0, nil
end
consumed, ast = parse_tokens_until(expr, alternative_parsers, tokens, current, [TokenType::WHITE_SPACE, TokenType::END_OF_LINE, TokenType::BEGIN_PARAMETER])
sub_current = current + consumed
unless ast.map { |astNode| astNode.type }.include? NodeType::ALTERNATIVE
return 0, nil
end
start = tokens[current].start
_end = tokens[sub_current].start
return consumed, [Node.new(NodeType::ALTERNATION, split_alternatives(start, _end, ast), nil, start, _end)]
end
parse_cucumber_expression = parse_between(
NodeType::EXPRESSION,
TokenType::START_OF_LINE,
TokenType::END_OF_LINE,
[parse_alternation, parse_optional, parse_parameter, parse_text]
)
tokenizer = CucumberExpressionTokenizer.new
tokens = tokenizer.tokenize(expression)
_, ast = parse_cucumber_expression.call(expression, tokens, 0)
ast[0]
end
|