srl_ruby 0.4.5 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +298 -23
  3. data/CHANGELOG.md +41 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +1 -1
  7. data/Rakefile +3 -0
  8. data/appveyor.yml +14 -12
  9. data/bin/srl2ruby +13 -9
  10. data/bin/srl2ruby_cli_parser.rb +3 -3
  11. data/features/lib/step_definitions/srl_testing_steps.rb +2 -0
  12. data/features/lib/support/env..rb +2 -0
  13. data/lib/regex/abstract_method.rb +2 -0
  14. data/lib/regex/alternation.rb +3 -3
  15. data/lib/regex/anchor.rb +3 -0
  16. data/lib/regex/atomic_expression.rb +2 -0
  17. data/lib/regex/capturing_group.rb +8 -3
  18. data/lib/regex/char_class.rb +4 -2
  19. data/lib/regex/char_range.rb +3 -3
  20. data/lib/regex/char_shorthand.rb +3 -0
  21. data/lib/regex/character.rb +5 -2
  22. data/lib/regex/compound_expression.rb +2 -0
  23. data/lib/regex/concatenation.rb +3 -1
  24. data/lib/regex/expression.rb +6 -1
  25. data/lib/regex/lookaround.rb +3 -1
  26. data/lib/regex/match_option.rb +2 -0
  27. data/lib/regex/monadic_expression.rb +2 -0
  28. data/lib/regex/multiplicity.rb +8 -9
  29. data/lib/regex/non_capturing_group.rb +3 -1
  30. data/lib/regex/polyadic_expression.rb +2 -0
  31. data/lib/regex/quantifiable.rb +3 -1
  32. data/lib/regex/raw_expression.rb +2 -0
  33. data/lib/regex/repetition.rb +2 -0
  34. data/lib/regex/wildcard.rb +2 -5
  35. data/lib/srl_ruby/ast_builder.rb +81 -121
  36. data/lib/srl_ruby/grammar.rb +80 -92
  37. data/lib/srl_ruby/regex_repr.rb +2 -0
  38. data/lib/srl_ruby/tokenizer.rb +10 -4
  39. data/lib/srl_ruby/version.rb +3 -1
  40. data/lib/srl_ruby.rb +2 -0
  41. data/spec/acceptance/srl_test_suite_spec.rb +2 -0
  42. data/spec/acceptance/support/rule_file_ast_builder.rb +2 -0
  43. data/spec/acceptance/support/rule_file_grammar.rb +7 -5
  44. data/spec/acceptance/support/rule_file_nodes.rb +2 -0
  45. data/spec/acceptance/support/rule_file_parser.rb +2 -0
  46. data/spec/acceptance/support/rule_file_tokenizer.rb +10 -3
  47. data/spec/regex/atomic_expression_spec.rb +2 -0
  48. data/spec/regex/character_spec.rb +16 -6
  49. data/spec/regex/match_option_spec.rb +2 -0
  50. data/spec/regex/monadic_expression_spec.rb +2 -0
  51. data/spec/regex/multiplicity_spec.rb +4 -0
  52. data/spec/regex/repetition_spec.rb +2 -0
  53. data/spec/spec_helper.rb +2 -0
  54. data/spec/srl_ruby/srl_ruby_spec.rb +2 -0
  55. data/spec/srl_ruby/tokenizer_spec.rb +2 -0
  56. data/spec/srl_ruby_spec.rb +8 -6
  57. data/srl_ruby.gemspec +6 -4
  58. metadata +13 -14
