srl_ruby 0.4.5 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +298 -23
- data/CHANGELOG.md +41 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/Rakefile +3 -0
- data/appveyor.yml +14 -12
- data/bin/srl2ruby +13 -9
- data/bin/srl2ruby_cli_parser.rb +3 -3
- data/features/lib/step_definitions/srl_testing_steps.rb +2 -0
- data/features/lib/support/env..rb +2 -0
- data/lib/regex/abstract_method.rb +2 -0
- data/lib/regex/alternation.rb +3 -3
- data/lib/regex/anchor.rb +3 -0
- data/lib/regex/atomic_expression.rb +2 -0
- data/lib/regex/capturing_group.rb +8 -3
- data/lib/regex/char_class.rb +4 -2
- data/lib/regex/char_range.rb +3 -3
- data/lib/regex/char_shorthand.rb +3 -0
- data/lib/regex/character.rb +5 -2
- data/lib/regex/compound_expression.rb +2 -0
- data/lib/regex/concatenation.rb +3 -1
- data/lib/regex/expression.rb +6 -1
- data/lib/regex/lookaround.rb +3 -1
- data/lib/regex/match_option.rb +2 -0
- data/lib/regex/monadic_expression.rb +2 -0
- data/lib/regex/multiplicity.rb +8 -9
- data/lib/regex/non_capturing_group.rb +3 -1
- data/lib/regex/polyadic_expression.rb +2 -0
- data/lib/regex/quantifiable.rb +3 -1
- data/lib/regex/raw_expression.rb +2 -0
- data/lib/regex/repetition.rb +2 -0
- data/lib/regex/wildcard.rb +2 -5
- data/lib/srl_ruby/ast_builder.rb +81 -121
- data/lib/srl_ruby/grammar.rb +80 -92
- data/lib/srl_ruby/regex_repr.rb +2 -0
- data/lib/srl_ruby/tokenizer.rb +10 -4
- data/lib/srl_ruby/version.rb +3 -1
- data/lib/srl_ruby.rb +2 -0
- data/spec/acceptance/srl_test_suite_spec.rb +2 -0
- data/spec/acceptance/support/rule_file_ast_builder.rb +2 -0
- data/spec/acceptance/support/rule_file_grammar.rb +7 -5
- data/spec/acceptance/support/rule_file_nodes.rb +2 -0
- data/spec/acceptance/support/rule_file_parser.rb +2 -0
- data/spec/acceptance/support/rule_file_tokenizer.rb +10 -3
- data/spec/regex/atomic_expression_spec.rb +2 -0
- data/spec/regex/character_spec.rb +16 -6
- data/spec/regex/match_option_spec.rb +2 -0
- data/spec/regex/monadic_expression_spec.rb +2 -0
- data/spec/regex/multiplicity_spec.rb +4 -0
- data/spec/regex/repetition_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/srl_ruby/srl_ruby_spec.rb +2 -0
- data/spec/srl_ruby/tokenizer_spec.rb +2 -0
- data/spec/srl_ruby_spec.rb +8 -6
- data/srl_ruby.gemspec +6 -4
- metadata +13 -14
data/lib/srl_ruby/grammar.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Grammar for SRL (Simple Regex Language)
|
2
4
|
require 'rley' # Load the gem
|
3
5
|
module SrlRuby
|
4
6
|
########################################
|
5
7
|
# SRL grammar
|
6
|
-
builder = Rley::
|
8
|
+
builder = Rley::grammar_builder do
|
7
9
|
# Separators...
|
8
10
|
add_terminals('LPAREN', 'RPAREN', 'COMMA')
|
9
11
|
|
@@ -29,97 +31,83 @@ module SrlRuby
|
|
29
31
|
add_terminals('LAZY')
|
30
32
|
|
31
33
|
# Grammar rules...
|
32
|
-
rule('srl' => 'expression').
|
33
|
-
rule('expression' =>
|
34
|
-
rule('
|
35
|
-
rule('
|
36
|
-
rule('
|
37
|
-
rule('
|
38
|
-
rule('
|
39
|
-
rule('
|
40
|
-
rule('
|
41
|
-
rule('
|
42
|
-
rule('
|
43
|
-
rule('
|
44
|
-
rule('
|
45
|
-
rule('
|
46
|
-
rule('
|
47
|
-
rule('
|
48
|
-
rule('
|
49
|
-
rule('
|
50
|
-
rule('
|
51
|
-
rule('
|
52
|
-
rule('
|
53
|
-
rule('
|
54
|
-
rule('
|
55
|
-
rule('
|
56
|
-
rule('
|
57
|
-
rule('
|
58
|
-
rule('
|
59
|
-
rule('
|
60
|
-
rule('
|
61
|
-
rule('
|
62
|
-
rule('
|
63
|
-
rule('
|
64
|
-
rule('
|
65
|
-
rule('
|
66
|
-
rule('
|
67
|
-
rule('
|
68
|
-
rule('
|
69
|
-
rule('
|
70
|
-
rule('
|
71
|
-
rule('
|
72
|
-
rule('
|
73
|
-
rule('
|
74
|
-
rule('
|
75
|
-
rule('
|
76
|
-
rule('
|
77
|
-
rule('
|
78
|
-
rule('
|
79
|
-
rule('
|
80
|
-
rule('
|
81
|
-
rule('
|
82
|
-
rule('
|
83
|
-
rule('
|
84
|
-
rule('
|
85
|
-
rule('
|
86
|
-
rule('
|
87
|
-
rule('
|
88
|
-
rule('
|
89
|
-
rule('
|
90
|
-
rule('
|
91
|
-
rule('
|
92
|
-
rule('
|
93
|
-
rule('
|
94
|
-
rule('
|
95
|
-
rule('
|
96
|
-
rule('
|
97
|
-
rule('
|
98
|
-
rule('
|
99
|
-
rule('
|
100
|
-
rule('
|
101
|
-
rule('
|
102
|
-
rule('
|
103
|
-
rule('
|
104
|
-
rule('
|
105
|
-
rule('
|
106
|
-
rule('
|
107
|
-
rule('
|
108
|
-
rule('
|
109
|
-
rule('quantifier' => 'ONCE').as 'once'
|
110
|
-
rule('quantifier' => 'TWICE').as 'twice'
|
111
|
-
rule('quantifier' => %w[EXACTLY count TIMES]).as 'exactly'
|
112
|
-
rule('quantifier' => %w[BETWEEN count AND count times_suffix]).as 'between_and'
|
113
|
-
rule('quantifier' => 'OPTIONAL').as 'optional'
|
114
|
-
rule('quantifier' => %w[ONCE OR MORE]).as 'once_or_more'
|
115
|
-
rule('quantifier' => %w[NEVER OR MORE]).as 'never_or_more'
|
116
|
-
rule('quantifier' => %w[AT LEAST count TIMES]).as 'at_least'
|
117
|
-
rule('digit_or_number' => 'DIGIT').as 'digit_keyword'
|
118
|
-
rule('digit_or_number' => 'NUMBER').as 'number_keyword'
|
119
|
-
rule('count' => 'DIGIT_LIT').as 'single_digit'
|
120
|
-
rule('count' => 'INTEGER').as 'integer_count'
|
121
|
-
rule('times_suffix' => 'TIMES').as 'times_keyword'
|
122
|
-
rule('times_suffix' => []).as 'times_dropped'
|
34
|
+
rule('srl' => 'expression').tag 'start_rule'
|
35
|
+
rule('expression' => 'pattern flags?').tag 'flagged_expr'
|
36
|
+
rule('pattern' => 'sub_pattern (separator sub_pattern)*').tag 'pattern_sequence'
|
37
|
+
rule('sub_pattern' => 'quantifiable').tag 'quantifiable_sub_pattern'
|
38
|
+
rule('sub_pattern' => 'assertion').tag 'assertion_sub_pattern'
|
39
|
+
rule('separator' => 'COMMA?')
|
40
|
+
rule('flags' => '(separator single_flag)+').tag 'flag_sequence'
|
41
|
+
rule('single_flag' => 'CASE INSENSITIVE').tag 'case_insensitive'
|
42
|
+
rule('single_flag' => 'MULTI LINE').tag 'multi_line'
|
43
|
+
rule('single_flag' => 'ALL LAZY').tag 'all_lazy'
|
44
|
+
rule('quantifiable' => 'begin_anchor? anchorable end_anchor?').tag 'quantifiable'
|
45
|
+
rule('begin_anchor' => 'STARTS WITH').tag 'starts_with'
|
46
|
+
rule('begin_anchor' => 'BEGIN WITH').tag 'begin_with'
|
47
|
+
rule('end_anchor' => 'separator MUST END').tag 'end_anchor'
|
48
|
+
rule('anchorable' => 'assertable').tag 'simple_anchorable'
|
49
|
+
rule('assertion' => 'IF NOT? FOLLOWED BY assertable').tag 'if_followed'
|
50
|
+
rule('assertion' => 'IF NOT? ALREADY HAD assertable').tag 'if_had'
|
51
|
+
rule('assertable' => 'term quantifier?').tag 'assertable'
|
52
|
+
rule('term' => 'atom').tag 'atom_term'
|
53
|
+
rule('term' => 'alternation').tag 'alternation_term'
|
54
|
+
rule('term' => 'grouping').tag 'grouping_term'
|
55
|
+
rule('term' => 'capturing_group').tag 'capturing_group_atom'
|
56
|
+
rule('atom' => 'letter_range').tag 'letter_range_atom'
|
57
|
+
rule('atom' => 'digit_range').tag 'digit_range_atom'
|
58
|
+
rule('atom' => 'character_class').tag 'character_class_atom'
|
59
|
+
rule('atom' => 'special_char').tag 'special_char_atom'
|
60
|
+
rule('atom' => 'literal').tag 'literal_atom'
|
61
|
+
rule('atom' => 'raw').tag 'raw_atom'
|
62
|
+
rule('letter_range' => 'LETTER FROM LETTER_LIT TO LETTER_LIT').tag 'lowercase_from_to'
|
63
|
+
rule('letter_range' => 'UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT').tag 'uppercase_from_to'
|
64
|
+
rule('letter_range' => 'LETTER').tag 'any_lowercase'
|
65
|
+
rule('letter_range' => 'UPPERCASE LETTER').tag 'any_uppercase'
|
66
|
+
rule('digit_range' => 'digit_or_number FROM DIGIT_LIT TO DIGIT_LIT').tag 'digits_from_to'
|
67
|
+
rule('character_class' => 'ANY CHARACTER').tag 'any_character'
|
68
|
+
rule('character_class' => 'NO CHARACTER').tag 'no_character'
|
69
|
+
rule('character_class' => 'digit_or_number').tag 'digit'
|
70
|
+
rule('character_class' => 'NO DIGIT').tag 'non_digit'
|
71
|
+
rule('character_class' => 'WHITESPACE').tag 'whitespace'
|
72
|
+
rule('character_class' => 'NO WHITESPACE').tag 'no_whitespace'
|
73
|
+
rule('character_class' => 'ANYTHING').tag 'anything'
|
74
|
+
rule('character_class' => 'ONE OF cclass').tag 'one_of'
|
75
|
+
rule('character_class' => 'NONE OF cclass').tag 'none_of'
|
76
|
+
rule('cclass' => 'STRING_LIT').tag 'quoted_cclass' # Preferred syntax
|
77
|
+
rule('cclass' => 'INTEGER').tag 'digits_cclass'
|
78
|
+
rule('cclass' => 'IDENTIFIER').tag 'identifier_cclass'
|
79
|
+
rule('cclass' => 'CHAR_CLASS').tag 'unquoted_cclass'
|
80
|
+
rule('special_char' => 'TAB').tag 'tab'
|
81
|
+
rule('special_char' => 'VERTICAL TAB').tag 'vtab'
|
82
|
+
rule('special_char' => 'BACKSLASH').tag 'backslash'
|
83
|
+
rule('special_char' => 'NEW LINE').tag 'new_line'
|
84
|
+
rule('special_char' => 'CARRIAGE RETURN').tag 'carriage_return'
|
85
|
+
rule('special_char' => 'WORD').tag 'word'
|
86
|
+
rule('special_char' => 'NO WORD').tag 'no_word'
|
87
|
+
rule('literal' => 'LITERALLY STRING_LIT').tag 'literally'
|
88
|
+
rule('raw' => 'RAW STRING_LIT').tag 'raw_literal'
|
89
|
+
rule('alternation' => 'any_or_either OF LPAREN alternatives RPAREN').tag 'any_of'
|
90
|
+
rule('alternatives' => 'alternatives separator quantifiable').tag 'alternative_list'
|
91
|
+
rule('alternatives' => 'quantifiable').tag 'simple_alternative'
|
92
|
+
rule('any_or_either' => 'ANY').tag 'any_keyword'
|
93
|
+
rule('any_or_either' => 'EITHER').tag 'either_keyword'
|
94
|
+
rule('grouping' => 'LPAREN pattern RPAREN').tag 'grouping_parenthenses'
|
95
|
+
rule('capturing_group' => 'CAPTURE assertable (UNTIL assertable)?').tag 'capture'
|
96
|
+
rule('capturing_group' => 'CAPTURE assertable AS var_name (UNTIL assertable)?').tag 'named_capture'
|
97
|
+
rule('var_name' => 'STRING_LIT').tag 'var_name'
|
98
|
+
rule('var_name' => 'IDENTIFIER').tag 'var_ident' # capture name not enclosed between quotes
|
99
|
+
rule('quantifier' => 'ONCE').tag 'once'
|
100
|
+
rule('quantifier' => 'TWICE').tag 'twice'
|
101
|
+
rule('quantifier' => 'EXACTLY count TIMES').tag 'exactly'
|
102
|
+
rule('quantifier' => 'BETWEEN count AND count TIMES?').tag 'between_and'
|
103
|
+
rule('quantifier' => 'OPTIONAL').tag 'optional'
|
104
|
+
rule('quantifier' => 'ONCE OR MORE').tag 'once_or_more'
|
105
|
+
rule('quantifier' => 'NEVER OR MORE').tag 'never_or_more'
|
106
|
+
rule('quantifier' => 'AT LEAST count TIMES').tag 'at_least'
|
107
|
+
rule('digit_or_number' => 'DIGIT').tag 'digit_keyword'
|
108
|
+
rule('digit_or_number' => 'NUMBER').tag 'number_keyword'
|
109
|
+
rule('count' => 'DIGIT_LIT').tag 'single_digit'
|
110
|
+
rule('count' => 'INTEGER').tag 'integer_count'
|
123
111
|
end
|
124
112
|
|
125
113
|
# And now build the grammar and make it accessible via a global constant
|
data/lib/srl_ruby/regex_repr.rb
CHANGED
data/lib/srl_ruby/tokenizer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# File: srl_tokenizer.rb
|
2
4
|
# Tokenizer for SRL (Simple Regex Language)
|
3
5
|
require 'strscan'
|
@@ -15,10 +17,14 @@ module SrlRuby
|
|
15
17
|
# Delimiters: parentheses '(' and ')'
|
16
18
|
# Separators: comma (optional)
|
17
19
|
class Tokenizer
|
20
|
+
# @return [StringScanner]
|
18
21
|
attr_reader(:scanner)
|
22
|
+
|
23
|
+
# @return [Integer] current line number
|
19
24
|
attr_reader(:lineno)
|
25
|
+
|
26
|
+
# @return [Integer] offset of start of current line within input
|
20
27
|
attr_reader(:line_start)
|
21
|
-
# attr_reader(:column)
|
22
28
|
|
23
29
|
@@lexeme2name = {
|
24
30
|
'(' => 'LPAREN',
|
@@ -84,7 +90,7 @@ module SrlRuby
|
|
84
90
|
WHITESPACE
|
85
91
|
WITH
|
86
92
|
WORD
|
87
|
-
].map { |x| [x, x] }
|
93
|
+
].map { |x| [x, x] }.to_h
|
88
94
|
|
89
95
|
class ScanError < StandardError; end
|
90
96
|
|
@@ -151,9 +157,9 @@ module SrlRuby
|
|
151
157
|
col = scanner.pos - aLexeme.size - @line_start + 1
|
152
158
|
pos = Rley::Lexical::Position.new(@lineno, col)
|
153
159
|
token = Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
|
154
|
-
rescue StandardError =>
|
160
|
+
rescue StandardError => e
|
155
161
|
puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
|
156
|
-
raise
|
162
|
+
raise e
|
157
163
|
end
|
158
164
|
|
159
165
|
return token
|
data/lib/srl_ruby/version.rb
CHANGED
data/lib/srl_ruby.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# File: rule_file_grammar.rb
|
2
4
|
require 'rley' # Load the Rley gem
|
3
5
|
|
@@ -5,20 +7,20 @@ require 'rley' # Load the Rley gem
|
|
5
7
|
# [File format](https://github.com/SimpleRegex/Test-Rules/blob/master/README.md)
|
6
8
|
########################################
|
7
9
|
# Define a grammar for basic arithmetical expressions
|
8
|
-
builder = Rley::
|
10
|
+
builder = Rley::grammar_builder do
|
9
11
|
# Punctuation
|
10
12
|
add_terminals('COLON', 'DASH')
|
11
13
|
|
12
14
|
# Keywords
|
13
15
|
add_terminals('CAPTURE', 'FOR')
|
14
|
-
add_terminals('MATCH
|
16
|
+
add_terminals('MATCH', 'NO', 'SRL')
|
15
17
|
|
16
18
|
# Literals
|
17
19
|
add_terminals('INTEGER', 'STRING_LIT')
|
18
20
|
add_terminals('IDENTIFIER', 'SRL_SOURCE')
|
19
21
|
|
20
22
|
rule('rule_file' => 'srl_heading srl_tests').as 'start_rule'
|
21
|
-
rule('srl_heading' => 'SRL
|
23
|
+
rule('srl_heading' => 'SRL SRL_SOURCE').as 'srl_source'
|
22
24
|
rule('srl_tests' => 'srl_tests single_test').as 'test_list'
|
23
25
|
rule('srl_tests' => 'single_test').as 'one_test'
|
24
26
|
rule('single_test' => 'atomic_test').as 'single_atomic_test'
|
@@ -26,8 +28,8 @@ builder = Rley::Syntax::GrammarBuilder.new do
|
|
26
28
|
rule('atomic_test' => 'match_test').as 'atomic_match'
|
27
29
|
rule('atomic_test' => 'no_match_test').as 'atomic_no_match'
|
28
30
|
rule('compound_test' => 'capture_test').as 'compound_capture'
|
29
|
-
rule('match_test' => 'MATCH
|
30
|
-
rule('no_match_test' => 'NO MATCH
|
31
|
+
rule('match_test' => 'MATCH STRING_LIT').as 'match_string'
|
32
|
+
rule('no_match_test' => 'NO MATCH STRING_LIT').as 'no_match_string'
|
31
33
|
rule('capture_test' => 'capture_heading capture_expectations').as 'capture_test'
|
32
34
|
rule('capture_heading' => 'CAPTURE FOR STRING_LIT COLON').as 'capture_string'
|
33
35
|
rule('capture_expectations' => 'capture_expectations single_expectation').as 'assertion_list'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# File: rule_tokenizer.rb
|
2
4
|
# Tokenizer for SimpleRegex Test-Rule files
|
3
5
|
# [File format](https://github.com/SimpleRegex/Test-Rules/blob/master/README.md)
|
@@ -14,8 +16,13 @@ module Acceptance
|
|
14
16
|
# Delimiters: parentheses '(' and ')'
|
15
17
|
# Separators: comma (optional)
|
16
18
|
class RuleFileTokenizer
|
19
|
+
# @return [StringScanner]
|
17
20
|
attr_reader(:scanner)
|
21
|
+
|
22
|
+
# @return [Integer] current line number
|
18
23
|
attr_reader(:lineno)
|
24
|
+
|
25
|
+
# @return [Integer] offset of start of current line within input
|
19
26
|
attr_reader(:line_start)
|
20
27
|
|
21
28
|
# Can be :default, :expecting_srl
|
@@ -80,7 +87,7 @@ module Acceptance
|
|
80
87
|
elsif (lexeme = scanner.scan(/[0-9]+/))
|
81
88
|
token = build_token('INTEGER', lexeme)
|
82
89
|
elsif (lexeme = scanner.scan(/srl:|match:/))
|
83
|
-
token = build_token(@@keywords[lexeme], lexeme)
|
90
|
+
token = build_token(@@keywords[lexeme].chop, lexeme.chop)
|
84
91
|
@state = :expecting_srl if lexeme == 'srl:'
|
85
92
|
elsif (lexeme = scanner.scan(/[a-zA-Z_][a-zA-Z0-9_]*/))
|
86
93
|
keyw = @@keywords[lexeme]
|
@@ -111,9 +118,9 @@ module Acceptance
|
|
111
118
|
col = scanner.pos - aLexeme.size - @line_start + 1
|
112
119
|
pos = Rley::Lexical::Position.new(@lineno, col)
|
113
120
|
token = Rley::Lexical::Token.new(aLexeme, aSymbolName, pos)
|
114
|
-
rescue StandardError =>
|
121
|
+
rescue StandardError => e
|
115
122
|
puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
|
116
|
-
raise
|
123
|
+
raise e
|
117
124
|
end
|
118
125
|
|
119
126
|
return token
|
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# File: character_spec.rb
|
2
4
|
require_relative '../spec_helper' # Use the RSpec test framework
|
3
5
|
require_relative '../../lib/regex/character'
|
4
6
|
|
5
7
|
module Regex # Open this namespace, to get rid of scope qualifiers
|
6
8
|
describe Character do
|
9
|
+
# rubocop: disable Lint/ConstantDefinitionInBlock
|
10
|
+
|
7
11
|
# This constant holds an arbitrary selection of characters
|
8
12
|
SampleChars = [?a, ?\0, ?\u0107].freeze
|
9
13
|
|
@@ -85,6 +89,8 @@ module Regex # Open this namespace, to get rid of scope qualifiers
|
|
85
89
|
|
86
90
|
# Try with our escape sequence samples
|
87
91
|
(SampleDigrams + SampleNumEscs).each do |escape_seq|
|
92
|
+
|
93
|
+
# Build a string from escape sequence literal
|
88
94
|
expectation = String.class_eval(%Q|"#{escape_seq}"|, __FILE__, __LINE__)
|
89
95
|
new_ch = Character.new(escape_seq).to_str
|
90
96
|
new_ch == expectation
|
@@ -109,11 +115,20 @@ module Regex # Open this namespace, to get rid of scope qualifiers
|
|
109
115
|
|
110
116
|
# Try with our escape sequence samples
|
111
117
|
(SampleDigrams + SampleNumEscs).each do |escape_seq|
|
118
|
+
|
119
|
+
# Get ordinal value of given escape sequence
|
112
120
|
expectation = String.class_eval(%Q|"#{escape_seq}".ord()|, __FILE__, __LINE__)
|
113
121
|
expect(Character.new(escape_seq).codepoint).to eq(expectation)
|
114
122
|
end
|
115
123
|
end
|
116
124
|
|
125
|
+
# Create a module that re-defines the existing to_s method
|
126
|
+
module Tweak_to_s
|
127
|
+
def to_s # Overwrite the existing to_s method
|
128
|
+
?\u03a3
|
129
|
+
end
|
130
|
+
end # module
|
131
|
+
|
117
132
|
it 'should known whether it is equal to another Object' do
|
118
133
|
newOne = Character.new(?\u03a3)
|
119
134
|
|
@@ -145,12 +160,6 @@ module Regex # Open this namespace, to get rid of scope qualifiers
|
|
145
160
|
expect(simulator).to receive(:to_s).and_return(?\u03a3)
|
146
161
|
expect(newOne).to eq(simulator)
|
147
162
|
|
148
|
-
# Create a module that re-defines the existing to_s method
|
149
|
-
module Tweak_to_s
|
150
|
-
def to_s # Overwrite the existing to_s method
|
151
|
-
?\u03a3
|
152
|
-
end
|
153
|
-
end # module
|
154
163
|
weird = Object.new
|
155
164
|
weird.extend(Tweak_to_s)
|
156
165
|
expect(newOne).to eq(weird)
|
@@ -164,6 +173,7 @@ module Regex # Open this namespace, to get rid of scope qualifiers
|
|
164
173
|
expect(ch2.explain).to eq("the character '\u03a3'")
|
165
174
|
end
|
166
175
|
end # context
|
176
|
+
# rubocop: enable Lint/ConstantDefinitionInBlock
|
167
177
|
end # describe
|
168
178
|
end # module
|
169
179
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# File: multiplicity_spec.rb
|
2
4
|
|
3
5
|
require_relative '../spec_helper' # Use the RSpec test framework
|
@@ -21,6 +23,7 @@ module Regex # This module is used as a namespace
|
|
21
23
|
end
|
22
24
|
|
23
25
|
context 'Provided services' do
|
26
|
+
# rubocop: disable Style/CombinableLoops
|
24
27
|
it 'should know its text representation' do
|
25
28
|
policy2text = { greedy: '', lazy: '?', possessive: '+' }
|
26
29
|
|
@@ -71,6 +74,7 @@ module Regex # This module is used as a namespace
|
|
71
74
|
end
|
72
75
|
end
|
73
76
|
end
|
77
|
+
# rubocop: enable Style/CombinableLoops
|
74
78
|
end
|
75
79
|
end
|
76
80
|
end # module
|
data/spec/spec_helper.rb
CHANGED
data/spec/srl_ruby_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper' # Use the RSpec framework
|
2
4
|
require_relative '../lib/srl_ruby'
|
3
5
|
|
@@ -224,7 +226,7 @@ SRL
|
|
224
226
|
let(:prefix) { 'letter from p to t ' }
|
225
227
|
|
226
228
|
it "should parse 'once' syntax" do
|
227
|
-
regexp = SrlRuby.parse(prefix
|
229
|
+
regexp = SrlRuby.parse("#{prefix}once")
|
228
230
|
expect(regexp.source).to eq('[p-t]{1}')
|
229
231
|
end
|
230
232
|
|
@@ -244,26 +246,26 @@ SRL
|
|
244
246
|
end
|
245
247
|
|
246
248
|
it "should parse 'between ... and ... times' syntax" do
|
247
|
-
regexp = SrlRuby.parse(prefix
|
249
|
+
regexp = SrlRuby.parse("#{prefix}between 2 and 4 times")
|
248
250
|
expect(regexp.source).to eq('[p-t]{2,4}')
|
249
251
|
|
250
252
|
# Dropping 'times' keyword is a shorter alternative syntax
|
251
|
-
regexp = SrlRuby.parse(prefix
|
253
|
+
regexp = SrlRuby.parse("#{prefix}between 2 and 4")
|
252
254
|
expect(regexp.source).to eq('[p-t]{2,4}')
|
253
255
|
end
|
254
256
|
|
255
257
|
it "should parse 'once or more' syntax" do
|
256
|
-
regexp = SrlRuby.parse(prefix
|
258
|
+
regexp = SrlRuby.parse("#{prefix}once or more")
|
257
259
|
expect(regexp.source).to eq('[p-t]+')
|
258
260
|
end
|
259
261
|
|
260
262
|
it "should parse 'never or more' syntax" do
|
261
|
-
regexp = SrlRuby.parse(prefix
|
263
|
+
regexp = SrlRuby.parse("#{prefix}never or more")
|
262
264
|
expect(regexp.source).to eq('[p-t]*')
|
263
265
|
end
|
264
266
|
|
265
267
|
it "should parse 'at least ... times' syntax" do
|
266
|
-
regexp = SrlRuby.parse(prefix
|
268
|
+
regexp = SrlRuby.parse("#{prefix}at least 10 times")
|
267
269
|
expect(regexp.source).to eq('[p-t]{10,}')
|
268
270
|
end
|
269
271
|
end # context
|
data/srl_ruby.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path('../lib', __FILE__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
require 'srl_ruby/version'
|
@@ -63,14 +65,14 @@ SUMMARY
|
|
63
65
|
spec.require_paths = ['lib']
|
64
66
|
PkgExtending.pkg_files(spec)
|
65
67
|
PkgExtending.pkg_documentation(spec)
|
66
|
-
spec.required_ruby_version = '>= 2.
|
68
|
+
spec.required_ruby_version = '>= 2.5.0'
|
67
69
|
|
68
70
|
# Runtime dependencies
|
69
|
-
spec.add_dependency 'rley', '~> 0.
|
71
|
+
spec.add_dependency 'rley', '~> 0.8.08'
|
70
72
|
|
71
73
|
# Development dependencies
|
72
|
-
spec.add_development_dependency 'bundler', '~>
|
74
|
+
spec.add_development_dependency 'bundler', '~> 2.2.0'
|
73
75
|
spec.add_development_dependency 'cucumber', '>= 2.2.0'
|
74
|
-
spec.add_development_dependency 'rake', '~>
|
76
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
75
77
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
76
78
|
end
|