@@ -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::Syntax::GrammarBuilder.new do
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').as 'start_rule'
33
- rule('expression' => %w[pattern flags]).as 'flagged_expr'
34
- rule('expression' => 'pattern').as 'simple_expr'
35
- rule('pattern' => %w[pattern separator sub_pattern]).as 'pattern_sequence'
36
- rule('pattern' => 'sub_pattern').as 'basic_pattern'
37
- rule('sub_pattern' => 'quantifiable').as 'quantifiable_sub_pattern'
38
- rule('sub_pattern' => 'assertion').as 'assertion_sub_pattern'
39
- rule('separator' => 'COMMA').as 'comma_separator'
40
- rule('separator' => []).as 'void_separator'
41
- rule('flags' => %w[flags separator single_flag]).as 'flag_sequence'
42
- rule('flags' => %w[separator single_flag]).as 'flag_simple'
43
- rule('single_flag' => %w[CASE INSENSITIVE]).as 'case_insensitive'
44
- rule('single_flag' => %w[MULTI LINE]).as 'multi_line'
45
- rule('single_flag' => %w[ALL LAZY]).as 'all_lazy'
46
- rule('quantifiable' => %w[begin_anchor anchorable end_anchor]).as 'pinned_quantifiable'
47
- rule('quantifiable' => %w[begin_anchor anchorable]).as 'begin_anchor_quantifiable'
48
- rule('quantifiable' => %w[anchorable end_anchor]).as 'end_anchor_quantifiable'
49
- rule('quantifiable' => 'anchorable').as 'simple_quantifiable'
50
- rule('begin_anchor' => %w[STARTS WITH]).as 'starts_with'
51
- rule('begin_anchor' => %w[BEGIN WITH]).as 'begin_with'
52
- rule('end_anchor' => %w[separator MUST END]).as 'end_anchor'
53
- rule('anchorable' => 'assertable').as 'simple_anchorable'
54
- rule('assertion' => %w[IF FOLLOWED BY assertable]).as 'if_followed'
55
- rule('assertion' => %w[IF NOT FOLLOWED BY assertable]).as 'if_not_followed'
56
- rule('assertion' => %w[IF ALREADY HAD assertable]).as 'if_had'
57
- rule('assertion' => %w[IF NOT ALREADY HAD assertable]).as 'if_not_had'
58
- rule('assertable' => 'term').as 'simple_assertable'
59
- rule('assertable' => %w[term quantifier]).as 'quantified_assertable'
60
- rule('term' => 'atom').as 'atom_term'
61
- rule('term' => 'alternation').as 'alternation_term'
62
- rule('term' => 'grouping').as 'grouping_term'
63
- rule('term' => 'capturing_group').as 'capturing_group_atom'
64
- rule('atom' => 'letter_range').as 'letter_range_atom'
65
- rule('atom' => 'digit_range').as 'digit_range_atom'
66
- rule('atom' => 'character_class').as 'character_class_atom'
67
- rule('atom' => 'special_char').as 'special_char_atom'
68
- rule('atom' => 'literal').as 'literal_atom'
69
- rule('atom' => 'raw').as 'raw_atom'
70
- rule('letter_range' => %w[LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'lowercase_from_to'
71
- rule('letter_range' => %w[UPPERCASE LETTER FROM LETTER_LIT TO LETTER_LIT]).as 'uppercase_from_to'
72
- rule('letter_range' => 'LETTER').as 'any_lowercase'
73
- rule('letter_range' => %w[UPPERCASE LETTER]).as 'any_uppercase'
74
- rule('digit_range' => %w[digit_or_number FROM DIGIT_LIT TO DIGIT_LIT]).as 'digits_from_to'
75
- rule('character_class' => %w[ANY CHARACTER]).as 'any_character'
76
- rule('character_class' => %w[NO CHARACTER]).as 'no_character'
77
- rule('character_class' => 'digit_or_number').as 'digit'
78
- rule('character_class' => %w[NO DIGIT]).as 'non_digit'
79
- rule('character_class' => 'WHITESPACE').as 'whitespace'
80
- rule('character_class' => %w[NO WHITESPACE]).as 'no_whitespace'
81
- rule('character_class' => 'ANYTHING').as 'anything'
82
- rule('character_class' => %w[ONE OF cclass]).as 'one_of'
83
- rule('character_class' => %w[NONE OF cclass]).as 'none_of'
84
- rule('cclass' => 'STRING_LIT').as 'quoted_cclass' # Preferred syntax
85
- rule('cclass' => 'INTEGER').as 'digits_cclass'
86
- rule('cclass' => 'IDENTIFIER').as 'identifier_cclass'
87
- rule('cclass' => 'CHAR_CLASS').as 'unquoted_cclass'
88
- rule('special_char' => 'TAB').as 'tab'
89
- rule('special_char' => 'VERTICAL TAB').as 'vtab'
90
- rule('special_char' => 'BACKSLASH').as 'backslash'
91
- rule('special_char' => %w[NEW LINE]).as 'new_line'
92
- rule('special_char' => %w[CARRIAGE RETURN]).as 'carriage_return'
93
- rule('special_char' => %w[WORD]).as 'word'
94
- rule('special_char' => %w[NO WORD]).as 'no_word'
95
- rule('literal' => %w[LITERALLY STRING_LIT]).as 'literally'
96
- rule('raw' => 'RAW STRING_LIT').as 'raw_literal'
97
- rule('alternation' => %w[any_or_either OF LPAREN alternatives RPAREN]).as 'any_of'
98
- rule('alternatives' => %w[alternatives separator quantifiable]).as 'alternative_list'
99
- rule('alternatives' => 'quantifiable').as 'simple_alternative'
100
- rule('any_or_either' => 'ANY').as 'any_keyword'
101
- rule('any_or_either' => 'EITHER').as 'either_keyword'
102
- rule('grouping' => %w[LPAREN pattern RPAREN]).as 'grouping_parenthenses'
103
- rule('capturing_group' => %w[CAPTURE assertable]).as 'capture'
104
- rule('capturing_group' => %w[CAPTURE assertable UNTIL assertable]).as 'capture_until'
105
- rule('capturing_group' => %w[CAPTURE assertable AS var_name]).as 'named_capture'
106
- rule('capturing_group' => %w[CAPTURE assertable AS var_name UNTIL assertable]).as 'named_capture_until'
107
- rule('var_name' => 'STRING_LIT').as 'var_name'
108
- rule('var_name' => 'IDENTIFIER').as 'var_ident' # capture name not enclosed between quotes
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../regex/character'
2
4
  require_relative '../regex/char_range'
3
5
  require_relative '../regex/concatenation'
@@ -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] } .to_h
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 => exc
160
+ rescue StandardError => e
155
161
  puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
156
- raise exc
162
+ raise e
157
163
  end
158
164
 
159
165
  return token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SrlRuby
2
- VERSION = '0.4.5'.freeze
4
+ VERSION = '0.4.9'
3
5
  end
data/lib/srl_ruby.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './srl_ruby/version'
2
4
  require_relative './srl_ruby/tokenizer'
3
5
  require_relative './srl_ruby/grammar'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
  require_relative './support/rule_file_parser'
3
5
  require_relative '../../lib/srl_ruby'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'rule_file_nodes'
2
4
 
3
5
  module Acceptance
@@ -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::Syntax::GrammarBuilder.new do
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:', 'NO', 'SRL:')
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: SRL_SOURCE').as 'srl_source'
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: STRING_LIT').as 'match_string'
30
- rule('no_match_test' => 'NO MATCH: STRING_LIT').as 'no_match_string'
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
  # Classes that implement nodes of Abstract Syntax Trees (AST) representing
2
4
  # rule file contents.
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'rule_file_tokenizer'
2
4
  require_relative 'rule_file_grammar'
3
5
  require_relative 'rule_file_ast_builder'
@@ -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 => exc
121
+ rescue StandardError => e
115
122
  puts "Failing with '#{aSymbolName}' and '#{aLexeme}'"
116
- raise exc
123
+ raise e
117
124
  end
118
125
 
119
126
  return token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: atomic_expression_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/atomic_expression'
@@ -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: match_option_spec.rb
2
4
 
3
5
  require_relative '../spec_helper' # Use the RSpec test framework
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: monadic_expression_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/monadic_expression'
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # File: repetition_spec.rb
2
4
  require_relative '../spec_helper' # Use the RSpec test framework
3
5
  require_relative '../../lib/regex/repetition'
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/setup'
2
4
  require 'rspec' # Use the RSpec framework
3
5
  require_relative '../lib/srl_ruby'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
 
3
5
  RSpec.describe SrlRuby do
@@ -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/tokenizer' # Load the class under test
3
5
 
@@ -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 + 'once')
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 + 'between 2 and 4 times')
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 + 'between 2 and 4')
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 + 'once or more')
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 + 'never or more')
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 + 'at least 10 times')
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.1.0'
68
+ spec.required_ruby_version = '>= 2.5.0'
67
69
 
68
70
  # Runtime dependencies
69
- spec.add_dependency 'rley', '~> 0.7.00'
71
+ spec.add_dependency 'rley', '~> 0.8.08'
70
72
 
71
73
  # Development dependencies
72
- spec.add_development_dependency 'bundler', '~> 1.16'
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', '~> 10.0'
76
+ spec.add_development_dependency 'rake', '~> 12.0'
75
77
  spec.add_development_dependency 'rspec', '~> 3.0'
76
78
  end